Jakarta EE 9 migration

Upgrades many dependency declarations; removes old EJB 2.x support and outdated Servlet-based integrations (Commons FileUpload, FreeMarker JSP support, Tiles).

Closes gh-22093
Closes gh-25354
Closes gh-26185
Closes gh-27423
See gh-27424
This commit is contained in:
Juergen Hoeller 2021-09-17 09:14:07 +02:00
parent 5822f1bf85
commit d84ca2ba90
1291 changed files with 4992 additions and 25322 deletions

View File

@ -32,7 +32,7 @@ configure(allprojects) { project ->
mavenBom "io.projectreactor:reactor-bom:2020.0.11"
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR10"
mavenBom "io.rsocket:rsocket-bom:1.1.1"
mavenBom "org.eclipse.jetty:jetty-bom:9.4.43.v20210629"
mavenBom "org.eclipse.jetty:jetty-bom:11.0.6"
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.30"
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.2"
mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.2.2"
@ -83,14 +83,10 @@ configure(allprojects) { project ->
exclude group: "xpp3", name: "xpp3_min"
exclude group: "xmlpull", name: "xmlpull"
}
dependency "org.apache.johnzon:johnzon-jsonb:1.2.10"
dependency "org.eclipse:yasson:2.0.2"
dependency("org.codehaus.jettison:jettison:1.3.8") {
exclude group: "stax", name: "stax-api"
}
dependencySet(group: 'org.jibx', version: '1.3.3') {
entry 'jibx-bind'
entry 'jibx-run'
}
dependency "org.ogce:xpp3:1.1.6"
dependency "org.yaml:snakeyaml:1.29"
@ -108,7 +104,6 @@ configure(allprojects) { project ->
}
entry 'activemq-stomp'
}
dependency "org.apache.bcel:bcel:6.0"
dependency "org.apache.commons:commons-pool2:2.9.0"
dependencySet(group: 'org.apache.derby', version: '10.14.2.0') {
entry 'derby'
@ -119,35 +114,28 @@ configure(allprojects) { project ->
dependency "org.freemarker:freemarker:2.3.31"
dependency "org.hsqldb:hsqldb:2.5.2"
dependency "org.quartz-scheduler:quartz:2.3.2"
dependency "org.codehaus.fabric3.api:commonj:1.1.0"
dependency "net.sf.ehcache:ehcache:2.10.6"
dependency "org.ehcache:jcache:1.0.1"
dependency "org.ehcache:ehcache:3.4.0"
dependency "org.hibernate:hibernate-core:5.5.7.Final"
dependency "org.hibernate:hibernate-validator:6.2.0.Final"
dependency "org.hibernate:hibernate-core-jakarta:5.5.7.Final"
dependency "org.hibernate:hibernate-validator:7.0.1.Final"
dependency "org.webjars:webjars-locator-core:0.47"
dependency "org.webjars:underscorejs:1.8.3"
dependencySet(group: 'org.apache.tomcat', version: '9.0.52') {
dependencySet(group: 'org.apache.tomcat', version: '10.0.11') {
entry 'tomcat-util'
entry('tomcat-websocket') {
exclude group: "org.apache.tomcat", name: "tomcat-websocket-api"
exclude group: "org.apache.tomcat", name: "tomcat-servlet-api"
}
}
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.52') {
dependencySet(group: 'org.apache.tomcat.embed', version: '10.0.11') {
entry 'tomcat-embed-core'
entry 'tomcat-embed-websocket'
}
dependencySet(group: 'io.undertow', version: '2.2.10.Final') {
entry 'undertow-core'
entry('undertow-websockets-jsr') {
exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec"
}
entry('undertow-servlet') {
exclude group: "org.jboss.spec.javax.servlet", name: "jboss-servlet-api_3.1_spec"
exclude group: "org.jboss.spec.javax.annotation", name: "jboss-annotations-api_1.2_spec"
}
entry('undertow-servlet-jakartaee9')
entry('undertow-websockets-jsr-jakartaee9')
}
dependencySet(group: 'com.squareup.okhttp3', version: '3.14.9') {
@ -162,15 +150,12 @@ configure(allprojects) { project ->
}
dependency 'org.apache.httpcomponents.client5:httpclient5:5.1'
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.1.1'
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.9"
dependency "org.eclipse.jetty:jetty-reactive-httpclient:3.0.4"
dependency "org.jruby:jruby:9.2.19.0"
dependency "org.python:jython-standalone:2.7.1"
dependency "org.mozilla:rhino:1.7.11"
dependency "commons-fileupload:commons-fileupload:1.4"
dependency "org.synchronoss.cloud:nio-multipart-parser:1.1.0"
dependency("org.dom4j:dom4j:2.1.3") {
exclude group: "jaxen", name: "jaxen"
exclude group: "net.java.dev.msv", name: "xsdlib"
@ -218,69 +203,50 @@ configure(allprojects) { project ->
dependency "org.skyscreamer:jsonassert:1.5.0"
dependency "com.jayway.jsonpath:json-path:2.6.0"
dependency "org.bouncycastle:bcpkix-jdk15on:1.66"
dependencySet(group: 'org.apache.tiles', version: '3.0.8') {
entry 'tiles-api'
entry('tiles-core', withoutJclOverSlf4j)
entry('tiles-servlet', withoutJclOverSlf4j)
entry('tiles-jsp', withoutJclOverSlf4j)
entry('tiles-el', withoutJclOverSlf4j)
entry('tiles-extras') {
exclude group: "org.springframework", name: "spring-web"
exclude group: "org.slf4j", name: "jcl-over-slf4j"
}
}
dependency("org.apache.taglibs:taglibs-standard-jstlel:1.2.5") {
exclude group: "org.apache.taglibs", name: "taglibs-standard-spec"
}
dependency "com.ibm.websphere:uow:6.0.2.17"
dependency "com.jamonapi:jamon:2.82"
dependency "joda-time:joda-time:2.10.10"
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.9"
dependency "org.javamoney:moneta:1.3"
dependency "com.sun.activation:javax.activation:1.2.0"
dependency "com.sun.mail:javax.mail:1.6.2"
dependencySet(group: 'com.sun.xml.bind', version: '2.3.0.1') {
dependency "javax.cache:cache-api:1.1.1"
dependency "javax.money:money-api:1.1"
dependency "org.javamoney:moneta:1.4.2"
dependency "jakarta.activation:jakarta.activation-api:2.0.1"
dependency "jakarta.annotation:jakarta.annotation-api:2.0.0"
dependency "jakarta.ejb:jakarta.ejb-api:4.0.0"
dependency "jakarta.el:jakarta.el-api:4.0.0"
dependency "jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api:2.0.0"
dependency "jakarta.faces:jakarta.faces-api:3.0.0"
dependency "jakarta.inject:jakarta.inject-api:2.0.0"
dependency "jakarta.inject:jakarta.inject-tck:2.0.1"
dependency "jakarta.interceptor:jakarta.interceptor-api:2.0.0"
dependency "jakarta.jms:jakarta.jms-api:3.0.0"
dependency "jakarta.json:jakarta.json-api:2.0.1"
dependency "jakarta.json.bind:jakarta.json.bind-api:2.0.0"
dependency "jakarta.mail:jakarta.mail-api:2.0.1"
dependency "jakarta.persistence:jakarta.persistence-api:3.0.0"
dependency "jakarta.resource:jakarta.resource-api:2.0.0"
dependency "jakarta.servlet:jakarta.servlet-api:5.0.0"
dependency "jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.0.0"
dependency "jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:2.0.0"
dependency "jakarta.transaction:jakarta.transaction-api:2.0.0"
dependency "jakarta.validation:jakarta.validation-api:3.0.0"
dependency "jakarta.websocket:jakarta.websocket-api:2.0.0"
dependency "jakarta.xml.bind:jakarta.xml.bind-api:3.0.1"
dependency "jakarta.xml.ws:jakarta.xml.ws-api:3.0.1"
dependency "com.sun.activation:jakarta.activation:2.0.1"
dependency "com.sun.mail:jakarta.mail:2.0.1"
dependencySet(group: 'com.sun.xml.bind', version: '3.0.2') {
entry 'jaxb-core'
entry 'jaxb-impl'
entry 'jaxb-xjc'
}
dependency "javax.activation:javax.activation-api:1.2.0"
dependency "javax.annotation:javax.annotation-api:1.3.2"
dependency "javax.cache:cache-api:1.1.0"
dependency "javax.ejb:javax.ejb-api:3.2"
dependency "javax.el:javax.el-api:3.0.1-b04"
dependency "javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0"
dependency "javax.faces:javax.faces-api:2.2"
dependency "javax.inject:javax.inject:1"
dependency "javax.inject:javax.inject-tck:1"
dependency "javax.interceptor:javax.interceptor-api:1.2.2"
dependency "javax.jms:javax.jms-api:2.0.1"
dependency "javax.json:javax.json-api:1.1.4"
dependency "javax.json.bind:javax.json.bind-api:1.0"
dependency "javax.mail:javax.mail-api:1.6.2"
dependency "javax.money:money-api:1.0.3"
dependency "javax.resource:javax.resource-api:1.7.1"
dependency "javax.servlet:javax.servlet-api:4.0.1"
dependency "javax.servlet.jsp:javax.servlet.jsp-api:2.3.2-b02"
dependency "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1"
dependency "javax.transaction:javax.transaction-api:1.3"
dependency "javax.validation:validation-api:2.0.1.Final"
dependency "javax.websocket:javax.websocket-api:1.1"
dependency "javax.xml.bind:jaxb-api:2.3.1"
dependency "javax.xml.ws:jaxws-api:2.3.1"
dependency "org.eclipse.persistence:javax.persistence:2.2.0"
// Substitute for "javax.management:jmxremote_optional:1.0.1_04" which
// is not available on Maven Central
dependency "org.glassfish.external:opendmk_jmxremote_optional_jar:1.0-b01-ea"
dependency "org.glassfish:javax.el:3.0.1-b08"
dependency "org.glassfish.main:javax.jws:4.0-b33"
dependency "org.glassfish.tyrus:tyrus-container-servlet:1.13.1"
dependency "org.glassfish:jakarta.el:4.0.2"
dependency "org.glassfish.tyrus:tyrus-container-servlet:2.0.1"
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:3.0.2"
}
generatedPomCustomization {
enabled = false

View File

@ -15,12 +15,12 @@ dependencies {
testImplementation(project(":spring-test"))
testImplementation(project(":spring-tx"))
testImplementation(project(":spring-web"))
testImplementation("javax.inject:javax.inject")
testImplementation("javax.resource:javax.resource-api")
testImplementation("javax.servlet:javax.servlet-api")
testImplementation("jakarta.inject:jakarta.inject-api")
testImplementation("jakarta.resource:jakarta.resource-api")
testImplementation("jakarta.servlet:jakarta.servlet-api")
testImplementation("org.aspectj:aspectjweaver")
testImplementation("org.hsqldb:hsqldb")
testImplementation("org.hibernate:hibernate-core")
testImplementation("org.hibernate:hibernate-core-jakarta")
}
normalization {

View File

@ -20,8 +20,7 @@ import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import javax.servlet.ServletException;
import jakarta.servlet.ServletException;
import org.junit.jupiter.api.Test;
import org.springframework.aop.support.AopUtils;

View File

@ -21,9 +21,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Named;
import javax.inject.Singleton;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -314,16 +313,16 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
for (String type : annDef.getMetadata().getAnnotationTypes()) {
if (type.equals(javax.inject.Singleton.class.getName())) {
if (type.equals(jakarta.inject.Singleton.class.getName())) {
metadata.setScopeName(BeanDefinition.SCOPE_SINGLETON);
break;
}
else if (annDef.getMetadata().getMetaAnnotationTypes(type).contains(javax.inject.Scope.class.getName())) {
else if (annDef.getMetadata().getMetaAnnotationTypes(type).contains(jakarta.inject.Scope.class.getName())) {
metadata.setScopeName(type.substring(type.length() - 13, type.length() - 6).toLowerCase());
metadata.setScopedProxyMode(scopedProxyMode);
break;
}
else if (type.startsWith("javax.inject")) {
else if (type.startsWith("jakarta.inject")) {
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
}
}
@ -391,14 +390,14 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@javax.inject.Scope
@jakarta.inject.Scope
public @interface RequestScoped {
}
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@javax.inject.Scope
@jakarta.inject.Scope
public @interface SessionScoped {
}

View File

@ -41,9 +41,6 @@ import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jca.context.ResourceAdapterApplicationContext;
import org.springframework.jca.support.SimpleBootstrapContext;
import org.springframework.jca.work.SimpleTaskWorkManager;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.mock.env.MockPropertySource;
import org.springframework.mock.web.MockServletConfig;
@ -535,22 +532,6 @@ public class EnvironmentSystemIntegrationTests {
assertThat(environment.getProperty("pSysProps1")).isEqualTo("pSysProps1Value");
}
@Test
void resourceAdapterApplicationContext() {
ResourceAdapterApplicationContext ctx = new ResourceAdapterApplicationContext(new SimpleBootstrapContext(new SimpleTaskWorkManager()));
assertHasStandardEnvironment(ctx);
registerEnvironmentBeanDefinition(ctx);
ctx.setEnvironment(prodEnv);
ctx.refresh();
assertHasEnvironment(ctx, prodEnv);
assertEnvironmentBeanRegistered(ctx);
assertEnvironmentAwareInvoked(ctx, prodEnv);
}
@Test
void abstractApplicationContextValidatesRequiredPropertiesOnRefresh() {
{

View File

@ -41,7 +41,7 @@
<props>
<prop key="setA*">PROPAGATION_REQUIRED</prop>
<prop key="rollbackOnly">PROPAGATION_REQUIRED</prop>
<prop key="echoException">PROPAGATION_REQUIRED,+javax.servlet.ServletException,-java.lang.Exception</prop>
<prop key="echoException">PROPAGATION_REQUIRED,+jakarta.servlet.ServletException,-java.lang.Exception</prop>
</props>
</property>
</bean>

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -47,7 +47,7 @@ import org.springframework.util.ClassUtils;
* target method needs to implement the same signature, it will have to return
* a temporary Future handle that just passes the return value through
* (like Spring's {@link org.springframework.scheduling.annotation.AsyncResult}
* or EJB 3.1's {@code javax.ejb.AsyncResult}).
* or EJB's {@code jakarta.ejb.AsyncResult}).
*
* <p>When the return type is {@code java.util.concurrent.Future}, any exception thrown
* during the execution can be accessed and managed by the caller. With {@code void}

View File

@ -29,14 +29,14 @@ dependencies {
optional(project(":spring-orm")) // for JPA exception translation support
optional(project(":spring-tx")) // for JPA, @Transactional support
optional("javax.cache:cache-api") // for JCache aspect
optional("javax.transaction:javax.transaction-api") // for @javax.transaction.Transactional support
optional("jakarta.transaction:jakarta.transaction-api") // for @javax.transaction.Transactional support
testImplementation(project(":spring-core")) // for CodeStyleAspect
testImplementation(project(":spring-test"))
testImplementation(testFixtures(project(":spring-context")))
testImplementation(testFixtures(project(":spring-context-support")))
testImplementation(testFixtures(project(":spring-core")))
testImplementation(testFixtures(project(":spring-tx")))
testImplementation("javax.mail:javax.mail-api")
testImplementation("jakarta.mail:jakarta.mail-api")
testCompileOnly("org.aspectj:aspectjrt")
}

View File

@ -27,7 +27,7 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils;
/**
* {@code @Configuration} class that registers the Spring infrastructure beans necessary
* to enable AspectJ-based annotation-driven transaction management for the JTA 1.2
* {@link javax.transaction.Transactional} annotation in addition to Spring's own
* {@link jakarta.transaction.Transactional} annotation in addition to Spring's own
* {@link org.springframework.transaction.annotation.Transactional} annotation.
*
* @author Juergen Hoeller

View File

@ -16,7 +16,7 @@
package org.springframework.transaction.aspectj;
import javax.transaction.Transactional;
import jakarta.transaction.Transactional;
import org.aspectj.lang.annotation.RequiredTypes;
@ -24,7 +24,7 @@ import org.springframework.transaction.annotation.AnnotationTransactionAttribute
/**
* Concrete AspectJ transaction aspect using the JTA 1.2
* {@link javax.transaction.Transactional} annotation.
* {@link jakarta.transaction.Transactional} annotation.
*
* <p>When using this aspect, you <i>must</i> annotate the implementation class
* (and/or methods within that class), <i>not</i> the interface (if any) that
@ -42,10 +42,10 @@ import org.springframework.transaction.annotation.AnnotationTransactionAttribute
*
* @author Stephane Nicoll
* @since 4.2
* @see javax.transaction.Transactional
* @see jakarta.transaction.Transactional
* @see AnnotationTransactionAspect
*/
@RequiredTypes("javax.transaction.Transactional")
@RequiredTypes("jakarta.transaction.Transactional")
public aspect JtaAnnotationTransactionAspect extends AbstractTransactionAspect {
public JtaAnnotationTransactionAspect() {

View File

@ -18,8 +18,7 @@ package org.springframework.transaction.aspectj;
import java.io.IOException;
import javax.transaction.Transactional;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -5,13 +5,13 @@ apply plugin: "kotlin"
dependencies {
api(project(":spring-core"))
optional("javax.inject:javax.inject")
optional("jakarta.inject:jakarta.inject-api")
optional("org.yaml:snakeyaml")
optional("org.codehaus.groovy:groovy-xml")
optional("org.jetbrains.kotlin:kotlin-reflect")
optional("org.jetbrains.kotlin:kotlin-stdlib")
testImplementation(testFixtures(project(":spring-core")))
testImplementation("javax.annotation:javax.annotation-api")
testImplementation("jakarta.annotation:jakarta.annotation-api")
testFixturesApi("org.junit.jupiter:junit-jupiter-api")
testFixturesImplementation("org.assertj:assertj-core")
}

View File

@ -25,7 +25,7 @@ import java.lang.annotation.Target;
/**
* Marks a constructor, field, setter method, or config method as to be autowired by
* Spring's dependency injection facilities. This is an alternative to the JSR-330
* {@link javax.inject.Inject} annotation, adding required-vs-optional semantics.
* {@link jakarta.inject.Inject} annotation, adding required-vs-optional semantics.
*
* <h3>Autowired Constructors</h3>
* <p>Only one constructor of any given bean class may declare this annotation with the

View File

@ -75,7 +75,7 @@ import org.springframework.util.StringUtils;
* by default, Spring's {@link Autowired @Autowired} and {@link Value @Value}
* annotations.
*
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* <p>Also supports JSR-330's {@link jakarta.inject.Inject @Inject} annotation,
* if available, as a direct alternative to Spring's own {@code @Autowired}.
*
* <h3>Autowired Constructors</h3>
@ -154,7 +154,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
* <p>Also supports JSR-330's {@link jakarta.inject.Inject @Inject} annotation,
* if available.
*/
@SuppressWarnings("unchecked")
@ -163,8 +163,8 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
ClassUtils.forName("jakarta.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.trace("JSR-330 'jakarta.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
@ -177,7 +177,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
* setter methods, and arbitrary config methods.
* <p>The default autowired annotation types are the Spring-provided
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
* as JSR-330's {@link javax.inject.Inject @Inject} annotation, if available.
* as JSR-330's {@link jakarta.inject.Inject @Inject} annotation, if available.
* <p>This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation type to indicate that a member is supposed
* to be autowired.
@ -193,7 +193,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
* setter methods, and arbitrary config methods.
* <p>The default autowired annotation types are the Spring-provided
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
* as JSR-330's {@link javax.inject.Inject @Inject} annotation, if available.
* as JSR-330's {@link jakarta.inject.Inject @Inject} annotation, if available.
* <p>This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation types to indicate that a member is supposed
* to be autowired.
@ -537,9 +537,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
* @param ann the Autowired annotation
* @return whether the annotation indicates that a dependency is required
*/
@SuppressWarnings({"deprecation", "cast"})
protected boolean determineRequiredStatus(MergedAnnotation<?> ann) {
// The following (AnnotationAttributes) cast is required on JDK 9+.
return determineRequiredStatus((AnnotationAttributes)
ann.asMap(mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
}

View File

@ -66,9 +66,9 @@ import org.springframework.util.ReflectionUtils;
* init method and destroy method, respectively.
*
* <p>Spring's {@link org.springframework.context.annotation.CommonAnnotationBeanPostProcessor}
* supports the JSR-250 {@link javax.annotation.PostConstruct} and {@link javax.annotation.PreDestroy}
* supports the JSR-250 {@link jakarta.annotation.PostConstruct} and {@link jakarta.annotation.PreDestroy}
* annotations out of the box, as init annotation and destroy annotation, respectively.
* Furthermore, it also supports the {@link javax.annotation.Resource} annotation
* Furthermore, it also supports the {@link jakarta.annotation.Resource} annotation
* for annotation-driven injection of named beans.
*
* @author Juergen Hoeller
@ -117,7 +117,7 @@ public class InitDestroyAnnotationBeanPostProcessor
* methods to call after configuration of a bean.
* <p>Any custom annotation can be used, since there are no required
* annotation attributes. There is no default, although a typical choice
* is the JSR-250 {@link javax.annotation.PostConstruct} annotation.
* is the JSR-250 {@link jakarta.annotation.PostConstruct} annotation.
*/
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
this.initAnnotationType = initAnnotationType;
@ -128,7 +128,7 @@ public class InitDestroyAnnotationBeanPostProcessor
* methods to call when the context is shutting down.
* <p>Any custom annotation can be used, since there are no required
* annotation attributes. There is no default, although a typical choice
* is the JSR-250 {@link javax.annotation.PreDestroy} annotation.
* is the JSR-250 {@link jakarta.annotation.PreDestroy} annotation.
*/
public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
this.destroyAnnotationType = destroyAnnotationType;

View File

@ -46,7 +46,7 @@ import org.springframework.util.ObjectUtils;
* against {@link Qualifier qualifier annotations} on the field or parameter to be autowired.
* Also supports suggested expression values through a {@link Value value} annotation.
*
* <p>Also supports JSR-330's {@link javax.inject.Qualifier} annotation, if available.
* <p>Also supports JSR-330's {@link jakarta.inject.Qualifier} annotation, if available.
*
* @author Mark Fisher
* @author Juergen Hoeller
@ -66,13 +66,13 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
/**
* Create a new QualifierAnnotationAutowireCandidateResolver
* for Spring's standard {@link Qualifier} annotation.
* <p>Also supports JSR-330's {@link javax.inject.Qualifier} annotation, if available.
* <p>Also supports JSR-330's {@link jakarta.inject.Qualifier} annotation, if available.
*/
@SuppressWarnings("unchecked")
public QualifierAnnotationAutowireCandidateResolver() {
this.qualifierTypes.add(Qualifier.class);
try {
this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Qualifier",
this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("jakarta.inject.Qualifier",
QualifierAnnotationAutowireCandidateResolver.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {

View File

@ -182,7 +182,7 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
/**
* Check whether the underlying field is annotated with any variant of a
* {@code Nullable} annotation, e.g. {@code javax.annotation.Nullable} or
* {@code Nullable} annotation, e.g. {@code jakarta.annotation.Nullable} or
* {@code edu.umd.cs.findbugs.annotations.Nullable}.
*/
private boolean hasNullableAnnotation() {

View File

@ -18,7 +18,7 @@ package org.springframework.beans.factory.config;
import java.io.Serializable;
import javax.inject.Provider;
import jakarta.inject.Provider;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
@ -27,18 +27,18 @@ import org.springframework.util.Assert;
/**
* A {@link org.springframework.beans.factory.FactoryBean} implementation that
* returns a value which is a JSR-330 {@link javax.inject.Provider} that in turn
* returns a value which is a JSR-330 {@link jakarta.inject.Provider} that in turn
* returns a bean sourced from a {@link org.springframework.beans.factory.BeanFactory}.
*
* <p>This is basically a JSR-330 compliant variant of Spring's good old
* {@link ObjectFactoryCreatingFactoryBean}. It can be used for traditional
* external dependency injection configuration that targets a property or
* constructor argument of type {@code javax.inject.Provider}, as an
* constructor argument of type {@code jakarta.inject.Provider}, as an
* alternative to JSR-330's {@code @Inject} annotation-driven approach.
*
* @author Juergen Hoeller
* @since 3.0.2
* @see javax.inject.Provider
* @see jakarta.inject.Provider
* @see ObjectFactoryCreatingFactoryBean
*/
public class ProviderCreatingFactoryBean extends AbstractFactoryBean<Provider<Object>> {

View File

@ -138,7 +138,7 @@ public interface Scope {
* <p>The exact meaning of the conversation ID depends on the underlying
* storage mechanism. In the case of session-scoped objects, the
* conversation ID would typically be equal to (or derived from) the
* {@link javax.servlet.http.HttpSession#getId() session ID}; in the
* {@link jakarta.servlet.http.HttpSession#getId() session ID}; in the
* case of a custom conversation that sits within the overall session,
* the specific ID for the current conversation would be appropriate.
* <p><b>Note: This is an optional operation.</b> It is perfectly valid to

View File

@ -41,7 +41,7 @@ import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import javax.inject.Provider;
import jakarta.inject.Provider;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
@ -125,7 +125,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
static {
try {
javaxInjectProviderClass =
ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
ClassUtils.forName("jakarta.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - Provider interface simply not supported then.
@ -1651,7 +1651,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Determine the candidate with the highest priority in the given set of beans.
* <p>Based on {@code @javax.annotation.Priority}. As defined by the related
* <p>Based on {@code @jakarta.annotation.Priority}. As defined by the related
* {@link org.springframework.core.Ordered} interface, the lowest value has
* the highest priority.
* @param candidates a Map of candidate names and candidate instances
@ -1711,7 +1711,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Return the priority assigned for the given bean instance by
* the {@code javax.annotation.Priority} annotation.
* the {@code jakarta.annotation.Priority} annotation.
* <p>The default implementation delegates to the specified
* {@link #setDependencyComparator dependency comparator}, checking its
* {@link OrderComparator#getPriority method} if it is an extension of
@ -2086,8 +2086,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
/**
* Separate inner class for avoiding a hard dependency on the {@code javax.inject} API.
* Actual {@code javax.inject.Provider} implementation is nested here in order to make it
* Separate inner class for avoiding a hard dependency on the {@code jakarta.inject} API.
* Actual {@code jakarta.inject.Provider} implementation is nested here in order to make it
* invisible for Graal's introspection of DefaultListableBeanFactory's nested classes.
*/
private class Jsr330Factory implements Serializable {

View File

@ -36,8 +36,7 @@ import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Priority;
import jakarta.annotation.Priority;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;

View File

@ -23,10 +23,9 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Provider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -51,7 +50,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Unit tests for {@link org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor}
* processing the JSR-330 {@link javax.inject.Inject} annotation.
* processing the JSR-330 {@link jakarta.inject.Inject} annotation.
*
* @author Juergen Hoeller
* @since 3.0

View File

@ -18,8 +18,7 @@ package org.springframework.beans.factory.config;
import java.util.Date;
import javax.inject.Provider;
import jakarta.inject.Provider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -2,8 +2,8 @@ description = "Spring Context Indexer"
dependencies {
testImplementation(project(":spring-context"))
testImplementation("javax.inject:javax.inject")
testImplementation("javax.annotation:javax.annotation-api")
testImplementation("javax.transaction:javax.transaction-api")
testImplementation("org.eclipse.persistence:javax.persistence")
testImplementation("jakarta.inject:jakarta.inject-api")
testImplementation("jakarta.annotation:jakarta.annotation-api")
testImplementation("jakarta.persistence:jakarta.persistence-api")
testImplementation("jakarta.transaction:jakarta.transaction-api")
}

View File

@ -49,7 +49,7 @@ class StandardStereotypesProvider implements StereotypesProvider {
}
for (AnnotationMirror annotation : this.typeHelper.getAllAnnotationMirrors(element)) {
String type = this.typeHelper.getType(annotation);
if (type.startsWith("javax.")) {
if (type.startsWith("jakarta.")) {
stereotypes.add(type);
}
}

View File

@ -21,14 +21,13 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import javax.annotation.ManagedBean;
import javax.inject.Named;
import javax.persistence.Converter;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import javax.transaction.Transactional;
import jakarta.annotation.ManagedBean;
import jakarta.inject.Named;
import jakarta.persistence.Converter;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Entity;
import jakarta.persistence.MappedSuperclass;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

View File

@ -16,7 +16,7 @@
package org.springframework.context.index.sample.cdi;
import javax.annotation.ManagedBean;
import jakarta.annotation.ManagedBean;
/**
* Test candidate for a CDI {@link ManagedBean}.

View File

@ -16,7 +16,7 @@
package org.springframework.context.index.sample.cdi;
import javax.inject.Named;
import jakarta.inject.Named;
/**
* Test candidate for a CDI {@link Named} bean.

View File

@ -16,7 +16,7 @@
package org.springframework.context.index.sample.cdi;
import javax.transaction.Transactional;
import jakarta.transaction.Transactional;
/**
* Test candidate for {@link Transactional}. This verifies that the annotation processor

View File

@ -16,7 +16,7 @@
package org.springframework.context.index.sample.jpa;
import javax.persistence.Converter;
import jakarta.persistence.Converter;
/**
* Test candidate for {@link Converter}.

View File

@ -16,7 +16,7 @@
package org.springframework.context.index.sample.jpa;
import javax.persistence.Embeddable;
import jakarta.persistence.Embeddable;
/**
* Test candidate for {@link Embeddable}.

View File

@ -16,7 +16,7 @@
package org.springframework.context.index.sample.jpa;
import javax.persistence.Entity;
import jakarta.persistence.Entity;
/**
* Test candidate for {@link Entity}.

View File

@ -16,7 +16,7 @@
package org.springframework.context.index.sample.jpa;
import javax.persistence.MappedSuperclass;
import jakarta.persistence.MappedSuperclass;
/**
* Test candidate for {@link MappedSuperclass}.

View File

@ -6,13 +6,11 @@ dependencies {
api(project(":spring-core"))
optional(project(":spring-jdbc")) // for Quartz support
optional(project(":spring-tx")) // for Quartz support
optional("javax.activation:javax.activation-api")
optional("javax.mail:javax.mail-api")
optional("jakarta.activation:jakarta.activation-api")
optional("jakarta.mail:jakarta.mail-api")
optional("javax.cache:cache-api")
optional("com.github.ben-manes.caffeine:caffeine")
optional("net.sf.ehcache:ehcache")
optional("org.quartz-scheduler:quartz")
optional("org.codehaus.fabric3.api:commonj")
optional("org.freemarker:freemarker")
testImplementation(project(":spring-context"))
testImplementation(testFixtures(project(":spring-beans")))
@ -20,12 +18,11 @@ dependencies {
testImplementation(testFixtures(project(":spring-core")))
testImplementation(testFixtures(project(":spring-tx")))
testImplementation("org.hsqldb:hsqldb")
testImplementation("org.hibernate:hibernate-validator")
testImplementation("javax.annotation:javax.annotation-api")
testImplementation("jakarta.annotation:jakarta.annotation-api")
testRuntimeOnly("org.ehcache:jcache")
testRuntimeOnly("org.ehcache:ehcache")
testRuntimeOnly("org.glassfish:javax.el")
testRuntimeOnly("com.sun.mail:javax.mail")
testRuntimeOnly("org.glassfish:jakarta.el")
testRuntimeOnly("com.sun.mail:jakarta.mail")
testFixturesApi("org.junit.jupiter:junit-jupiter-api")
testFixturesImplementation("org.assertj:assertj-core")
testFixturesImplementation("org.mockito:mockito-core")

View File

@ -1,171 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.ehcache;
import java.util.concurrent.Callable;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.Status;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* {@link Cache} implementation on top of an {@link Ehcache} instance.
*
* @author Costin Leau
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 3.1
* @see EhCacheCacheManager
*/
public class EhCacheCache implements Cache {
private final Ehcache cache;
/**
* Create an {@link EhCacheCache} instance.
* @param ehcache the backing Ehcache instance
*/
public EhCacheCache(Ehcache ehcache) {
Assert.notNull(ehcache, "Ehcache must not be null");
Status status = ehcache.getStatus();
if (!Status.STATUS_ALIVE.equals(status)) {
throw new IllegalArgumentException(
"An 'alive' Ehcache is required - current cache is " + status.toString());
}
this.cache = ehcache;
}
@Override
public final String getName() {
return this.cache.getName();
}
@Override
public final Ehcache getNativeCache() {
return this.cache;
}
@Override
@Nullable
public ValueWrapper get(Object key) {
Element element = lookup(key);
return toValueWrapper(element);
}
@SuppressWarnings("unchecked")
@Override
@Nullable
public <T> T get(Object key, @Nullable Class<T> type) {
Element element = this.cache.get(key);
Object value = (element != null ? element.getObjectValue() : null);
if (value != null && type != null && !type.isInstance(value)) {
throw new IllegalStateException(
"Cached value is not of required type [" + type.getName() + "]: " + value);
}
return (T) value;
}
@SuppressWarnings("unchecked")
@Override
@Nullable
public <T> T get(Object key, Callable<T> valueLoader) {
Element element = lookup(key);
if (element != null) {
return (T) element.getObjectValue();
}
else {
this.cache.acquireWriteLockOnKey(key);
try {
element = lookup(key); // one more attempt with the write lock
if (element != null) {
return (T) element.getObjectValue();
}
else {
return loadValue(key, valueLoader);
}
}
finally {
this.cache.releaseWriteLockOnKey(key);
}
}
}
private <T> T loadValue(Object key, Callable<T> valueLoader) {
T value;
try {
value = valueLoader.call();
}
catch (Throwable ex) {
throw new ValueRetrievalException(key, valueLoader, ex);
}
put(key, value);
return value;
}
@Override
public void put(Object key, @Nullable Object value) {
this.cache.put(new Element(key, value));
}
@Override
@Nullable
public ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
Element existingElement = this.cache.putIfAbsent(new Element(key, value));
return toValueWrapper(existingElement);
}
@Override
public void evict(Object key) {
this.cache.remove(key);
}
@Override
public boolean evictIfPresent(Object key) {
return this.cache.remove(key);
}
@Override
public void clear() {
this.cache.removeAll();
}
@Override
public boolean invalidate() {
boolean notEmpty = (this.cache.getSize() > 0);
this.cache.removeAll();
return notEmpty;
}
@Nullable
private Element lookup(Object key) {
return this.cache.get(key);
}
@Nullable
private ValueWrapper toValueWrapper(@Nullable Element element) {
return (element != null ? new SimpleValueWrapper(element.getObjectValue()) : null);
}
}

View File

@ -1,117 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.ehcache;
import java.util.Collection;
import java.util.LinkedHashSet;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Status;
import org.springframework.cache.Cache;
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* CacheManager backed by an EhCache {@link net.sf.ehcache.CacheManager}.
*
* @author Costin Leau
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 3.1
* @see EhCacheCache
*/
public class EhCacheCacheManager extends AbstractTransactionSupportingCacheManager {
@Nullable
private net.sf.ehcache.CacheManager cacheManager;
/**
* Create a new EhCacheCacheManager, setting the target EhCache CacheManager
* through the {@link #setCacheManager} bean property.
*/
public EhCacheCacheManager() {
}
/**
* Create a new EhCacheCacheManager for the given backing EhCache CacheManager.
* @param cacheManager the backing EhCache {@link net.sf.ehcache.CacheManager}
*/
public EhCacheCacheManager(net.sf.ehcache.CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
/**
* Set the backing EhCache {@link net.sf.ehcache.CacheManager}.
*/
public void setCacheManager(@Nullable net.sf.ehcache.CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
/**
* Return the backing EhCache {@link net.sf.ehcache.CacheManager}.
*/
@Nullable
public net.sf.ehcache.CacheManager getCacheManager() {
return this.cacheManager;
}
@Override
public void afterPropertiesSet() {
if (getCacheManager() == null) {
setCacheManager(EhCacheManagerUtils.buildCacheManager());
}
super.afterPropertiesSet();
}
@Override
protected Collection<Cache> loadCaches() {
net.sf.ehcache.CacheManager cacheManager = getCacheManager();
Assert.state(cacheManager != null, "No CacheManager set");
Status status = cacheManager.getStatus();
if (!Status.STATUS_ALIVE.equals(status)) {
throw new IllegalStateException(
"An 'alive' EhCache CacheManager is required - current cache is " + status.toString());
}
String[] names = getCacheManager().getCacheNames();
Collection<Cache> caches = new LinkedHashSet<>(names.length);
for (String name : names) {
caches.add(new EhCacheCache(getCacheManager().getEhcache(name)));
}
return caches;
}
@Override
protected Cache getMissingCache(String name) {
net.sf.ehcache.CacheManager cacheManager = getCacheManager();
Assert.state(cacheManager != null, "No CacheManager set");
// Check the EhCache cache again (in case the cache was added at runtime)
Ehcache ehcache = cacheManager.getEhcache(name);
if (ehcache != null) {
return new EhCacheCache(ehcache);
}
return null;
}
}

View File

@ -1,329 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.ehcache;
import java.util.Set;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.bootstrap.BootstrapCacheLoader;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.constructs.blocking.BlockingCache;
import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
import net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory;
import net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache;
import net.sf.ehcache.event.CacheEventListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
/**
* {@link FactoryBean} that creates a named EhCache {@link net.sf.ehcache.Cache} instance
* (or a decorator that implements the {@link net.sf.ehcache.Ehcache} interface),
* representing a cache region within an EhCache {@link net.sf.ehcache.CacheManager}.
*
* <p>If the specified named cache is not configured in the cache configuration descriptor,
* this FactoryBean will construct an instance of a Cache with the provided name and the
* specified cache properties and add it to the CacheManager for later retrieval. If some
* or all properties are not set at configuration time, this FactoryBean will use defaults.
*
* <p>Note: If the named Cache instance is found, the properties will be ignored and the
* Cache instance will be retrieved from the CacheManager.
*
* <p>Note: As of Spring 5.0, Spring's EhCache support requires EhCache 2.10 or higher.
*
* @author Juergen Hoeller
* @author Dmitriy Kopylenko
* @since 1.1.1
* @see #setCacheManager
* @see EhCacheManagerFactoryBean
* @see net.sf.ehcache.Cache
*/
public class EhCacheFactoryBean extends CacheConfiguration implements FactoryBean<Ehcache>, BeanNameAware, InitializingBean {
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private CacheManager cacheManager;
private boolean blocking = false;
@Nullable
private CacheEntryFactory cacheEntryFactory;
@Nullable
private BootstrapCacheLoader bootstrapCacheLoader;
@Nullable
private Set<CacheEventListener> cacheEventListeners;
private boolean disabled = false;
@Nullable
private String beanName;
@Nullable
private Ehcache cache;
public EhCacheFactoryBean() {
setMaxEntriesLocalHeap(10000);
setMaxEntriesLocalDisk(10000000);
setTimeToLiveSeconds(120);
setTimeToIdleSeconds(120);
}
/**
* Set a CacheManager from which to retrieve a named Cache instance.
* By default, {@code CacheManager.getInstance()} will be called.
* <p>Note that in particular for persistent caches, it is advisable to
* properly handle the shutdown of the CacheManager: Set up a separate
* EhCacheManagerFactoryBean and pass a reference to this bean property.
* <p>A separate EhCacheManagerFactoryBean is also necessary for loading
* EhCache configuration from a non-default config location.
* @see EhCacheManagerFactoryBean
* @see net.sf.ehcache.CacheManager#getInstance
*/
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
/**
* Set a name for which to retrieve or create a cache instance.
* Default is the bean name of this EhCacheFactoryBean.
*/
public void setCacheName(String cacheName) {
setName(cacheName);
}
/**
* Set the time to live.
* @see #setTimeToLiveSeconds(long)
*/
public void setTimeToLive(int timeToLive) {
setTimeToLiveSeconds(timeToLive);
}
/**
* Set the time to idle.
* @see #setTimeToIdleSeconds(long)
*/
public void setTimeToIdle(int timeToIdle) {
setTimeToIdleSeconds(timeToIdle);
}
/**
* Set the disk spool buffer size (in MB).
* @see #setDiskSpoolBufferSizeMB(int)
*/
public void setDiskSpoolBufferSize(int diskSpoolBufferSize) {
setDiskSpoolBufferSizeMB(diskSpoolBufferSize);
}
/**
* Set whether to use a blocking cache that lets read attempts block
* until the requested element is created.
* <p>If you intend to build a self-populating blocking cache,
* consider specifying a {@link #setCacheEntryFactory CacheEntryFactory}.
* @see net.sf.ehcache.constructs.blocking.BlockingCache
* @see #setCacheEntryFactory
*/
public void setBlocking(boolean blocking) {
this.blocking = blocking;
}
/**
* Set an EhCache {@link net.sf.ehcache.constructs.blocking.CacheEntryFactory}
* to use for a self-populating cache. If such a factory is specified,
* the cache will be decorated with EhCache's
* {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}.
* <p>The specified factory can be of type
* {@link net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory},
* which will lead to the use of an
* {@link net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache}.
* <p>Note: Any such self-populating cache is automatically a blocking cache.
* @see net.sf.ehcache.constructs.blocking.SelfPopulatingCache
* @see net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache
* @see net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory
*/
public void setCacheEntryFactory(CacheEntryFactory cacheEntryFactory) {
this.cacheEntryFactory = cacheEntryFactory;
}
/**
* Set an EhCache {@link net.sf.ehcache.bootstrap.BootstrapCacheLoader}
* for this cache, if any.
*/
public void setBootstrapCacheLoader(BootstrapCacheLoader bootstrapCacheLoader) {
this.bootstrapCacheLoader = bootstrapCacheLoader;
}
/**
* Specify EhCache {@link net.sf.ehcache.event.CacheEventListener cache event listeners}
* to registered with this cache.
*/
public void setCacheEventListeners(Set<CacheEventListener> cacheEventListeners) {
this.cacheEventListeners = cacheEventListeners;
}
/**
* Set whether this cache should be marked as disabled.
* @see net.sf.ehcache.Cache#setDisabled
*/
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void afterPropertiesSet() throws CacheException {
// If no cache name given, use bean name as cache name.
String cacheName = getName();
if (cacheName == null) {
cacheName = this.beanName;
if (cacheName != null) {
setName(cacheName);
}
}
// If no CacheManager given, fetch the default.
if (this.cacheManager == null) {
if (logger.isDebugEnabled()) {
logger.debug("Using default EhCache CacheManager for cache region '" + cacheName + "'");
}
this.cacheManager = CacheManager.getInstance();
}
synchronized (this.cacheManager) {
// Fetch cache region: If none with the given name exists, create one on the fly.
Ehcache rawCache;
boolean cacheExists = this.cacheManager.cacheExists(cacheName);
if (cacheExists) {
if (logger.isDebugEnabled()) {
logger.debug("Using existing EhCache cache region '" + cacheName + "'");
}
rawCache = this.cacheManager.getEhcache(cacheName);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Creating new EhCache cache region '" + cacheName + "'");
}
rawCache = createCache();
rawCache.setBootstrapCacheLoader(this.bootstrapCacheLoader);
}
if (this.cacheEventListeners != null) {
for (CacheEventListener listener : this.cacheEventListeners) {
rawCache.getCacheEventNotificationService().registerListener(listener);
}
}
// Needs to happen after listener registration but before setStatisticsEnabled
if (!cacheExists) {
this.cacheManager.addCache(rawCache);
}
if (this.disabled) {
rawCache.setDisabled(true);
}
Ehcache decoratedCache = decorateCache(rawCache);
if (decoratedCache != rawCache) {
this.cacheManager.replaceCacheWithDecoratedCache(rawCache, decoratedCache);
}
this.cache = decoratedCache;
}
}
/**
* Create a raw Cache object based on the configuration of this FactoryBean.
*/
protected Cache createCache() {
return new Cache(this);
}
/**
* Decorate the given Cache, if necessary.
* @param cache the raw Cache object, based on the configuration of this FactoryBean
* @return the (potentially decorated) cache object to be registered with the CacheManager
*/
protected Ehcache decorateCache(Ehcache cache) {
if (this.cacheEntryFactory != null) {
if (this.cacheEntryFactory instanceof UpdatingCacheEntryFactory) {
return new UpdatingSelfPopulatingCache(cache, (UpdatingCacheEntryFactory) this.cacheEntryFactory);
}
else {
return new SelfPopulatingCache(cache, this.cacheEntryFactory);
}
}
if (this.blocking) {
return new BlockingCache(cache);
}
return cache;
}
@Override
@Nullable
public Ehcache getObject() {
return this.cache;
}
/**
* Predict the particular {@code Ehcache} implementation that will be returned from
* {@link #getObject()} based on logic in {@link #createCache()} and
* {@link #decorateCache(Ehcache)} as orchestrated by {@link #afterPropertiesSet()}.
*/
@Override
public Class<? extends Ehcache> getObjectType() {
if (this.cache != null) {
return this.cache.getClass();
}
if (this.cacheEntryFactory != null) {
if (this.cacheEntryFactory instanceof UpdatingCacheEntryFactory) {
return UpdatingSelfPopulatingCache.class;
}
else {
return SelfPopulatingCache.class;
}
}
if (this.blocking) {
return BlockingCache.class;
}
return Cache.class;
}
@Override
public boolean isSingleton() {
return true;
}
}

View File

@ -1,199 +0,0 @@
/*
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.ehcache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.ConfigurationFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
/**
* {@link FactoryBean} that exposes an EhCache {@link net.sf.ehcache.CacheManager}
* instance (independent or shared), configured from a specified config location.
*
* <p>If no config location is specified, a CacheManager will be configured from
* "ehcache.xml" in the root of the class path (that is, default EhCache initialization
* - as defined in the EhCache docs - will apply).
*
* <p>Setting up a separate EhCacheManagerFactoryBean is also advisable when using
* EhCacheFactoryBean, as it provides a (by default) independent CacheManager instance
* and cares for proper shutdown of the CacheManager. EhCacheManagerFactoryBean is
* also necessary for loading EhCache configuration from a non-default config location.
*
* <p>Note: As of Spring 5.0, Spring's EhCache support requires EhCache 2.10 or higher.
*
* @author Juergen Hoeller
* @author Dmitriy Kopylenko
* @since 1.1.1
* @see #setConfigLocation
* @see #setShared
* @see EhCacheFactoryBean
* @see net.sf.ehcache.CacheManager
*/
public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, InitializingBean, DisposableBean {
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private Resource configLocation;
@Nullable
private String cacheManagerName;
private boolean acceptExisting = false;
private boolean shared = false;
@Nullable
private CacheManager cacheManager;
private boolean locallyManaged = true;
/**
* Set the location of the EhCache config file. A typical value is "/WEB-INF/ehcache.xml".
* <p>Default is "ehcache.xml" in the root of the class path, or if not found,
* "ehcache-failsafe.xml" in the EhCache jar (default EhCache initialization).
* @see net.sf.ehcache.CacheManager#create(java.io.InputStream)
* @see net.sf.ehcache.CacheManager#CacheManager(java.io.InputStream)
*/
public void setConfigLocation(Resource configLocation) {
this.configLocation = configLocation;
}
/**
* Set the name of the EhCache CacheManager (if a specific name is desired).
* @see net.sf.ehcache.config.Configuration#setName(String)
*/
public void setCacheManagerName(String cacheManagerName) {
this.cacheManagerName = cacheManagerName;
}
/**
* Set whether an existing EhCache CacheManager of the same name will be accepted
* for this EhCacheManagerFactoryBean setup. Default is "false".
* <p>Typically used in combination with {@link #setCacheManagerName "cacheManagerName"}
* but will simply work with the default CacheManager name if none specified.
* All references to the same CacheManager name (or the same default) in the
* same ClassLoader space will share the specified CacheManager then.
* @see #setCacheManagerName
* #see #setShared
* @see net.sf.ehcache.CacheManager#getCacheManager(String)
* @see net.sf.ehcache.CacheManager#CacheManager()
*/
public void setAcceptExisting(boolean acceptExisting) {
this.acceptExisting = acceptExisting;
}
/**
* Set whether the EhCache CacheManager should be shared (as a singleton at the
* ClassLoader level) or independent (typically local within the application).
* Default is "false", creating an independent local instance.
* <p><b>NOTE:</b> This feature allows for sharing this EhCacheManagerFactoryBean's
* CacheManager with any code calling <code>CacheManager.create()</code> in the same
* ClassLoader space, with no need to agree on a specific CacheManager name.
* However, it only supports a single EhCacheManagerFactoryBean involved which will
* control the lifecycle of the underlying CacheManager (in particular, its shutdown).
* <p>This flag overrides {@link #setAcceptExisting "acceptExisting"} if both are set,
* since it indicates the 'stronger' mode of sharing.
* @see #setCacheManagerName
* @see #setAcceptExisting
* @see net.sf.ehcache.CacheManager#create()
* @see net.sf.ehcache.CacheManager#CacheManager()
*/
public void setShared(boolean shared) {
this.shared = shared;
}
@Override
public void afterPropertiesSet() throws CacheException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
Configuration configuration = (this.configLocation != null ?
EhCacheManagerUtils.parseConfiguration(this.configLocation) : ConfigurationFactory.parseConfiguration());
if (this.cacheManagerName != null) {
configuration.setName(this.cacheManagerName);
}
if (this.shared) {
// Old-school EhCache singleton sharing...
// No way to find out whether we actually created a new CacheManager
// or just received an existing singleton reference.
this.cacheManager = CacheManager.create(configuration);
}
else if (this.acceptExisting) {
// EhCache 2.5+: Reusing an existing CacheManager of the same name.
// Basically the same code as in CacheManager.getInstance(String),
// just storing whether we're dealing with an existing instance.
synchronized (CacheManager.class) {
this.cacheManager = CacheManager.getCacheManager(this.cacheManagerName);
if (this.cacheManager == null) {
this.cacheManager = new CacheManager(configuration);
}
else {
this.locallyManaged = false;
}
}
}
else {
// Throwing an exception if a CacheManager of the same name exists already...
this.cacheManager = new CacheManager(configuration);
}
}
@Override
@Nullable
public CacheManager getObject() {
return this.cacheManager;
}
@Override
public Class<? extends CacheManager> getObjectType() {
return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public void destroy() {
if (this.cacheManager != null && this.locallyManaged) {
if (logger.isDebugEnabled()) {
logger.debug("Shutting down EhCache CacheManager" +
(this.cacheManagerName != null ? " '" + this.cacheManagerName + "'" : ""));
}
this.cacheManager.shutdown();
}
}
}

View File

@ -1,125 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.ehcache;
import java.io.IOException;
import java.io.InputStream;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.ConfigurationFactory;
import org.springframework.core.io.Resource;
/**
* Convenient builder methods for EhCache 2.5+ {@link CacheManager} setup,
* providing easy programmatic bootstrapping from a Spring-provided resource.
* This is primarily intended for use within {@code @Bean} methods in a
* Spring configuration class.
*
* <p>These methods are a simple alternative to custom {@link CacheManager} setup
* code. For any advanced purposes, consider using {@link #parseConfiguration},
* customizing the configuration object, and then calling the
* {@link CacheManager#CacheManager(Configuration)} constructor.
*
* @author Juergen Hoeller
* @since 4.1
*/
public abstract class EhCacheManagerUtils {
/**
* Build an EhCache {@link CacheManager} from the default configuration.
* <p>The CacheManager will be configured from "ehcache.xml" in the root of the class path
* (that is, default EhCache initialization - as defined in the EhCache docs - will apply).
* If no configuration file can be found, a fail-safe fallback configuration will be used.
* @return the new EhCache CacheManager
* @throws CacheException in case of configuration parsing failure
*/
public static CacheManager buildCacheManager() throws CacheException {
return new CacheManager(ConfigurationFactory.parseConfiguration());
}
/**
* Build an EhCache {@link CacheManager} from the default configuration.
* <p>The CacheManager will be configured from "ehcache.xml" in the root of the class path
* (that is, default EhCache initialization - as defined in the EhCache docs - will apply).
* If no configuration file can be found, a fail-safe fallback configuration will be used.
* @param name the desired name of the cache manager
* @return the new EhCache CacheManager
* @throws CacheException in case of configuration parsing failure
*/
public static CacheManager buildCacheManager(String name) throws CacheException {
Configuration configuration = ConfigurationFactory.parseConfiguration();
configuration.setName(name);
return new CacheManager(configuration);
}
/**
* Build an EhCache {@link CacheManager} from the given configuration resource.
* @param configLocation the location of the configuration file (as a Spring resource)
* @return the new EhCache CacheManager
* @throws CacheException in case of configuration parsing failure
*/
public static CacheManager buildCacheManager(Resource configLocation) throws CacheException {
return new CacheManager(parseConfiguration(configLocation));
}
/**
* Build an EhCache {@link CacheManager} from the given configuration resource.
* @param name the desired name of the cache manager
* @param configLocation the location of the configuration file (as a Spring resource)
* @return the new EhCache CacheManager
* @throws CacheException in case of configuration parsing failure
*/
public static CacheManager buildCacheManager(String name, Resource configLocation) throws CacheException {
Configuration configuration = parseConfiguration(configLocation);
configuration.setName(name);
return new CacheManager(configuration);
}
/**
* Parse EhCache configuration from the given resource, for further use with
* custom {@link CacheManager} creation.
* @param configLocation the location of the configuration file (as a Spring resource)
* @return the EhCache Configuration handle
* @throws CacheException in case of configuration parsing failure
* @see CacheManager#CacheManager(Configuration)
* @see CacheManager#create(Configuration)
*/
public static Configuration parseConfiguration(Resource configLocation) throws CacheException {
InputStream is = null;
try {
is = configLocation.getInputStream();
return ConfigurationFactory.parseConfiguration(is);
}
catch (IOException ex) {
throw new CacheException("Failed to parse EhCache configuration resource", ex);
}
finally {
if (is != null) {
try {
is.close();
}
catch (IOException ex) {
// ignore
}
}
}
}
}

View File

@ -1,17 +0,0 @@
/**
* Support classes for the open source cache
* <a href="https://www.ehcache.org/">EhCache 2.x</a>,
* allowing to set up an EhCache CacheManager and Caches
* as beans in a Spring context.
*
* <p>Note: EhCache 3.x lives in a different package namespace
* and is not covered by the traditional support classes here.
* Instead, consider using it through JCache (JSR-107), with
* Spring's support in {@code org.springframework.cache.jcache}.
*/
@NonNullApi
@NonNullFields
package org.springframework.cache.ehcache;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

View File

@ -104,7 +104,7 @@ public class MailSendException extends MailException {
* be available after serialization as well.
* @return the Map of failed messages as keys and thrown exceptions as values
* @see SimpleMailMessage
* @see javax.mail.internet.MimeMessage
* @see jakarta.mail.internet.MimeMessage
*/
public final Map<Object, Exception> getFailedMessages() {
return this.failedMessages;

View File

@ -20,8 +20,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.activation.FileTypeMap;
import javax.activation.MimetypesFileTypeMap;
import jakarta.activation.FileTypeMap;
import jakarta.activation.MimetypesFileTypeMap;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
@ -58,7 +58,7 @@ import org.springframework.lang.Nullable;
* @since 1.2
* @see #setMappingLocation
* @see #setMappings
* @see javax.activation.MimetypesFileTypeMap
* @see jakarta.activation.MimetypesFileTypeMap
*/
public class ConfigurableMimeFileTypeMap extends FileTypeMap implements InitializingBean {
@ -140,8 +140,8 @@ public class ConfigurableMimeFileTypeMap extends FileTypeMap implements Initiali
* @param mappings an array of MIME type mapping lines (can be {@code null})
* @return the compiled FileTypeMap
* @throws IOException if resource access failed
* @see javax.activation.MimetypesFileTypeMap#MimetypesFileTypeMap(java.io.InputStream)
* @see javax.activation.MimetypesFileTypeMap#addMimeTypes(String)
* @see jakarta.activation.MimetypesFileTypeMap#MimetypesFileTypeMap(java.io.InputStream)
* @see jakarta.activation.MimetypesFileTypeMap#addMimeTypes(String)
*/
protected FileTypeMap createFileTypeMap(@Nullable Resource mappingLocation, @Nullable String[] mappings) throws IOException {
MimetypesFileTypeMap fileTypeMap = null;

View File

@ -18,8 +18,8 @@ package org.springframework.mail.javamail;
import java.beans.PropertyEditorSupport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import org.springframework.util.StringUtils;
@ -32,7 +32,7 @@ import org.springframework.util.StringUtils;
*
* @author Juergen Hoeller
* @since 1.2.3
* @see javax.mail.internet.InternetAddress
* @see jakarta.mail.internet.InternetAddress
*/
public class InternetAddressEditor extends PropertyEditorSupport {

View File

@ -18,7 +18,7 @@ package org.springframework.mail.javamail;
import java.io.InputStream;
import javax.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMessage;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
@ -40,7 +40,7 @@ import org.springframework.mail.MailSender;
* mechanism, possibly using a {@link MimeMessageHelper} for populating the message.
* See {@link MimeMessageHelper MimeMessageHelper's javadoc} for an example.
*
* <p>The entire JavaMail {@link javax.mail.Session} management is abstracted
* <p>The entire JavaMail {@link jakarta.mail.Session} management is abstracted
* by the JavaMailSender. Client code should not deal with a Session in any way,
* rather leave the entire JavaMail configuration and resource handling to the
* JavaMailSender implementation. This also increases testability.
@ -54,8 +54,8 @@ import org.springframework.mail.MailSender;
*
* @author Juergen Hoeller
* @since 07.10.2003
* @see javax.mail.internet.MimeMessage
* @see javax.mail.Session
* @see jakarta.mail.internet.MimeMessage
* @see jakarta.mail.Session
* @see JavaMailSenderImpl
* @see MimeMessagePreparator
* @see MimeMessageHelper

View File

@ -24,14 +24,14 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.activation.FileTypeMap;
import javax.mail.Address;
import javax.mail.AuthenticationFailedException;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.MimeMessage;
import jakarta.activation.FileTypeMap;
import jakarta.mail.Address;
import jakarta.mail.AuthenticationFailedException;
import jakarta.mail.MessagingException;
import jakarta.mail.NoSuchProviderException;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.MimeMessage;
import org.springframework.lang.Nullable;
import org.springframework.mail.MailAuthenticationException;
@ -49,7 +49,7 @@ import org.springframework.util.Assert;
* plain {@link org.springframework.mail.MailSender} implementation.
*
* <p>Allows for defining all settings locally as bean properties.
* Alternatively, a pre-configured JavaMail {@link javax.mail.Session} can be
* Alternatively, a pre-configured JavaMail {@link jakarta.mail.Session} can be
* specified, possibly pulled from an application server's JNDI environment.
*
* <p>Non-default properties in this object will always override the settings
@ -59,8 +59,8 @@ import org.springframework.util.Assert;
* @author Dmitriy Kopylenko
* @author Juergen Hoeller
* @since 10.09.2003
* @see javax.mail.internet.MimeMessage
* @see javax.mail.Session
* @see jakarta.mail.internet.MimeMessage
* @see jakarta.mail.Session
* @see #setSession
* @see #setJavaMailProperties
* @see #setHost
@ -523,7 +523,7 @@ public class JavaMailSenderImpl implements JavaMailSender {
* Obtain a Transport object from the given JavaMail Session,
* using the configured protocol.
* <p>Can be overridden in subclasses, e.g. to return a mock Transport object.
* @see javax.mail.Session#getTransport(String)
* @see jakarta.mail.Session#getTransport(String)
* @see #getSession()
* @see #getProtocol()
*/

View File

@ -18,8 +18,8 @@ package org.springframework.mail.javamail;
import java.util.Date;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.springframework.mail.MailMessage;
import org.springframework.mail.MailParseException;
@ -35,7 +35,7 @@ import org.springframework.mail.MailParseException;
* @author Juergen Hoeller
* @since 1.1.5
* @see MimeMessageHelper
* @see javax.mail.internet.MimeMessage
* @see jakarta.mail.internet.MimeMessage
*/
public class MimeMailMessage implements MailMessage {

View File

@ -23,20 +23,20 @@ import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.FileTypeMap;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
import javax.mail.internet.MimeUtility;
import jakarta.activation.DataHandler;
import jakarta.activation.DataSource;
import jakarta.activation.FileDataSource;
import jakarta.activation.FileTypeMap;
import jakarta.mail.BodyPart;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
import jakarta.mail.internet.MimePart;
import jakarta.mail.internet.MimeUtility;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
@ -44,7 +44,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Helper class for populating a {@link javax.mail.internet.MimeMessage}.
* Helper class for populating a {@link jakarta.mail.internet.MimeMessage}.
*
* <p>Mirrors the simple setters of {@link org.springframework.mail.SimpleMailMessage},
* directly applying the values to the underlying MimeMessage. Allows for defining
@ -186,8 +186,8 @@ public class MimeMessageHelper {
* the passed-in MimeMessage object, if carried there. Else,
* JavaMail's default encoding will be used.
* @param mimeMessage the mime message to work on
* @see #MimeMessageHelper(javax.mail.internet.MimeMessage, boolean)
* @see #getDefaultEncoding(javax.mail.internet.MimeMessage)
* @see #MimeMessageHelper(jakarta.mail.internet.MimeMessage, boolean)
* @see #getDefaultEncoding(jakarta.mail.internet.MimeMessage)
* @see JavaMailSenderImpl#setDefaultEncoding
*/
public MimeMessageHelper(MimeMessage mimeMessage) {
@ -200,7 +200,7 @@ public class MimeMessageHelper {
* i.e. no alternative texts and no inline elements or attachments).
* @param mimeMessage the mime message to work on
* @param encoding the character encoding to use for the message
* @see #MimeMessageHelper(javax.mail.internet.MimeMessage, boolean)
* @see #MimeMessageHelper(jakarta.mail.internet.MimeMessage, boolean)
*/
public MimeMessageHelper(MimeMessage mimeMessage, @Nullable String encoding) {
this.mimeMessage = mimeMessage;
@ -223,8 +223,8 @@ public class MimeMessageHelper {
* supports alternative texts, inline elements and attachments
* (corresponds to MULTIPART_MODE_MIXED_RELATED)
* @throws MessagingException if multipart creation failed
* @see #MimeMessageHelper(javax.mail.internet.MimeMessage, int)
* @see #getDefaultEncoding(javax.mail.internet.MimeMessage)
* @see #MimeMessageHelper(jakarta.mail.internet.MimeMessage, int)
* @see #getDefaultEncoding(jakarta.mail.internet.MimeMessage)
* @see JavaMailSenderImpl#setDefaultEncoding
*/
public MimeMessageHelper(MimeMessage mimeMessage, boolean multipart) throws MessagingException {
@ -244,7 +244,7 @@ public class MimeMessageHelper {
* (corresponds to MULTIPART_MODE_MIXED_RELATED)
* @param encoding the character encoding to use for the message
* @throws MessagingException if multipart creation failed
* @see #MimeMessageHelper(javax.mail.internet.MimeMessage, int, String)
* @see #MimeMessageHelper(jakarta.mail.internet.MimeMessage, int, String)
*/
public MimeMessageHelper(MimeMessage mimeMessage, boolean multipart, @Nullable String encoding)
throws MessagingException {
@ -267,7 +267,7 @@ public class MimeMessageHelper {
* @see #MULTIPART_MODE_MIXED
* @see #MULTIPART_MODE_RELATED
* @see #MULTIPART_MODE_MIXED_RELATED
* @see #getDefaultEncoding(javax.mail.internet.MimeMessage)
* @see #getDefaultEncoding(jakarta.mail.internet.MimeMessage)
* @see JavaMailSenderImpl#setDefaultEncoding
*/
public MimeMessageHelper(MimeMessage mimeMessage, int multipartMode) throws MessagingException {
@ -388,7 +388,7 @@ public class MimeMessageHelper {
* @throws IllegalStateException if this helper is not in multipart mode
* @see #isMultipart
* @see #getMimeMessage
* @see javax.mail.internet.MimeMultipart#addBodyPart
* @see jakarta.mail.internet.MimeMultipart#addBodyPart
*/
public final MimeMultipart getRootMimeMultipart() throws IllegalStateException {
if (this.rootMimeMultipart == null) {
@ -407,7 +407,7 @@ public class MimeMessageHelper {
* @throws IllegalStateException if this helper is not in multipart mode
* @see #isMultipart
* @see #getRootMimeMultipart
* @see javax.mail.internet.MimeMultipart#addBodyPart
* @see jakarta.mail.internet.MimeMultipart#addBodyPart
*/
public final MimeMultipart getMimeMultipart() throws IllegalStateException {
if (this.mimeMultipart == null) {
@ -469,9 +469,9 @@ public class MimeMessageHelper {
* {@code FileTypeMap} instance else.
* @see #addInline
* @see #addAttachment
* @see #getDefaultFileTypeMap(javax.mail.internet.MimeMessage)
* @see #getDefaultFileTypeMap(jakarta.mail.internet.MimeMessage)
* @see JavaMailSenderImpl#setDefaultFileTypeMap
* @see javax.activation.FileTypeMap#getDefaultFileTypeMap
* @see jakarta.activation.FileTypeMap#getDefaultFileTypeMap
* @see ConfigurableMimeFileTypeMap
*/
public void setFileTypeMap(@Nullable FileTypeMap fileTypeMap) {
@ -538,7 +538,7 @@ public class MimeMessageHelper {
* @param address the address to validate
* @throws AddressException if validation failed
* @see #isValidateAddresses()
* @see javax.mail.internet.InternetAddress#validate()
* @see jakarta.mail.internet.InternetAddress#validate()
*/
protected void validateAddress(InternetAddress address) throws AddressException {
if (isValidateAddresses()) {
@ -889,7 +889,7 @@ public class MimeMessageHelper {
/**
* Add an inline element to the MimeMessage, taking the content from a
* {@code javax.activation.DataSource}.
* {@code jakarta.activation.DataSource}.
* <p>Note that the InputStream returned by the DataSource implementation
* needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
* {@code getInputStream()} multiple times.
@ -898,7 +898,7 @@ public class MimeMessageHelper {
* @param contentId the content ID to use. Will end up as "Content-ID" header
* in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
* Can be referenced in HTML source via src="cid:myId" expressions.
* @param dataSource the {@code javax.activation.DataSource} to take
* @param dataSource the {@code jakarta.activation.DataSource} to take
* the content from, determining the InputStream and the content type
* @throws MessagingException in case of errors
* @see #addInline(String, java.io.File)
@ -929,7 +929,7 @@ public class MimeMessageHelper {
* @throws MessagingException in case of errors
* @see #setText
* @see #addInline(String, org.springframework.core.io.Resource)
* @see #addInline(String, javax.activation.DataSource)
* @see #addInline(String, jakarta.activation.DataSource)
*/
public void addInline(String contentId, File file) throws MessagingException {
Assert.notNull(file, "File must not be null");
@ -956,7 +956,7 @@ public class MimeMessageHelper {
* @throws MessagingException in case of errors
* @see #setText
* @see #addInline(String, java.io.File)
* @see #addInline(String, javax.activation.DataSource)
* @see #addInline(String, jakarta.activation.DataSource)
*/
public void addInline(String contentId, Resource resource) throws MessagingException {
Assert.notNull(resource, "Resource must not be null");
@ -984,7 +984,7 @@ public class MimeMessageHelper {
* @see #setText
* @see #getFileTypeMap
* @see #addInline(String, org.springframework.core.io.Resource)
* @see #addInline(String, javax.activation.DataSource)
* @see #addInline(String, jakarta.activation.DataSource)
*/
public void addInline(String contentId, InputStreamSource inputStreamSource, String contentType)
throws MessagingException {
@ -1001,13 +1001,13 @@ public class MimeMessageHelper {
/**
* Add an attachment to the MimeMessage, taking the content from a
* {@code javax.activation.DataSource}.
* {@code jakarta.activation.DataSource}.
* <p>Note that the InputStream returned by the DataSource implementation
* needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
* {@code getInputStream()} multiple times.
* @param attachmentFilename the name of the attachment as it will
* appear in the mail (the content type will be determined by this)
* @param dataSource the {@code javax.activation.DataSource} to take
* @param dataSource the {@code jakarta.activation.DataSource} to take
* the content from, determining the InputStream and the content type
* @throws MessagingException in case of errors
* @see #addAttachment(String, org.springframework.core.io.InputStreamSource)
@ -1040,7 +1040,7 @@ public class MimeMessageHelper {
* @param file the File resource to take the content from
* @throws MessagingException in case of errors
* @see #addAttachment(String, org.springframework.core.io.InputStreamSource)
* @see #addAttachment(String, javax.activation.DataSource)
* @see #addAttachment(String, jakarta.activation.DataSource)
*/
public void addAttachment(String attachmentFilename, File file) throws MessagingException {
Assert.notNull(file, "File must not be null");
@ -1064,7 +1064,7 @@ public class MimeMessageHelper {
* (all of Spring's Resource implementations can be passed in here)
* @throws MessagingException in case of errors
* @see #addAttachment(String, java.io.File)
* @see #addAttachment(String, javax.activation.DataSource)
* @see #addAttachment(String, jakarta.activation.DataSource)
* @see org.springframework.core.io.Resource
*/
public void addAttachment(String attachmentFilename, InputStreamSource inputStreamSource)
@ -1087,7 +1087,7 @@ public class MimeMessageHelper {
* @param contentType the content type to use for the element
* @throws MessagingException in case of errors
* @see #addAttachment(String, java.io.File)
* @see #addAttachment(String, javax.activation.DataSource)
* @see #addAttachment(String, jakarta.activation.DataSource)
* @see org.springframework.core.io.Resource
*/
public void addAttachment(
@ -1121,7 +1121,7 @@ public class MimeMessageHelper {
}
@Override
public OutputStream getOutputStream() {
throw new UnsupportedOperationException("Read-only javax.activation.DataSource");
throw new UnsupportedOperationException("Read-only jakarta.activation.DataSource");
}
@Override
public String getContentType() {

View File

@ -16,7 +16,7 @@
package org.springframework.mail.javamail;
import javax.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMessage;
/**
* Callback interface for the preparation of JavaMail MIME messages.
@ -42,7 +42,7 @@ public interface MimeMessagePreparator {
/**
* Prepare the given new MimeMessage instance.
* @param mimeMessage the message to prepare
* @throws javax.mail.MessagingException passing any exceptions thrown by MimeMessage
* @throws jakarta.mail.MessagingException passing any exceptions thrown by MimeMessage
* methods through for automatic conversion to the MailException hierarchy
* @throws java.io.IOException passing any exceptions thrown by MimeMessage methods
* through for automatic conversion to the MailException hierarchy

View File

@ -16,9 +16,9 @@
package org.springframework.mail.javamail;
import javax.activation.FileTypeMap;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import jakarta.activation.FileTypeMap;
import jakarta.mail.Session;
import jakarta.mail.internet.MimeMessage;
import org.springframework.lang.Nullable;
@ -34,8 +34,8 @@ import org.springframework.lang.Nullable;
* @author Juergen Hoeller
* @since 1.2
* @see JavaMailSenderImpl#createMimeMessage()
* @see MimeMessageHelper#getDefaultEncoding(javax.mail.internet.MimeMessage)
* @see MimeMessageHelper#getDefaultFileTypeMap(javax.mail.internet.MimeMessage)
* @see MimeMessageHelper#getDefaultEncoding(jakarta.mail.internet.MimeMessage)
* @see MimeMessageHelper#getDefaultFileTypeMap(jakarta.mail.internet.MimeMessage)
*/
class SmartMimeMessage extends MimeMessage {

View File

@ -1,58 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.commonj;
import commonj.timers.Timer;
import commonj.timers.TimerListener;
import org.springframework.util.Assert;
/**
* Simple TimerListener adapter that delegates to a given Runnable.
*
* @author Juergen Hoeller
* @since 2.0
* @see commonj.timers.TimerListener
* @see java.lang.Runnable
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public class DelegatingTimerListener implements TimerListener {
private final Runnable runnable;
/**
* Create a new DelegatingTimerListener.
* @param runnable the Runnable implementation to delegate to
*/
public DelegatingTimerListener(Runnable runnable) {
Assert.notNull(runnable, "Runnable is required");
this.runnable = runnable;
}
/**
* Delegates execution to the underlying Runnable.
*/
@Override
public void timerExpired(Timer timer) {
this.runnable.run();
}
}

View File

@ -1,85 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.commonj;
import commonj.work.Work;
import org.springframework.scheduling.SchedulingAwareRunnable;
import org.springframework.util.Assert;
/**
* Simple Work adapter that delegates to a given Runnable.
*
* @author Juergen Hoeller
* @since 2.0
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor}
*/
@Deprecated
public class DelegatingWork implements Work {
private final Runnable delegate;
/**
* Create a new DelegatingWork.
* @param delegate the Runnable implementation to delegate to
* (may be a SchedulingAwareRunnable for extended support)
* @see org.springframework.scheduling.SchedulingAwareRunnable
* @see #isDaemon()
*/
public DelegatingWork(Runnable delegate) {
Assert.notNull(delegate, "Delegate must not be null");
this.delegate = delegate;
}
/**
* Return the wrapped Runnable implementation.
*/
public final Runnable getDelegate() {
return this.delegate;
}
/**
* Delegates execution to the underlying Runnable.
*/
@Override
public void run() {
this.delegate.run();
}
/**
* This implementation delegates to
* {@link org.springframework.scheduling.SchedulingAwareRunnable#isLongLived()},
* if available.
*/
@Override
public boolean isDaemon() {
return (this.delegate instanceof SchedulingAwareRunnable &&
((SchedulingAwareRunnable) this.delegate).isLongLived());
}
/**
* This implementation is empty, since we expect the Runnable
* to terminate based on some specific shutdown signal.
*/
@Override
public void release() {
}
}

View File

@ -1,229 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.commonj;
import commonj.timers.TimerListener;
import org.springframework.lang.Nullable;
/**
* JavaBean that describes a scheduled TimerListener, consisting of
* the TimerListener itself (or a Runnable to create a TimerListener for)
* and a delay plus period. Period needs to be specified;
* there is no point in a default for it.
*
* <p>The CommonJ TimerManager does not offer more sophisticated scheduling
* options such as cron expressions. Consider using Quartz for such
* advanced needs.
*
* <p>Note that the TimerManager uses a TimerListener instance that is
* shared between repeated executions, in contrast to Quartz which
* instantiates a new Job for each execution.
*
* @author Juergen Hoeller
* @since 2.0
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public class ScheduledTimerListener {
@Nullable
private TimerListener timerListener;
private long delay = 0;
private long period = -1;
private boolean fixedRate = false;
/**
* Create a new ScheduledTimerListener,
* to be populated via bean properties.
* @see #setTimerListener
* @see #setDelay
* @see #setPeriod
* @see #setFixedRate
*/
public ScheduledTimerListener() {
}
/**
* Create a new ScheduledTimerListener, with default
* one-time execution without delay.
* @param timerListener the TimerListener to schedule
*/
public ScheduledTimerListener(TimerListener timerListener) {
this.timerListener = timerListener;
}
/**
* Create a new ScheduledTimerListener, with default
* one-time execution with the given delay.
* @param timerListener the TimerListener to schedule
* @param delay the delay before starting the task for the first time (ms)
*/
public ScheduledTimerListener(TimerListener timerListener, long delay) {
this.timerListener = timerListener;
this.delay = delay;
}
/**
* Create a new ScheduledTimerListener.
* @param timerListener the TimerListener to schedule
* @param delay the delay before starting the task for the first time (ms)
* @param period the period between repeated task executions (ms)
* @param fixedRate whether to schedule as fixed-rate execution
*/
public ScheduledTimerListener(TimerListener timerListener, long delay, long period, boolean fixedRate) {
this.timerListener = timerListener;
this.delay = delay;
this.period = period;
this.fixedRate = fixedRate;
}
/**
* Create a new ScheduledTimerListener, with default
* one-time execution without delay.
* @param timerTask the Runnable to schedule as TimerListener
*/
public ScheduledTimerListener(Runnable timerTask) {
setRunnable(timerTask);
}
/**
* Create a new ScheduledTimerListener, with default
* one-time execution with the given delay.
* @param timerTask the Runnable to schedule as TimerListener
* @param delay the delay before starting the task for the first time (ms)
*/
public ScheduledTimerListener(Runnable timerTask, long delay) {
setRunnable(timerTask);
this.delay = delay;
}
/**
* Create a new ScheduledTimerListener.
* @param timerTask the Runnable to schedule as TimerListener
* @param delay the delay before starting the task for the first time (ms)
* @param period the period between repeated task executions (ms)
* @param fixedRate whether to schedule as fixed-rate execution
*/
public ScheduledTimerListener(Runnable timerTask, long delay, long period, boolean fixedRate) {
setRunnable(timerTask);
this.delay = delay;
this.period = period;
this.fixedRate = fixedRate;
}
/**
* Set the Runnable to schedule as TimerListener.
* @see DelegatingTimerListener
*/
public void setRunnable(Runnable timerTask) {
this.timerListener = new DelegatingTimerListener(timerTask);
}
/**
* Set the TimerListener to schedule.
*/
public void setTimerListener(@Nullable TimerListener timerListener) {
this.timerListener = timerListener;
}
/**
* Return the TimerListener to schedule.
*/
@Nullable
public TimerListener getTimerListener() {
return this.timerListener;
}
/**
* Set the delay before starting the task for the first time,
* in milliseconds. Default is 0, immediately starting the
* task after successful scheduling.
* <p>If the "firstTime" property is specified, this property will be ignored.
* Specify one or the other, not both.
*/
public void setDelay(long delay) {
this.delay = delay;
}
/**
* Return the delay before starting the job for the first time.
*/
public long getDelay() {
return this.delay;
}
/**
* Set the period between repeated task executions, in milliseconds.
* <p>Default is -1, leading to one-time execution. In case of zero or a
* positive value, the task will be executed repeatedly, with the given
* interval in-between executions.
* <p>Note that the semantics of the period value vary between fixed-rate
* and fixed-delay execution.
* <p><b>Note:</b> A period of 0 (for example as fixed delay) <i>is</i>
* supported, because the CommonJ specification defines this as a legal value.
* Hence a value of 0 will result in immediate re-execution after a job has
* finished (not in one-time execution like with {@code java.util.Timer}).
* @see #setFixedRate
* @see #isOneTimeTask()
* @see commonj.timers.TimerManager#schedule(commonj.timers.TimerListener, long, long)
*/
public void setPeriod(long period) {
this.period = period;
}
/**
* Return the period between repeated task executions.
*/
public long getPeriod() {
return this.period;
}
/**
* Is this task only ever going to execute once?
* @return {@code true} if this task is only ever going to execute once
* @see #getPeriod()
*/
public boolean isOneTimeTask() {
return (this.period < 0);
}
/**
* Set whether to schedule as fixed-rate execution, rather than
* fixed-delay execution. Default is "false", i.e. fixed delay.
* <p>See TimerManager javadoc for details on those execution modes.
* @see commonj.timers.TimerManager#schedule(commonj.timers.TimerListener, long, long)
* @see commonj.timers.TimerManager#scheduleAtFixedRate(commonj.timers.TimerListener, long, long)
*/
public void setFixedRate(boolean fixedRate) {
this.fixedRate = fixedRate;
}
/**
* Return whether to schedule as fixed-rate execution.
*/
public boolean isFixedRate() {
return this.fixedRate;
}
}

View File

@ -1,192 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.commonj;
import javax.naming.NamingException;
import commonj.timers.TimerManager;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Lifecycle;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Base class for classes that are accessing a CommonJ {@link commonj.timers.TimerManager}
* Defines common configuration settings and common lifecycle handling.
*
* @author Juergen Hoeller
* @since 3.0
* @see commonj.timers.TimerManager
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public abstract class TimerManagerAccessor extends JndiLocatorSupport
implements InitializingBean, DisposableBean, Lifecycle {
@Nullable
private TimerManager timerManager;
@Nullable
private String timerManagerName;
private boolean shared = false;
/**
* Specify the CommonJ TimerManager to delegate to.
* <p>Note that the given TimerManager's lifecycle will be managed
* by this FactoryBean.
* <p>Alternatively (and typically), you can specify the JNDI name
* of the target TimerManager.
* @see #setTimerManagerName
*/
public void setTimerManager(TimerManager timerManager) {
this.timerManager = timerManager;
}
/**
* Set the JNDI name of the CommonJ TimerManager.
* <p>This can either be a fully qualified JNDI name, or the JNDI name relative
* to the current environment naming context if "resourceRef" is set to "true".
* @see #setTimerManager
* @see #setResourceRef
*/
public void setTimerManagerName(String timerManagerName) {
this.timerManagerName = timerManagerName;
}
/**
* Specify whether the TimerManager obtained by this FactoryBean
* is a shared instance ("true") or an independent instance ("false").
* The lifecycle of the former is supposed to be managed by the application
* server, while the lifecycle of the latter is up to the application.
* <p>Default is "false", i.e. managing an independent TimerManager instance.
* This is what the CommonJ specification suggests that application servers
* are supposed to offer via JNDI lookups, typically declared as a
* {@code resource-ref} of type {@code commonj.timers.TimerManager}
* in {@code web.xml}, with {@code res-sharing-scope} set to 'Unshareable'.
* <p>Switch this flag to "true" if you are obtaining a shared TimerManager,
* typically through specifying the JNDI location of a TimerManager that
* has been explicitly declared as 'Shareable'. Note that WebLogic's
* cluster-aware Job Scheduler is a shared TimerManager too.
* <p>The sole difference between this FactoryBean being in shared or
* non-shared mode is that it will only attempt to suspend / resume / stop
* the underlying TimerManager in case of an independent (non-shared) instance.
* This only affects the {@link org.springframework.context.Lifecycle} support
* as well as application context shutdown.
* @see #stop()
* @see #start()
* @see #destroy()
* @see commonj.timers.TimerManager
*/
public void setShared(boolean shared) {
this.shared = shared;
}
@Override
public void afterPropertiesSet() throws NamingException {
if (this.timerManager == null) {
if (this.timerManagerName == null) {
throw new IllegalArgumentException("Either 'timerManager' or 'timerManagerName' must be specified");
}
this.timerManager = lookup(this.timerManagerName, TimerManager.class);
}
}
/**
* Return the configured TimerManager, if any.
* @return the TimerManager, or {@code null} if not available
*/
@Nullable
protected final TimerManager getTimerManager() {
return this.timerManager;
}
/**
* Obtain the TimerManager for actual use.
* @return the TimerManager (never {@code null})
* @throws IllegalStateException in case of no TimerManager set
* @since 5.0
*/
protected TimerManager obtainTimerManager() {
Assert.notNull(this.timerManager, "No TimerManager set");
return this.timerManager;
}
//---------------------------------------------------------------------
// Implementation of Lifecycle interface
//---------------------------------------------------------------------
/**
* Resumes the underlying TimerManager (if not shared).
* @see commonj.timers.TimerManager#resume()
*/
@Override
public void start() {
if (!this.shared) {
obtainTimerManager().resume();
}
}
/**
* Suspends the underlying TimerManager (if not shared).
* @see commonj.timers.TimerManager#suspend()
*/
@Override
public void stop() {
if (!this.shared) {
obtainTimerManager().suspend();
}
}
/**
* Considers the underlying TimerManager as running if it is
* neither suspending nor stopping.
* @see commonj.timers.TimerManager#isSuspending()
* @see commonj.timers.TimerManager#isStopping()
*/
@Override
public boolean isRunning() {
TimerManager tm = obtainTimerManager();
return (!tm.isSuspending() && !tm.isStopping());
}
//---------------------------------------------------------------------
// Implementation of DisposableBean interface
//---------------------------------------------------------------------
/**
* Stops the underlying TimerManager (if not shared).
* @see commonj.timers.TimerManager#stop()
*/
@Override
public void destroy() {
// Stop the entire TimerManager, if necessary.
if (this.timerManager != null && !this.shared) {
// May return early, but at least we already cancelled all known Timers.
this.timerManager.stop();
}
}
}

View File

@ -1,165 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.commonj;
import java.util.ArrayList;
import java.util.List;
import javax.naming.NamingException;
import commonj.timers.Timer;
import commonj.timers.TimerManager;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Lifecycle;
import org.springframework.lang.Nullable;
/**
* {@link org.springframework.beans.factory.FactoryBean} that retrieves a
* CommonJ {@link commonj.timers.TimerManager} and exposes it for bean references.
*
* <p><b>This is the central convenience class for setting up a
* CommonJ TimerManager in a Spring context.</b>
*
* <p>Allows for registration of ScheduledTimerListeners. This is the main
* purpose of this class; the TimerManager itself could also be fetched
* from JNDI via {@link org.springframework.jndi.JndiObjectFactoryBean}.
* In scenarios that just require static registration of tasks at startup,
* there is no need to access the TimerManager itself in application code.
*
* <p>Note that the TimerManager uses a TimerListener instance that is
* shared between repeated executions, in contrast to Quartz which
* instantiates a new Job for each execution.
*
* @author Juergen Hoeller
* @since 2.0
* @see ScheduledTimerListener
* @see commonj.timers.TimerManager
* @see commonj.timers.TimerListener
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public class TimerManagerFactoryBean extends TimerManagerAccessor
implements FactoryBean<TimerManager>, InitializingBean, DisposableBean, Lifecycle {
@Nullable
private ScheduledTimerListener[] scheduledTimerListeners;
@Nullable
private List<Timer> timers;
/**
* Register a list of ScheduledTimerListener objects with the TimerManager
* that this FactoryBean creates. Depending on each ScheduledTimerListener's settings,
* it will be registered via one of TimerManager's schedule methods.
* @see commonj.timers.TimerManager#schedule(commonj.timers.TimerListener, long)
* @see commonj.timers.TimerManager#schedule(commonj.timers.TimerListener, long, long)
* @see commonj.timers.TimerManager#scheduleAtFixedRate(commonj.timers.TimerListener, long, long)
*/
public void setScheduledTimerListeners(ScheduledTimerListener[] scheduledTimerListeners) {
this.scheduledTimerListeners = scheduledTimerListeners;
}
//---------------------------------------------------------------------
// Implementation of InitializingBean interface
//---------------------------------------------------------------------
@Override
public void afterPropertiesSet() throws NamingException {
super.afterPropertiesSet();
if (this.scheduledTimerListeners != null) {
this.timers = new ArrayList<>(this.scheduledTimerListeners.length);
TimerManager timerManager = obtainTimerManager();
for (ScheduledTimerListener scheduledTask : this.scheduledTimerListeners) {
Timer timer;
if (scheduledTask.isOneTimeTask()) {
timer = timerManager.schedule(scheduledTask.getTimerListener(), scheduledTask.getDelay());
}
else {
if (scheduledTask.isFixedRate()) {
timer = timerManager.scheduleAtFixedRate(
scheduledTask.getTimerListener(), scheduledTask.getDelay(), scheduledTask.getPeriod());
}
else {
timer = timerManager.schedule(
scheduledTask.getTimerListener(), scheduledTask.getDelay(), scheduledTask.getPeriod());
}
}
this.timers.add(timer);
}
}
}
//---------------------------------------------------------------------
// Implementation of FactoryBean interface
//---------------------------------------------------------------------
@Override
@Nullable
public TimerManager getObject() {
return getTimerManager();
}
@Override
public Class<? extends TimerManager> getObjectType() {
TimerManager timerManager = getTimerManager();
return (timerManager != null ? timerManager.getClass() : TimerManager.class);
}
@Override
public boolean isSingleton() {
return true;
}
//---------------------------------------------------------------------
// Implementation of DisposableBean interface
//---------------------------------------------------------------------
/**
* Cancels all statically registered Timers on shutdown,
* and stops the underlying TimerManager (if not shared).
* @see commonj.timers.Timer#cancel()
* @see commonj.timers.TimerManager#stop()
*/
@Override
public void destroy() {
// Cancel all registered timers.
if (this.timers != null) {
for (Timer timer : this.timers) {
try {
timer.cancel();
}
catch (Throwable ex) {
logger.debug("Could not cancel CommonJ Timer", ex);
}
}
this.timers.clear();
}
// Stop the TimerManager itself.
super.destroy();
}
}

View File

@ -1,201 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.commonj;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import commonj.timers.Timer;
import commonj.timers.TimerListener;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.SimpleTriggerContext;
import org.springframework.scheduling.support.TaskUtils;
import org.springframework.util.Assert;
import org.springframework.util.ErrorHandler;
/**
* Implementation of Spring's {@link TaskScheduler} interface, wrapping
* a CommonJ {@link commonj.timers.TimerManager}.
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 3.0
* @deprecated as of 5.1, in favor of EE 7's
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler}
*/
@Deprecated
public class TimerManagerTaskScheduler extends TimerManagerAccessor implements TaskScheduler {
@Nullable
private volatile ErrorHandler errorHandler;
/**
* Provide an {@link ErrorHandler} strategy.
*/
public void setErrorHandler(ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
@Override
@Nullable
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
return new ReschedulingTimerListener(errorHandlingTask(task, true), trigger).schedule();
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, false));
Timer timer = obtainTimerManager().schedule(futureTask, startTime);
futureTask.setTimer(timer);
return futureTask;
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
Timer timer = obtainTimerManager().scheduleAtFixedRate(futureTask, startTime, period);
futureTask.setTimer(timer);
return futureTask;
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
Timer timer = obtainTimerManager().scheduleAtFixedRate(futureTask, 0, period);
futureTask.setTimer(timer);
return futureTask;
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
Timer timer = obtainTimerManager().schedule(futureTask, startTime, delay);
futureTask.setTimer(timer);
return futureTask;
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
TimerScheduledFuture futureTask = new TimerScheduledFuture(errorHandlingTask(task, true));
Timer timer = obtainTimerManager().schedule(futureTask, 0, delay);
futureTask.setTimer(timer);
return futureTask;
}
private Runnable errorHandlingTask(Runnable delegate, boolean isRepeatingTask) {
return TaskUtils.decorateTaskWithErrorHandler(delegate, this.errorHandler, isRepeatingTask);
}
/**
* ScheduledFuture adapter that wraps a CommonJ Timer.
*/
private static class TimerScheduledFuture extends FutureTask<Object> implements TimerListener, ScheduledFuture<Object> {
@Nullable
protected transient Timer timer;
protected transient boolean cancelled = false;
public TimerScheduledFuture(Runnable runnable) {
super(runnable, null);
}
public void setTimer(Timer timer) {
this.timer = timer;
}
@Override
public void timerExpired(Timer timer) {
runAndReset();
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean result = super.cancel(mayInterruptIfRunning);
if (this.timer != null) {
this.timer.cancel();
}
this.cancelled = true;
return result;
}
@Override
public long getDelay(TimeUnit unit) {
Assert.state(this.timer != null, "No Timer available");
return unit.convert(this.timer.getScheduledExecutionTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed other) {
if (this == other) {
return 0;
}
long diff = getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS);
return (diff == 0 ? 0 : ((diff < 0) ? -1 : 1));
}
}
/**
* ScheduledFuture adapter for trigger-based rescheduling.
*/
private class ReschedulingTimerListener extends TimerScheduledFuture {
private final Trigger trigger;
private final SimpleTriggerContext triggerContext = new SimpleTriggerContext();
private volatile Date scheduledExecutionTime = new Date();
public ReschedulingTimerListener(Runnable runnable, Trigger trigger) {
super(runnable);
this.trigger = trigger;
}
@Nullable
public ScheduledFuture<?> schedule() {
Date nextExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
if (nextExecutionTime == null) {
return null;
}
this.scheduledExecutionTime = nextExecutionTime;
setTimer(obtainTimerManager().schedule(this, this.scheduledExecutionTime));
return this;
}
@Override
public void timerExpired(Timer timer) {
Date actualExecutionTime = new Date();
super.timerExpired(timer);
Date completionTime = new Date();
this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
if (!this.cancelled) {
schedule();
}
}
}
}

View File

@ -1,234 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.scheduling.commonj;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import javax.naming.NamingException;
import commonj.work.Work;
import commonj.work.WorkException;
import commonj.work.WorkItem;
import commonj.work.WorkListener;
import commonj.work.WorkManager;
import commonj.work.WorkRejectedException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.TaskDecorator;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.util.Assert;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
/**
* TaskExecutor implementation that delegates to a CommonJ WorkManager,
* implementing the {@link commonj.work.WorkManager} interface,
* which either needs to be specified as reference or through the JNDI name.
*
* <p><b>This is the central convenience class for setting up a
* CommonJ WorkManager in a Spring context.</b>
*
* <p>Also implements the CommonJ WorkManager interface itself, delegating all
* calls to the target WorkManager. Hence, a caller can choose whether it wants
* to talk to this executor through the Spring TaskExecutor interface or the
* CommonJ WorkManager interface.
*
* <p>The CommonJ WorkManager will usually be retrieved from the application
* server's JNDI environment, as defined in the server's management console.
*
* <p>Note: On EE 7/8 compliant versions of WebLogic and WebSphere, a
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor}
* should be preferred, following JSR-236 support in Java EE 7/8.
*
* @author Juergen Hoeller
* @since 2.0
* @deprecated as of 5.1, in favor of the EE 7/8 based
* {@link org.springframework.scheduling.concurrent.DefaultManagedTaskExecutor}
*/
@Deprecated
public class WorkManagerTaskExecutor extends JndiLocatorSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, WorkManager, InitializingBean {
@Nullable
private WorkManager workManager;
@Nullable
private String workManagerName;
@Nullable
private WorkListener workListener;
@Nullable
private TaskDecorator taskDecorator;
/**
* Specify the CommonJ WorkManager to delegate to.
* <p>Alternatively, you can also specify the JNDI name of the target WorkManager.
* @see #setWorkManagerName
*/
public void setWorkManager(WorkManager workManager) {
this.workManager = workManager;
}
/**
* Set the JNDI name of the CommonJ WorkManager.
* <p>This can either be a fully qualified JNDI name, or the JNDI name relative
* to the current environment naming context if "resourceRef" is set to "true".
* @see #setWorkManager
* @see #setResourceRef
*/
public void setWorkManagerName(String workManagerName) {
this.workManagerName = workManagerName;
}
/**
* Specify a CommonJ WorkListener to apply, if any.
* <p>This shared WorkListener instance will be passed on to the
* WorkManager by all {@link #execute} calls on this TaskExecutor.
*/
public void setWorkListener(WorkListener workListener) {
this.workListener = workListener;
}
/**
* Specify a custom {@link TaskDecorator} to be applied to any {@link Runnable}
* about to be executed.
* <p>Note that such a decorator is not necessarily being applied to the
* user-supplied {@code Runnable}/{@code Callable} but rather to the actual
* execution callback (which may be a wrapper around the user-supplied task).
* <p>The primary use case is to set some execution context around the task's
* invocation, or to provide some monitoring/statistics for task execution.
* <p><b>NOTE:</b> Exception handling in {@code TaskDecorator} implementations
* is limited to plain {@code Runnable} execution via {@code execute} calls.
* In case of {@code #submit} calls, the exposed {@code Runnable} will be a
* {@code FutureTask} which does not propagate any exceptions; you might
* have to cast it and call {@code Future#get} to evaluate exceptions.
* @since 4.3
*/
public void setTaskDecorator(TaskDecorator taskDecorator) {
this.taskDecorator = taskDecorator;
}
@Override
public void afterPropertiesSet() throws NamingException {
if (this.workManager == null) {
if (this.workManagerName == null) {
throw new IllegalArgumentException("Either 'workManager' or 'workManagerName' must be specified");
}
this.workManager = lookup(this.workManagerName, WorkManager.class);
}
}
private WorkManager obtainWorkManager() {
Assert.state(this.workManager != null, "No WorkManager specified");
return this.workManager;
}
//-------------------------------------------------------------------------
// Implementation of the Spring SchedulingTaskExecutor interface
//-------------------------------------------------------------------------
@Override
public void execute(Runnable task) {
Work work = new DelegatingWork(this.taskDecorator != null ? this.taskDecorator.decorate(task) : task);
try {
if (this.workListener != null) {
obtainWorkManager().schedule(work, this.workListener);
}
else {
obtainWorkManager().schedule(work);
}
}
catch (WorkRejectedException ex) {
throw new TaskRejectedException("CommonJ WorkManager did not accept task: " + task, ex);
}
catch (WorkException ex) {
throw new SchedulingException("Could not schedule task on CommonJ WorkManager", ex);
}
}
@Override
public void execute(Runnable task, long startTimeout) {
execute(task);
}
@Override
public Future<?> submit(Runnable task) {
FutureTask<Object> future = new FutureTask<>(task, null);
execute(future);
return future;
}
@Override
public <T> Future<T> submit(Callable<T> task) {
FutureTask<T> future = new FutureTask<>(task);
execute(future);
return future;
}
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
ListenableFutureTask<Object> future = new ListenableFutureTask<>(task, null);
execute(future);
return future;
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
ListenableFutureTask<T> future = new ListenableFutureTask<>(task);
execute(future);
return future;
}
//-------------------------------------------------------------------------
// Implementation of the CommonJ WorkManager interface
//-------------------------------------------------------------------------
@Override
public WorkItem schedule(Work work) throws WorkException, IllegalArgumentException {
return obtainWorkManager().schedule(work);
}
@Override
public WorkItem schedule(Work work, WorkListener workListener) throws WorkException {
return obtainWorkManager().schedule(work, workListener);
}
@Override
@SuppressWarnings("rawtypes")
public boolean waitForAll(Collection workItems, long timeout) throws InterruptedException {
return obtainWorkManager().waitForAll(workItems, timeout);
}
@Override
@SuppressWarnings("rawtypes")
public Collection waitForAny(Collection workItems, long timeout) throws InterruptedException {
return obtainWorkManager().waitForAny(workItems, timeout);
}
}

View File

@ -1,10 +0,0 @@
/**
* Convenience classes for scheduling based on the CommonJ WorkManager/TimerManager
* facility, as supported by IBM WebSphere 6.0+ and BEA WebLogic 9.0+.
*/
@NonNullApi
@NonNullFields
package org.springframework.scheduling.commonj;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

View File

@ -1,85 +0,0 @@
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.ehcache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManagerTests;
/**
* @author Stephane Nicoll
*/
public class EhCacheCacheManagerTests extends AbstractTransactionSupportingCacheManagerTests<EhCacheCacheManager> {
private CacheManager nativeCacheManager;
private EhCacheCacheManager cacheManager;
private EhCacheCacheManager transactionalCacheManager;
@BeforeEach
public void setup() {
nativeCacheManager = new CacheManager(new Configuration().name("EhCacheCacheManagerTests")
.defaultCache(new CacheConfiguration("default", 100)));
addNativeCache(CACHE_NAME);
cacheManager = new EhCacheCacheManager(nativeCacheManager);
cacheManager.setTransactionAware(false);
cacheManager.afterPropertiesSet();
transactionalCacheManager = new EhCacheCacheManager(nativeCacheManager);
transactionalCacheManager.setTransactionAware(true);
transactionalCacheManager.afterPropertiesSet();
}
@AfterEach
public void shutdown() {
nativeCacheManager.shutdown();
}
@Override
protected EhCacheCacheManager getCacheManager(boolean transactionAware) {
if (transactionAware) {
return transactionalCacheManager;
}
else {
return cacheManager;
}
}
@Override
protected Class<? extends org.springframework.cache.Cache> getCacheType() {
return EhCacheCache.class;
}
@Override
protected void addNativeCache(String cacheName) {
nativeCacheManager.addCache(cacheName);
}
@Override
protected void removeNativeCache(String cacheName) {
nativeCacheManager.removeCache(cacheName);
}
}

View File

@ -1,91 +0,0 @@
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.ehcache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.config.Configuration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.testfixture.cache.AbstractCacheTests;
import org.springframework.core.testfixture.EnabledForTestGroups;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.core.testfixture.TestGroup.LONG_RUNNING;
/**
* @author Costin Leau
* @author Stephane Nicoll
* @author Juergen Hoeller
*/
public class EhCacheCacheTests extends AbstractCacheTests<EhCacheCache> {
private CacheManager cacheManager;
private Ehcache nativeCache;
private EhCacheCache cache;
@BeforeEach
public void setup() {
cacheManager = new CacheManager(new Configuration().name("EhCacheCacheTests")
.defaultCache(new CacheConfiguration("default", 100)));
nativeCache = new net.sf.ehcache.Cache(new CacheConfiguration(CACHE_NAME, 100));
cacheManager.addCache(nativeCache);
cache = new EhCacheCache(nativeCache);
}
@AfterEach
public void shutdown() {
cacheManager.shutdown();
}
@Override
protected EhCacheCache getCache() {
return cache;
}
@Override
protected Ehcache getNativeCache() {
return nativeCache;
}
@Test
@EnabledForTestGroups(LONG_RUNNING)
public void testExpiredElements() throws Exception {
String key = "brancusi";
String value = "constantin";
Element brancusi = new Element(key, value);
// ttl = 10s
brancusi.setTimeToLive(3);
nativeCache.put(brancusi);
assertThat(cache.get(key).get()).isEqualTo(value);
// wait for the entry to expire
Thread.sleep(5 * 1000);
assertThat(cache.get(key)).isNull();
}
}

View File

@ -1,287 +0,0 @@
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.ehcache;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.constructs.blocking.BlockingCache;
import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
import net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory;
import net.sf.ehcache.constructs.blocking.UpdatingSelfPopulatingCache;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Juergen Hoeller
* @author Dmitriy Kopylenko
* @since 27.09.2004
*/
public class EhCacheSupportTests {
@Test
public void testBlankCacheManager() {
EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
cacheManagerFb.setCacheManagerName("myCacheManager");
assertThat(cacheManagerFb.getObjectType()).isEqualTo(CacheManager.class);
assertThat(cacheManagerFb.isSingleton()).as("Singleton property").isTrue();
cacheManagerFb.afterPropertiesSet();
try {
CacheManager cm = cacheManagerFb.getObject();
assertThat(cm.getCacheNames().length == 0).as("Loaded CacheManager with no caches").isTrue();
Cache myCache1 = cm.getCache("myCache1");
assertThat(myCache1 == null).as("No myCache1 defined").isTrue();
}
finally {
cacheManagerFb.destroy();
}
}
@Test
public void testCacheManagerConflict() {
EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
try {
cacheManagerFb.setCacheManagerName("myCacheManager");
assertThat(cacheManagerFb.getObjectType()).isEqualTo(CacheManager.class);
assertThat(cacheManagerFb.isSingleton()).as("Singleton property").isTrue();
cacheManagerFb.afterPropertiesSet();
CacheManager cm = cacheManagerFb.getObject();
assertThat(cm.getCacheNames().length == 0).as("Loaded CacheManager with no caches").isTrue();
Cache myCache1 = cm.getCache("myCache1");
assertThat(myCache1 == null).as("No myCache1 defined").isTrue();
EhCacheManagerFactoryBean cacheManagerFb2 = new EhCacheManagerFactoryBean();
cacheManagerFb2.setCacheManagerName("myCacheManager");
assertThatExceptionOfType(CacheException.class).as("because of naming conflict").isThrownBy(
cacheManagerFb2::afterPropertiesSet);
}
finally {
cacheManagerFb.destroy();
}
}
@Test
public void testAcceptExistingCacheManager() {
EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
cacheManagerFb.setCacheManagerName("myCacheManager");
assertThat(cacheManagerFb.getObjectType()).isEqualTo(CacheManager.class);
assertThat(cacheManagerFb.isSingleton()).as("Singleton property").isTrue();
cacheManagerFb.afterPropertiesSet();
try {
CacheManager cm = cacheManagerFb.getObject();
assertThat(cm.getCacheNames().length == 0).as("Loaded CacheManager with no caches").isTrue();
Cache myCache1 = cm.getCache("myCache1");
assertThat(myCache1 == null).as("No myCache1 defined").isTrue();
EhCacheManagerFactoryBean cacheManagerFb2 = new EhCacheManagerFactoryBean();
cacheManagerFb2.setCacheManagerName("myCacheManager");
cacheManagerFb2.setAcceptExisting(true);
cacheManagerFb2.afterPropertiesSet();
CacheManager cm2 = cacheManagerFb2.getObject();
assertThat(cm2).isSameAs(cm);
cacheManagerFb2.destroy();
}
finally {
cacheManagerFb.destroy();
}
}
public void testCacheManagerFromConfigFile() {
EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
cacheManagerFb.setConfigLocation(new ClassPathResource("testEhcache.xml", getClass()));
cacheManagerFb.setCacheManagerName("myCacheManager");
cacheManagerFb.afterPropertiesSet();
try {
CacheManager cm = cacheManagerFb.getObject();
assertThat(cm.getCacheNames().length == 1).as("Correct number of caches loaded").isTrue();
Cache myCache1 = cm.getCache("myCache1");
assertThat(myCache1.getCacheConfiguration().isEternal()).as("myCache1 is not eternal").isFalse();
assertThat(myCache1.getCacheConfiguration().getMaxEntriesLocalHeap() == 300).as("myCache1.maxElements == 300").isTrue();
}
finally {
cacheManagerFb.destroy();
}
}
@Test
public void testEhCacheFactoryBeanWithDefaultCacheManager() {
doTestEhCacheFactoryBean(false);
}
@Test
public void testEhCacheFactoryBeanWithExplicitCacheManager() {
doTestEhCacheFactoryBean(true);
}
private void doTestEhCacheFactoryBean(boolean useCacheManagerFb) {
Cache cache;
EhCacheManagerFactoryBean cacheManagerFb = null;
boolean cacheManagerFbInitialized = false;
try {
EhCacheFactoryBean cacheFb = new EhCacheFactoryBean();
Class<? extends Ehcache> objectType = cacheFb.getObjectType();
assertThat(Ehcache.class.isAssignableFrom(objectType)).isTrue();
assertThat(cacheFb.isSingleton()).as("Singleton property").isTrue();
if (useCacheManagerFb) {
cacheManagerFb = new EhCacheManagerFactoryBean();
cacheManagerFb.setConfigLocation(new ClassPathResource("testEhcache.xml", getClass()));
cacheManagerFb.setCacheManagerName("cache");
cacheManagerFb.afterPropertiesSet();
cacheManagerFbInitialized = true;
cacheFb.setCacheManager(cacheManagerFb.getObject());
}
cacheFb.setCacheName("myCache1");
cacheFb.afterPropertiesSet();
cache = (Cache) cacheFb.getObject();
Class<? extends Ehcache> objectType2 = cacheFb.getObjectType();
assertThat(objectType2).isSameAs(objectType);
CacheConfiguration config = cache.getCacheConfiguration();
assertThat(cache.getName()).isEqualTo("myCache1");
if (useCacheManagerFb){
assertThat(config.getMaxEntriesLocalHeap()).as("myCache1.maxElements").isEqualTo(300);
}
else {
assertThat(config.getMaxEntriesLocalHeap()).as("myCache1.maxElements").isEqualTo(10000);
}
// Cache region is not defined. Should create one with default properties.
cacheFb = new EhCacheFactoryBean();
if (useCacheManagerFb) {
cacheFb.setCacheManager(cacheManagerFb.getObject());
}
cacheFb.setCacheName("undefinedCache");
cacheFb.afterPropertiesSet();
cache = (Cache) cacheFb.getObject();
config = cache.getCacheConfiguration();
assertThat(cache.getName()).isEqualTo("undefinedCache");
assertThat(config.getMaxEntriesLocalHeap() == 10000).as("default maxElements is correct").isTrue();
assertThat(config.isEternal()).as("default eternal is correct").isFalse();
assertThat(config.getTimeToLiveSeconds() == 120).as("default timeToLive is correct").isTrue();
assertThat(config.getTimeToIdleSeconds() == 120).as("default timeToIdle is correct").isTrue();
assertThat(config.getDiskExpiryThreadIntervalSeconds() == 120).as("default diskExpiryThreadIntervalSeconds is correct").isTrue();
// overriding the default properties
cacheFb = new EhCacheFactoryBean();
if (useCacheManagerFb) {
cacheFb.setCacheManager(cacheManagerFb.getObject());
}
cacheFb.setBeanName("undefinedCache2");
cacheFb.setMaxEntriesLocalHeap(5);
cacheFb.setTimeToLive(8);
cacheFb.setTimeToIdle(7);
cacheFb.setDiskExpiryThreadIntervalSeconds(10);
cacheFb.afterPropertiesSet();
cache = (Cache) cacheFb.getObject();
config = cache.getCacheConfiguration();
assertThat(cache.getName()).isEqualTo("undefinedCache2");
assertThat(config.getMaxEntriesLocalHeap() == 5).as("overridden maxElements is correct").isTrue();
assertThat(config.getTimeToLiveSeconds() == 8).as("default timeToLive is correct").isTrue();
assertThat(config.getTimeToIdleSeconds() == 7).as("default timeToIdle is correct").isTrue();
assertThat(config.getDiskExpiryThreadIntervalSeconds() == 10).as("overridden diskExpiryThreadIntervalSeconds is correct").isTrue();
}
finally {
if (cacheManagerFbInitialized) {
cacheManagerFb.destroy();
}
else {
CacheManager.getInstance().shutdown();
}
}
}
@Test
public void testEhCacheFactoryBeanWithBlockingCache() {
EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
cacheManagerFb.afterPropertiesSet();
try {
CacheManager cm = cacheManagerFb.getObject();
EhCacheFactoryBean cacheFb = new EhCacheFactoryBean();
cacheFb.setCacheManager(cm);
cacheFb.setCacheName("myCache1");
cacheFb.setBlocking(true);
assertThat(BlockingCache.class).isEqualTo(cacheFb.getObjectType());
cacheFb.afterPropertiesSet();
Ehcache myCache1 = cm.getEhcache("myCache1");
boolean condition = myCache1 instanceof BlockingCache;
assertThat(condition).isTrue();
}
finally {
cacheManagerFb.destroy();
}
}
@Test
public void testEhCacheFactoryBeanWithSelfPopulatingCache() {
EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
cacheManagerFb.afterPropertiesSet();
try {
CacheManager cm = cacheManagerFb.getObject();
EhCacheFactoryBean cacheFb = new EhCacheFactoryBean();
cacheFb.setCacheManager(cm);
cacheFb.setCacheName("myCache1");
cacheFb.setCacheEntryFactory(key -> key);
assertThat(SelfPopulatingCache.class).isEqualTo(cacheFb.getObjectType());
cacheFb.afterPropertiesSet();
Ehcache myCache1 = cm.getEhcache("myCache1");
boolean condition = myCache1 instanceof SelfPopulatingCache;
assertThat(condition).isTrue();
assertThat(myCache1.get("myKey1").getObjectValue()).isEqualTo("myKey1");
}
finally {
cacheManagerFb.destroy();
}
}
@Test
public void testEhCacheFactoryBeanWithUpdatingSelfPopulatingCache() {
EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
cacheManagerFb.afterPropertiesSet();
try {
CacheManager cm = cacheManagerFb.getObject();
EhCacheFactoryBean cacheFb = new EhCacheFactoryBean();
cacheFb.setCacheManager(cm);
cacheFb.setCacheName("myCache1");
cacheFb.setCacheEntryFactory(new UpdatingCacheEntryFactory() {
@Override
public Object createEntry(Object key) {
return key;
}
@Override
public void updateEntryValue(Object key, Object value) {
}
});
assertThat(UpdatingSelfPopulatingCache.class).isEqualTo(cacheFb.getObjectType());
cacheFb.afterPropertiesSet();
Ehcache myCache1 = cm.getEhcache("myCache1");
boolean condition = myCache1 instanceof UpdatingSelfPopulatingCache;
assertThat(condition).isTrue();
assertThat(myCache1.get("myKey1").getObjectValue()).isEqualTo("myKey1");
}
finally {
cacheManagerFb.destroy();
}
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.jcache;
import javax.cache.Caching;
import javax.cache.spi.CachingProvider;
/**
* Just here to be run against EHCache 3, whereas the original JCacheEhCacheAnnotationTests
* runs against EhCache 2.x with the EhCache-JCache add-on.
*
* @author Juergen Hoeller
*/
public class JCacheEhCache3AnnotationTests extends JCacheEhCacheAnnotationTests {
@Override
protected CachingProvider getCachingProvider() {
return Caching.getCachingProvider("org.ehcache.jsr107.EhcacheCachingProvider");
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.jcache;
import javax.cache.Caching;
import javax.cache.spi.CachingProvider;
/**
* Just here to be run against EHCache 3, whereas the original JCacheEhCacheAnnotationTests
* runs against EhCache 2.x with the EhCache-JCache add-on.
*
* @author Stephane Nicoll
*/
public class JCacheEhCache3ApiTests extends JCacheEhCacheApiTests {
@Override
protected CachingProvider getCachingProvider() {
return Caching.getCachingProvider("org.ehcache.jsr107.EhcacheCachingProvider");
}
}

View File

@ -64,7 +64,7 @@ public class JCacheEhCacheAnnotationTests extends AbstractCacheAnnotationTests {
}
protected CachingProvider getCachingProvider() {
return Caching.getCachingProvider("org.ehcache.jcache.JCacheCachingProvider");
return Caching.getCachingProvider("org.ehcache.jsr107.EhcacheCachingProvider");
}
@AfterEach

View File

@ -54,7 +54,7 @@ public class JCacheEhCacheApiTests extends AbstractValueAdaptingCacheTests<JCach
}
protected CachingProvider getCachingProvider() {
return Caching.getCachingProvider("org.ehcache.jcache.JCacheCachingProvider");
return Caching.getCachingProvider("org.ehcache.jsr107.EhcacheCachingProvider");
}
@AfterEach

View File

@ -24,18 +24,17 @@ import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;
import javax.activation.FileTypeMap;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import jakarta.activation.FileTypeMap;
import jakarta.mail.Address;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.NoSuchProviderException;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.URLName;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import org.junit.jupiter.api.Test;
import org.springframework.mail.MailParseException;

View File

@ -1,155 +0,0 @@
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.validation.beanvalidation2;
import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.validation.beanvalidation.BeanValidationPostProcessor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Juergen Hoeller
*/
public class BeanValidationPostProcessorTests {
@Test
public void testNotNullConstraint() {
GenericApplicationContext ac = new GenericApplicationContext();
ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
ac.registerBeanDefinition("bean", new RootBeanDefinition(NotNullConstrainedBean.class));
assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(ac::refresh)
.havingRootCause()
.withMessageContainingAll("testBean", "invalid");
ac.close();
}
@Test
public void testNotNullConstraintSatisfied() {
GenericApplicationContext ac = new GenericApplicationContext();
ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
RootBeanDefinition bd = new RootBeanDefinition(NotNullConstrainedBean.class);
bd.getPropertyValues().add("testBean", new TestBean());
ac.registerBeanDefinition("bean", bd);
ac.refresh();
ac.close();
}
@Test
public void testNotNullConstraintAfterInitialization() {
GenericApplicationContext ac = new GenericApplicationContext();
RootBeanDefinition bvpp = new RootBeanDefinition(BeanValidationPostProcessor.class);
bvpp.getPropertyValues().add("afterInitialization", true);
ac.registerBeanDefinition("bvpp", bvpp);
ac.registerBeanDefinition("capp", new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class));
ac.registerBeanDefinition("bean", new RootBeanDefinition(AfterInitConstraintBean.class));
ac.refresh();
ac.close();
}
@Test
public void testSizeConstraint() {
GenericApplicationContext ac = new GenericApplicationContext();
ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
RootBeanDefinition bd = new RootBeanDefinition(NotNullConstrainedBean.class);
bd.getPropertyValues().add("testBean", new TestBean());
bd.getPropertyValues().add("stringValue", "s");
ac.registerBeanDefinition("bean", bd);
assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(ac::refresh)
.havingRootCause()
.withMessageContainingAll("stringValue", "invalid");
ac.close();
}
@Test
public void testSizeConstraintSatisfied() {
GenericApplicationContext ac = new GenericApplicationContext();
ac.registerBeanDefinition("bvpp", new RootBeanDefinition(BeanValidationPostProcessor.class));
RootBeanDefinition bd = new RootBeanDefinition(NotNullConstrainedBean.class);
bd.getPropertyValues().add("testBean", new TestBean());
bd.getPropertyValues().add("stringValue", "ss");
ac.registerBeanDefinition("bean", bd);
ac.refresh();
ac.close();
}
public static class NotNullConstrainedBean {
@NotNull
private TestBean testBean;
@Size(min = 2)
private String stringValue;
public TestBean getTestBean() {
return testBean;
}
public void setTestBean(TestBean testBean) {
this.testBean = testBean;
}
public String getStringValue() {
return stringValue;
}
public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}
@PostConstruct
public void init() {
assertThat(this.testBean).as("Shouldn't be here after constraint checking").isNotNull();
}
}
public static class AfterInitConstraintBean {
@NotNull
private TestBean testBean;
public TestBean getTestBean() {
return testBean;
}
public void setTestBean(TestBean testBean) {
this.testBean = testBean;
}
@PostConstruct
public void init() {
this.testBean = new TestBean();
}
}
}

View File

@ -1,218 +0,0 @@
/*
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.validation.beanvalidation2;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.validation.ValidationException;
import javax.validation.Validator;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.groups.Default;
import org.junit.jupiter.api.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncAnnotationAdvisor;
import org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor;
import org.springframework.validation.annotation.Validated;
import org.springframework.validation.beanvalidation.CustomValidatorBean;
import org.springframework.validation.beanvalidation.MethodValidationInterceptor;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Juergen Hoeller
*/
public class MethodValidationTests {
@Test
@SuppressWarnings("unchecked")
public void testMethodValidationInterceptor() {
MyValidBean bean = new MyValidBean();
ProxyFactory proxyFactory = new ProxyFactory(bean);
proxyFactory.addAdvice(new MethodValidationInterceptor());
proxyFactory.addAdvisor(new AsyncAnnotationAdvisor());
doTestProxyValidation((MyValidInterface<String>) proxyFactory.getProxy());
}
@Test
@SuppressWarnings("unchecked")
public void testMethodValidationPostProcessor() {
StaticApplicationContext ac = new StaticApplicationContext();
ac.registerSingleton("mvpp", MethodValidationPostProcessor.class);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("beforeExistingAdvisors", false);
ac.registerSingleton("aapp", AsyncAnnotationBeanPostProcessor.class, pvs);
ac.registerSingleton("bean", MyValidBean.class);
ac.refresh();
doTestProxyValidation(ac.getBean("bean", MyValidInterface.class));
ac.close();
}
private void doTestProxyValidation(MyValidInterface<String> proxy) {
assertThat(proxy.myValidMethod("value", 5)).isNotNull();
assertThatExceptionOfType(ValidationException.class).isThrownBy(() ->
proxy.myValidMethod("value", 15));
assertThatExceptionOfType(ValidationException.class).isThrownBy(() ->
proxy.myValidMethod(null, 5));
assertThatExceptionOfType(ValidationException.class).isThrownBy(() ->
proxy.myValidMethod("value", 0));
proxy.myValidAsyncMethod("value", 5);
assertThatExceptionOfType(ValidationException.class).isThrownBy(() ->
proxy.myValidAsyncMethod("value", 15));
assertThatExceptionOfType(ValidationException.class).isThrownBy(() ->
proxy.myValidAsyncMethod(null, 5));
assertThat(proxy.myGenericMethod("myValue")).isEqualTo("myValue");
assertThatExceptionOfType(ValidationException.class).isThrownBy(() ->
proxy.myGenericMethod(null));
}
@Test
public void testLazyValidatorForMethodValidation() {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
LazyMethodValidationConfig.class, CustomValidatorBean.class,
MyValidBean.class, MyValidFactoryBean.class);
ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
}
@Test
public void testLazyValidatorForMethodValidationWithProxyTargetClass() {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
LazyMethodValidationConfigWithProxyTargetClass.class, CustomValidatorBean.class,
MyValidBean.class, MyValidFactoryBean.class);
ctx.getBeansOfType(MyValidInterface.class).values().forEach(bean -> bean.myValidMethod("value", 5));
}
@MyStereotype
public static class MyValidBean implements MyValidInterface<String> {
@Override
public Object myValidMethod(String arg1, int arg2) {
return (arg2 == 0 ? null : "value");
}
@Override
public void myValidAsyncMethod(String arg1, int arg2) {
}
@Override
public String myGenericMethod(String value) {
return value;
}
}
@MyStereotype
public static class MyValidFactoryBean implements FactoryBean<String>, MyValidInterface<String> {
@Override
public String getObject() {
return null;
}
@Override
public Class<?> getObjectType() {
return String.class;
}
@Override
public Object myValidMethod(String arg1, int arg2) {
return (arg2 == 0 ? null : "value");
}
@Override
public void myValidAsyncMethod(String arg1, int arg2) {
}
@Override
public String myGenericMethod(String value) {
return value;
}
}
public interface MyValidInterface<T> {
@NotNull Object myValidMethod(@NotNull(groups = MyGroup.class) String arg1, @Max(10) int arg2);
@MyValid
@Async void myValidAsyncMethod(@NotNull(groups = OtherGroup.class) String arg1, @Max(10) int arg2);
T myGenericMethod(@NotNull T value);
}
public interface MyGroup {
}
public interface OtherGroup {
}
@Validated({MyGroup.class, Default.class})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyStereotype {
}
@Validated({OtherGroup.class, Default.class})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValid {
}
@Configuration
public static class LazyMethodValidationConfig {
@Bean
public static MethodValidationPostProcessor methodValidationPostProcessor(@Lazy Validator validator) {
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
postProcessor.setValidator(validator);
return postProcessor;
}
}
@Configuration
public static class LazyMethodValidationConfigWithProxyTargetClass {
@Bean
public static MethodValidationPostProcessor methodValidationPostProcessor(@Lazy Validator validator) {
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
postProcessor.setValidator(validator);
postProcessor.setProxyTargetClass(true);
return postProcessor;
}
}
}

View File

@ -1,563 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.validation.beanvalidation2;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintViolation;
import javax.validation.Payload;
import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.context.support.StaticMessageSource;
import org.springframework.core.testfixture.io.SerializationTestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Kazuki Shimizu
* @author Juergen Hoeller
*/
public class SpringValidatorAdapterTests {
private final Validator nativeValidator = Validation.buildDefaultValidatorFactory().getValidator();
private final SpringValidatorAdapter validatorAdapter = new SpringValidatorAdapter(nativeValidator);
private final StaticMessageSource messageSource = new StaticMessageSource();
@BeforeEach
public void setupSpringValidatorAdapter() {
messageSource.addMessage("Size", Locale.ENGLISH, "Size of {0} must be between {2} and {1}");
messageSource.addMessage("Same", Locale.ENGLISH, "{2} must be same value as {1}");
messageSource.addMessage("password", Locale.ENGLISH, "Password");
messageSource.addMessage("confirmPassword", Locale.ENGLISH, "Password(Confirm)");
}
@Test
public void testUnwrap() {
Validator nativeValidator = validatorAdapter.unwrap(Validator.class);
assertThat(nativeValidator).isSameAs(this.nativeValidator);
}
@Test // SPR-13406
public void testNoStringArgumentValue() throws Exception {
TestBean testBean = new TestBean();
testBean.setPassword("pass");
testBean.setConfirmPassword("pass");
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(testBean, "testBean");
validatorAdapter.validate(testBean, errors);
assertThat(errors.getFieldErrorCount("password")).isEqualTo(1);
assertThat(errors.getFieldValue("password")).isEqualTo("pass");
FieldError error = errors.getFieldError("password");
assertThat(error).isNotNull();
assertThat(messageSource.getMessage(error, Locale.ENGLISH)).isEqualTo("Size of Password must be between 8 and 128");
assertThat(error.contains(ConstraintViolation.class)).isTrue();
assertThat(error.unwrap(ConstraintViolation.class).getPropertyPath().toString()).isEqualTo("password");
assertThat(SerializationTestUtils.serializeAndDeserialize(error.toString())).isEqualTo(error.toString());
}
@Test // SPR-13406
public void testApplyMessageSourceResolvableToStringArgumentValueWithResolvedLogicalFieldName() throws Exception {
TestBean testBean = new TestBean();
testBean.setPassword("password");
testBean.setConfirmPassword("PASSWORD");
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(testBean, "testBean");
validatorAdapter.validate(testBean, errors);
assertThat(errors.getFieldErrorCount("password")).isEqualTo(1);
assertThat(errors.getFieldValue("password")).isEqualTo("password");
FieldError error = errors.getFieldError("password");
assertThat(error).isNotNull();
assertThat(messageSource.getMessage(error, Locale.ENGLISH)).isEqualTo("Password must be same value as Password(Confirm)");
assertThat(error.contains(ConstraintViolation.class)).isTrue();
assertThat(error.unwrap(ConstraintViolation.class).getPropertyPath().toString()).isEqualTo("password");
assertThat(SerializationTestUtils.serializeAndDeserialize(error.toString())).isEqualTo(error.toString());
}
@Test // SPR-13406
public void testApplyMessageSourceResolvableToStringArgumentValueWithUnresolvedLogicalFieldName() {
TestBean testBean = new TestBean();
testBean.setEmail("test@example.com");
testBean.setConfirmEmail("TEST@EXAMPLE.IO");
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(testBean, "testBean");
validatorAdapter.validate(testBean, errors);
assertThat(errors.getFieldErrorCount("email")).isEqualTo(1);
assertThat(errors.getFieldValue("email")).isEqualTo("test@example.com");
assertThat(errors.getFieldErrorCount("confirmEmail")).isEqualTo(1);
FieldError error1 = errors.getFieldError("email");
FieldError error2 = errors.getFieldError("confirmEmail");
assertThat(error1).isNotNull();
assertThat(error2).isNotNull();
assertThat(messageSource.getMessage(error1, Locale.ENGLISH)).isEqualTo("email must be same value as confirmEmail");
assertThat(messageSource.getMessage(error2, Locale.ENGLISH)).isEqualTo("Email required");
assertThat(error1.contains(ConstraintViolation.class)).isTrue();
assertThat(error1.unwrap(ConstraintViolation.class).getPropertyPath().toString()).isEqualTo("email");
assertThat(error2.contains(ConstraintViolation.class)).isTrue();
assertThat(error2.unwrap(ConstraintViolation.class).getPropertyPath().toString()).isEqualTo("confirmEmail");
}
@Test // SPR-15123
public void testApplyMessageSourceResolvableToStringArgumentValueWithAlwaysUseMessageFormat() {
messageSource.setAlwaysUseMessageFormat(true);
TestBean testBean = new TestBean();
testBean.setEmail("test@example.com");
testBean.setConfirmEmail("TEST@EXAMPLE.IO");
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(testBean, "testBean");
validatorAdapter.validate(testBean, errors);
assertThat(errors.getFieldErrorCount("email")).isEqualTo(1);
assertThat(errors.getFieldValue("email")).isEqualTo("test@example.com");
assertThat(errors.getFieldErrorCount("confirmEmail")).isEqualTo(1);
FieldError error1 = errors.getFieldError("email");
FieldError error2 = errors.getFieldError("confirmEmail");
assertThat(error1).isNotNull();
assertThat(error2).isNotNull();
assertThat(messageSource.getMessage(error1, Locale.ENGLISH)).isEqualTo("email must be same value as confirmEmail");
assertThat(messageSource.getMessage(error2, Locale.ENGLISH)).isEqualTo("Email required");
assertThat(error1.contains(ConstraintViolation.class)).isTrue();
assertThat(error1.unwrap(ConstraintViolation.class).getPropertyPath().toString()).isEqualTo("email");
assertThat(error2.contains(ConstraintViolation.class)).isTrue();
assertThat(error2.unwrap(ConstraintViolation.class).getPropertyPath().toString()).isEqualTo("confirmEmail");
}
@Test
public void testPatternMessage() {
TestBean testBean = new TestBean();
testBean.setEmail("X");
testBean.setConfirmEmail("X");
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(testBean, "testBean");
validatorAdapter.validate(testBean, errors);
assertThat(errors.getFieldErrorCount("email")).isEqualTo(1);
assertThat(errors.getFieldValue("email")).isEqualTo("X");
FieldError error = errors.getFieldError("email");
assertThat(error).isNotNull();
assertThat(messageSource.getMessage(error, Locale.ENGLISH)).contains("[\\w.'-]{1,}@[\\w.'-]{1,}");
assertThat(error.contains(ConstraintViolation.class)).isTrue();
assertThat(error.unwrap(ConstraintViolation.class).getPropertyPath().toString()).isEqualTo("email");
}
@Test // SPR-16177
public void testWithList() {
Parent parent = new Parent();
parent.setName("Parent whit list");
parent.getChildList().addAll(createChildren(parent));
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(parent, "parent");
validatorAdapter.validate(parent, errors);
assertThat(errors.getErrorCount() > 0).isTrue();
}
@Test // SPR-16177
public void testWithSet() {
Parent parent = new Parent();
parent.setName("Parent with set");
parent.getChildSet().addAll(createChildren(parent));
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(parent, "parent");
validatorAdapter.validate(parent, errors);
assertThat(errors.getErrorCount() > 0).isTrue();
}
private List<Child> createChildren(Parent parent) {
Child child1 = new Child();
child1.setName("Child1");
child1.setAge(null);
child1.setParent(parent);
Child child2 = new Child();
child2.setName(null);
child2.setAge(17);
child2.setParent(parent);
return Arrays.asList(child1, child2);
}
@Test // SPR-15839
public void testListElementConstraint() {
BeanWithListElementConstraint bean = new BeanWithListElementConstraint();
bean.setProperty(Arrays.asList("no", "element", "can", "be", null));
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(bean, "bean");
validatorAdapter.validate(bean, errors);
assertThat(errors.getFieldErrorCount("property[4]")).isEqualTo(1);
assertThat(errors.getFieldValue("property[4]")).isNull();
}
@Test // SPR-15839
public void testMapValueConstraint() {
Map<String, String> property = new HashMap<>();
property.put("no value can be", null);
BeanWithMapEntryConstraint bean = new BeanWithMapEntryConstraint();
bean.setProperty(property);
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(bean, "bean");
validatorAdapter.validate(bean, errors);
assertThat(errors.getFieldErrorCount("property[no value can be]")).isEqualTo(1);
assertThat(errors.getFieldValue("property[no value can be]")).isNull();
}
@Test // SPR-15839
public void testMapEntryConstraint() {
Map<String, String> property = new HashMap<>();
property.put(null, null);
BeanWithMapEntryConstraint bean = new BeanWithMapEntryConstraint();
bean.setProperty(property);
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(bean, "bean");
validatorAdapter.validate(bean, errors);
assertThat(errors.hasFieldErrors("property[]")).isTrue();
assertThat(errors.getFieldValue("property[]")).isNull();
}
@Same(field = "password", comparingField = "confirmPassword")
@Same(field = "email", comparingField = "confirmEmail")
static class TestBean {
@Size(min = 8, max = 128)
private String password;
private String confirmPassword;
@Pattern(regexp = "[\\w.'-]{1,}@[\\w.'-]{1,}")
private String email;
@Pattern(regexp = "[\\p{L} -]*", message = "Email required")
private String confirmEmail;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getConfirmPassword() {
return confirmPassword;
}
public void setConfirmPassword(String confirmPassword) {
this.confirmPassword = confirmPassword;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getConfirmEmail() {
return confirmEmail;
}
public void setConfirmEmail(String confirmEmail) {
this.confirmEmail = confirmEmail;
}
}
@Documented
@Constraint(validatedBy = {SameValidator.class})
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(SameGroup.class)
@interface Same {
String message() default "{org.springframework.validation.beanvalidation.Same.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String field();
String comparingField();
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface List {
Same[] value();
}
}
@Documented
@Inherited
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface SameGroup {
Same[] value();
}
public static class SameValidator implements ConstraintValidator<Same, Object> {
private String field;
private String comparingField;
private String message;
@Override
public void initialize(Same constraintAnnotation) {
field = constraintAnnotation.field();
comparingField = constraintAnnotation.comparingField();
message = constraintAnnotation.message();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
BeanWrapper beanWrapper = new BeanWrapperImpl(value);
Object fieldValue = beanWrapper.getPropertyValue(field);
Object comparingFieldValue = beanWrapper.getPropertyValue(comparingField);
boolean matched = ObjectUtils.nullSafeEquals(fieldValue, comparingFieldValue);
if (matched) {
return true;
}
else {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message)
.addPropertyNode(field)
.addConstraintViolation();
return false;
}
}
}
public static class Parent {
private Integer id;
@NotNull
private String name;
@Valid
private Set<Child> childSet = new LinkedHashSet<>();
@Valid
private List<Child> childList = new ArrayList<>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Child> getChildSet() {
return childSet;
}
public void setChildSet(Set<Child> childSet) {
this.childSet = childSet;
}
public List<Child> getChildList() {
return childList;
}
public void setChildList(List<Child> childList) {
this.childList = childList;
}
}
@AnythingValid
public static class Child {
private Integer id;
@NotNull
private String name;
@NotNull
private Integer age;
@NotNull
private Parent parent;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
@Constraint(validatedBy = AnythingValidator.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnythingValid {
String message() default "{AnythingValid.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public static class AnythingValidator implements ConstraintValidator<AnythingValid, Object> {
private static final String ID = "id";
@Override
public void initialize(AnythingValid constraintAnnotation) {
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
List<Field> fieldsErrors = new ArrayList<>();
Arrays.asList(value.getClass().getDeclaredFields()).forEach(field -> {
field.setAccessible(true);
try {
if (!field.getName().equals(ID) && field.get(value) == null) {
fieldsErrors.add(field);
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate())
.addPropertyNode(field.getName())
.addConstraintViolation();
}
}
catch (IllegalAccessException ex) {
throw new IllegalStateException(ex);
}
});
return fieldsErrors.isEmpty();
}
}
public class BeanWithListElementConstraint {
@Valid
private List<@NotNull String> property;
public List<String> getProperty() {
return property;
}
public void setProperty(List<String> property) {
this.property = property;
}
}
public class BeanWithMapEntryConstraint {
@Valid
private Map<@NotNull String, @NotNull String> property;
public Map<String, String> getProperty() {
return property;
}
public void setProperty(Map<String, String> property) {
this.property = property;
}
}
}

View File

@ -1,505 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.validation.beanvalidation2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintViolation;
import javax.validation.Payload;
import javax.validation.Valid;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.HibernateValidatorFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.Environment;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Juergen Hoeller
*/
@SuppressWarnings("resource")
public class ValidatorFactoryTests {
@Test
@SuppressWarnings("cast")
public void testSimpleValidation() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
ValidPerson person = new ValidPerson();
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
assertThat(result.size()).isEqualTo(2);
for (ConstraintViolation<ValidPerson> cv : result) {
String path = cv.getPropertyPath().toString();
assertThat(path).matches(actual -> "name".equals(actual) || "address.street".equals(actual));
assertThat(cv.getConstraintDescriptor().getAnnotation()).isInstanceOf(NotNull.class);
}
Validator nativeValidator = validator.unwrap(Validator.class);
assertThat(nativeValidator.getClass().getName().startsWith("org.hibernate")).isTrue();
assertThat(validator.unwrap(ValidatorFactory.class) instanceof HibernateValidatorFactory).isTrue();
assertThat(validator.unwrap(HibernateValidatorFactory.class) instanceof HibernateValidatorFactory).isTrue();
validator.destroy();
}
@Test
@SuppressWarnings("cast")
public void testSimpleValidationWithCustomProvider() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setProviderClass(HibernateValidator.class);
validator.afterPropertiesSet();
ValidPerson person = new ValidPerson();
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
assertThat(result.size()).isEqualTo(2);
for (ConstraintViolation<ValidPerson> cv : result) {
String path = cv.getPropertyPath().toString();
assertThat(path).matches(actual -> "name".equals(actual) || "address.street".equals(actual));
assertThat(cv.getConstraintDescriptor().getAnnotation()).isInstanceOf(NotNull.class);
}
Validator nativeValidator = validator.unwrap(Validator.class);
assertThat(nativeValidator.getClass().getName().startsWith("org.hibernate")).isTrue();
assertThat(validator.unwrap(ValidatorFactory.class) instanceof HibernateValidatorFactory).isTrue();
assertThat(validator.unwrap(HibernateValidatorFactory.class) instanceof HibernateValidatorFactory).isTrue();
validator.destroy();
}
@Test
public void testSimpleValidationWithClassLevel() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
ValidPerson person = new ValidPerson();
person.setName("Juergen");
person.getAddress().setStreet("Juergen's Street");
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
assertThat(result.size()).isEqualTo(1);
Iterator<ConstraintViolation<ValidPerson>> iterator = result.iterator();
ConstraintViolation<?> cv = iterator.next();
assertThat(cv.getPropertyPath().toString()).isEqualTo("");
assertThat(cv.getConstraintDescriptor().getAnnotation() instanceof NameAddressValid).isTrue();
}
@Test
public void testSpringValidationFieldType() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
ValidPerson person = new ValidPerson();
person.setName("Phil");
person.getAddress().setStreet("Phil's Street");
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(person, "person");
validator.validate(person, errors);
assertThat(errors.getErrorCount()).isEqualTo(1);
assertThat(errors.getFieldError("address").getRejectedValue()).isInstanceOf(ValidAddress.class);
}
@Test
public void testSpringValidation() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
ValidPerson person = new ValidPerson();
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
validator.validate(person, result);
assertThat(result.getErrorCount()).isEqualTo(2);
FieldError fieldError = result.getFieldError("name");
assertThat(fieldError.getField()).isEqualTo("name");
List<String> errorCodes = Arrays.asList(fieldError.getCodes());
assertThat(errorCodes.size()).isEqualTo(4);
assertThat(errorCodes.contains("NotNull.person.name")).isTrue();
assertThat(errorCodes.contains("NotNull.name")).isTrue();
assertThat(errorCodes.contains("NotNull.java.lang.String")).isTrue();
assertThat(errorCodes.contains("NotNull")).isTrue();
fieldError = result.getFieldError("address.street");
assertThat(fieldError.getField()).isEqualTo("address.street");
errorCodes = Arrays.asList(fieldError.getCodes());
assertThat(errorCodes.size()).isEqualTo(5);
assertThat(errorCodes.contains("NotNull.person.address.street")).isTrue();
assertThat(errorCodes.contains("NotNull.address.street")).isTrue();
assertThat(errorCodes.contains("NotNull.street")).isTrue();
assertThat(errorCodes.contains("NotNull.java.lang.String")).isTrue();
assertThat(errorCodes.contains("NotNull")).isTrue();
}
@Test
public void testSpringValidationWithClassLevel() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
ValidPerson person = new ValidPerson();
person.setName("Juergen");
person.getAddress().setStreet("Juergen's Street");
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
validator.validate(person, result);
assertThat(result.getErrorCount()).isEqualTo(1);
ObjectError globalError = result.getGlobalError();
List<String> errorCodes = Arrays.asList(globalError.getCodes());
assertThat(errorCodes.size()).isEqualTo(2);
assertThat(errorCodes.contains("NameAddressValid.person")).isTrue();
assertThat(errorCodes.contains("NameAddressValid")).isTrue();
}
@Test
public void testSpringValidationWithAutowiredValidator() {
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
LocalValidatorFactoryBean.class);
LocalValidatorFactoryBean validator = ctx.getBean(LocalValidatorFactoryBean.class);
ValidPerson person = new ValidPerson();
person.expectsAutowiredValidator = true;
person.setName("Juergen");
person.getAddress().setStreet("Juergen's Street");
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
validator.validate(person, result);
assertThat(result.getErrorCount()).isEqualTo(1);
ObjectError globalError = result.getGlobalError();
List<String> errorCodes = Arrays.asList(globalError.getCodes());
assertThat(errorCodes.size()).isEqualTo(2);
assertThat(errorCodes.contains("NameAddressValid.person")).isTrue();
assertThat(errorCodes.contains("NameAddressValid")).isTrue();
ctx.close();
}
@Test
public void testSpringValidationWithErrorInListElement() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
ValidPerson person = new ValidPerson();
person.getAddressList().add(new ValidAddress());
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
validator.validate(person, result);
assertThat(result.getErrorCount()).isEqualTo(3);
FieldError fieldError = result.getFieldError("name");
assertThat(fieldError.getField()).isEqualTo("name");
fieldError = result.getFieldError("address.street");
assertThat(fieldError.getField()).isEqualTo("address.street");
fieldError = result.getFieldError("addressList[0].street");
assertThat(fieldError.getField()).isEqualTo("addressList[0].street");
}
@Test
public void testSpringValidationWithErrorInSetElement() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
ValidPerson person = new ValidPerson();
person.getAddressSet().add(new ValidAddress());
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
validator.validate(person, result);
assertThat(result.getErrorCount()).isEqualTo(3);
FieldError fieldError = result.getFieldError("name");
assertThat(fieldError.getField()).isEqualTo("name");
fieldError = result.getFieldError("address.street");
assertThat(fieldError.getField()).isEqualTo("address.street");
fieldError = result.getFieldError("addressSet[].street");
assertThat(fieldError.getField()).isEqualTo("addressSet[].street");
}
@Test
public void testInnerBeanValidation() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
MainBean mainBean = new MainBean();
Errors errors = new BeanPropertyBindingResult(mainBean, "mainBean");
validator.validate(mainBean, errors);
Object rejected = errors.getFieldValue("inner.value");
assertThat(rejected).isNull();
}
@Test
public void testValidationWithOptionalField() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
MainBeanWithOptional mainBean = new MainBeanWithOptional();
Errors errors = new BeanPropertyBindingResult(mainBean, "mainBean");
validator.validate(mainBean, errors);
Object rejected = errors.getFieldValue("inner.value");
assertThat(rejected).isNull();
}
@Test
public void testListValidation() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.afterPropertiesSet();
ListContainer listContainer = new ListContainer();
listContainer.addString("A");
listContainer.addString("X");
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(listContainer, "listContainer");
errors.initConversion(new DefaultConversionService());
validator.validate(listContainer, errors);
FieldError fieldError = errors.getFieldError("list[1]");
assertThat(fieldError).isNotNull();
assertThat(fieldError.getRejectedValue()).isEqualTo("X");
assertThat(errors.getFieldValue("list[1]")).isEqualTo("X");
}
@NameAddressValid
public static class ValidPerson {
@NotNull
private String name;
@Valid
private ValidAddress address = new ValidAddress();
@Valid
private List<ValidAddress> addressList = new ArrayList<>();
@Valid
private Set<ValidAddress> addressSet = new LinkedHashSet<>();
public boolean expectsAutowiredValidator = false;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ValidAddress getAddress() {
return address;
}
public void setAddress(ValidAddress address) {
this.address = address;
}
public List<ValidAddress> getAddressList() {
return addressList;
}
public void setAddressList(List<ValidAddress> addressList) {
this.addressList = addressList;
}
public Set<ValidAddress> getAddressSet() {
return addressSet;
}
public void setAddressSet(Set<ValidAddress> addressSet) {
this.addressSet = addressSet;
}
}
public static class ValidAddress {
@NotNull
private String street;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NameAddressValidator.class)
public @interface NameAddressValid {
String message() default "Street must not contain name";
Class<?>[] groups() default {};
Class<?>[] payload() default {};
}
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
@Autowired
private Environment environment;
@Override
public void initialize(NameAddressValid constraintAnnotation) {
}
@Override
public boolean isValid(ValidPerson value, ConstraintValidatorContext context) {
if (value.expectsAutowiredValidator) {
assertThat(this.environment).isNotNull();
}
boolean valid = (value.name == null || !value.address.street.contains(value.name));
if (!valid && "Phil".equals(value.name)) {
context.buildConstraintViolationWithTemplate(
context.getDefaultConstraintMessageTemplate()).addPropertyNode("address").addConstraintViolation().disableDefaultConstraintViolation();
}
return valid;
}
}
public static class MainBean {
@InnerValid
private InnerBean inner = new InnerBean();
public InnerBean getInner() {
return inner;
}
}
public static class MainBeanWithOptional {
@InnerValid
private InnerBean inner = new InnerBean();
public Optional<InnerBean> getInner() {
return Optional.ofNullable(inner);
}
}
public static class InnerBean {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Constraint(validatedBy=InnerValidator.class)
public static @interface InnerValid {
String message() default "NOT VALID";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default {};
}
public static class InnerValidator implements ConstraintValidator<InnerValid, InnerBean> {
@Override
public void initialize(InnerValid constraintAnnotation) {
}
@Override
public boolean isValid(InnerBean bean, ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
if (bean.getValue() == null) {
context.buildConstraintViolationWithTemplate("NULL").addPropertyNode("value").addConstraintViolation();
return false;
}
return true;
}
}
public static class ListContainer {
@NotXList
private List<String> list = new ArrayList<>();
public void addString(String value) {
list.add(value);
}
public List<String> getList() {
return list;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Constraint(validatedBy = NotXListValidator.class)
public @interface NotXList {
String message() default "Should not be X";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public static class NotXListValidator implements ConstraintValidator<NotXList, List<String>> {
@Override
public void initialize(NotXList constraintAnnotation) {
}
@Override
public boolean isValid(List<String> list, ConstraintValidatorContext context) {
context.disableDefaultConstraintViolation();
boolean valid = true;
for (int i = 0; i < list.size(); i++) {
if ("X".equals(list.get(i))) {
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addBeanNode().inIterable().atIndex(i).addConstraintViolation();
valid = false;
}
}
return valid;
}
}
}

View File

@ -9,20 +9,18 @@ dependencies {
api(project(":spring-core"))
api(project(":spring-expression"))
optional(project(":spring-instrument"))
optional("javax.annotation:javax.annotation-api")
optional("javax.ejb:javax.ejb-api")
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api")
optional("javax.inject:javax.inject")
optional("javax.interceptor:javax.interceptor-api")
optional("jakarta.annotation:jakarta.annotation-api")
optional("jakarta.ejb:jakarta.ejb-api")
optional("jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api")
optional("jakarta.inject:jakarta.inject-api")
optional("jakarta.interceptor:jakarta.interceptor-api")
optional("javax.money:money-api")
// Overriding 2.0.1.Final due to Bean Validation 1.1 compatibility in LocalValidatorFactoryBean
optional("javax.validation:validation-api:1.1.0.Final")
optional("javax.xml.ws:jaxws-api")
optional("jakarta.validation:jakarta.validation-api")
optional("jakarta.xml.ws:jakarta.xml.ws-api")
optional("org.aspectj:aspectjweaver")
optional("org.codehaus.groovy:groovy")
optional("org.apache-extras.beanshell:bsh")
optional("joda-time:joda-time")
optional("org.hibernate:hibernate-validator:5.4.3.Final")
optional("org.hibernate:hibernate-validator")
optional("org.jetbrains.kotlin:kotlin-reflect")
optional("org.jetbrains.kotlin:kotlin-stdlib")
optional("org.reactivestreams:reactive-streams")
@ -34,10 +32,10 @@ dependencies {
testImplementation("org.codehaus.groovy:groovy-test")
testImplementation("org.codehaus.groovy:groovy-xml")
testImplementation("org.apache.commons:commons-pool2")
testImplementation("javax.inject:javax.inject-tck")
testImplementation("jakarta.inject:jakarta.inject-tck")
testImplementation("org.awaitility:awaitility")
testRuntimeOnly("javax.xml.bind:jaxb-api")
testRuntimeOnly("org.glassfish:javax.el")
testRuntimeOnly("jakarta.xml.bind:jakarta.xml.bind-api")
testRuntimeOnly("org.glassfish:jakarta.el")
// Substitute for javax.management:jmxremote_optional:1.0.1_04 (not available on Maven Central)
testRuntimeOnly("org.glassfish.external:opendmk_jmxremote_optional_jar")
testRuntimeOnly("org.javamoney:moneta")

View File

@ -16,8 +16,7 @@
package org.springframework.context.annotation;
import javax.annotation.Resource;
import jakarta.annotation.Resource;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;

View File

@ -41,8 +41,8 @@ import org.springframework.util.StringUtils;
* {@link org.springframework.stereotype.Repository @Repository}) are
* themselves annotated with {@code @Component}.
*
* <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
* JSR-330's {@link javax.inject.Named} annotations, if available. Note that
* <p>Also supports Jakarta EE's {@link jakarta.annotation.ManagedBean} and
* JSR-330's {@link jakarta.inject.Named} annotations, if available. Note that
* Spring component annotations always override such standard annotations.
*
* <p>If the annotation's value doesn't indicate a bean name, an appropriate
@ -58,7 +58,7 @@ import org.springframework.util.StringUtils;
* @see org.springframework.stereotype.Repository#value()
* @see org.springframework.stereotype.Service#value()
* @see org.springframework.stereotype.Controller#value()
* @see javax.inject.Named#value()
* @see jakarta.inject.Named#value()
* @see FullyQualifiedAnnotationBeanNameGenerator
*/
public class AnnotationBeanNameGenerator implements BeanNameGenerator {
@ -136,8 +136,8 @@ public class AnnotationBeanNameGenerator implements BeanNameGenerator {
boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME) ||
annotationType.equals("javax.annotation.ManagedBean") ||
annotationType.equals("javax.inject.Named");
annotationType.equals("jakarta.annotation.ManagedBean") ||
annotationType.equals("jakarta.inject.Named");
return (isStereotype && attributes != null && attributes.containsKey("value"));
}

View File

@ -32,7 +32,7 @@ import org.springframework.util.Assert;
* Standalone application context, accepting <em>component classes</em> as input &mdash;
* in particular {@link Configuration @Configuration}-annotated classes, but also plain
* {@link org.springframework.stereotype.Component @Component} types and JSR-330 compliant
* classes using {@code javax.inject} annotations.
* classes using {@code jakarta.inject} annotations.
*
* <p>Allows for registering classes one by one using {@link #register(Class...)}
* as well as for classpath scanning using {@link #scan(String...)}.

View File

@ -123,8 +123,8 @@ public abstract class AnnotationConfigUtils {
static {
ClassLoader classLoader = AnnotationConfigUtils.class.getClassLoader();
jsr250Present = ClassUtils.isPresent("javax.annotation.Resource", classLoader);
jpaPresent = ClassUtils.isPresent("javax.persistence.EntityManagerFactory", classLoader) &&
jsr250Present = ClassUtils.isPresent("jakarta.annotation.Resource", classLoader);
jpaPresent = ClassUtils.isPresent("jakarta.persistence.EntityManagerFactory", classLoader) &&
ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, classLoader);
}

View File

@ -99,7 +99,7 @@ import org.springframework.core.annotation.AliasFor;
* <p><b>NOTE:</b> {@code @Order} values may influence priorities at injection points,
* but please be aware that they do not influence singleton startup order which is an
* orthogonal concern determined by dependency relationships and {@code @DependsOn}
* declarations as mentioned above. Also, {@link javax.annotation.Priority} is not
* declarations as mentioned above. Also, {@link jakarta.annotation.Priority} is not
* available at this level since it cannot be declared on methods; its semantics can
* be modeled through {@code @Order} values in combination with {@code @Primary} on
* a single bean per type.

View File

@ -47,8 +47,8 @@ import org.springframework.util.PatternMatchUtils;
* {@link org.springframework.stereotype.Service @Service}, or
* {@link org.springframework.stereotype.Controller @Controller} stereotype.
*
* <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
* JSR-330's {@link javax.inject.Named} annotations, if available.
* <p>Also supports Jakarta EE's {@link jakarta.annotation.ManagedBean} and
* JSR-330's {@link jakarta.inject.Named} annotations, if available.
*
* @author Mark Fisher
* @author Juergen Hoeller

View File

@ -197,8 +197,8 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
* {@link Component @Component} meta-annotation including the
* {@link Repository @Repository}, {@link Service @Service}, and
* {@link Controller @Controller} stereotype annotations.
* <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
* JSR-330's {@link javax.inject.Named} annotations, if available.
* <p>Also supports Jakarta EE's {@link jakarta.annotation.ManagedBean} and
* JSR-330's {@link jakarta.inject.Named} annotations, if available.
*
*/
@SuppressWarnings("unchecked")
@ -207,16 +207,16 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
((Class<? extends Annotation>) ClassUtils.forName("jakarta.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'jakarta.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
// JSR-250 1.1 API (as included in Jakarta EE) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
((Class<? extends Annotation>) ClassUtils.forName("jakarta.inject.Named", cl)), false));
logger.trace("JSR-330 'jakarta.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.

View File

@ -37,14 +37,15 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceRef;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import jakarta.ejb.EJB;
import jakarta.xml.ws.Service;
import jakarta.xml.ws.WebServiceClient;
import jakarta.xml.ws.WebServiceRef;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.ProxyFactory;
@ -77,36 +78,32 @@ import org.springframework.util.StringValueResolver;
/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
* that supports common Java annotations out of the box, in particular the JSR-250
* annotations in the {@code javax.annotation} package. These common Java
* annotations are supported in many Java EE 5 technologies (e.g. JSF 1.2),
* annotations in the {@code jakarta.annotation} package. These common Java
* annotations are supported in many Jakarta EE technologies (e.g. JSF 1.2),
* as well as in Java 6's JAX-WS.
*
* <p>This post-processor includes support for the {@link javax.annotation.PostConstruct}
* and {@link javax.annotation.PreDestroy} annotations - as init annotation
* <p>This post-processor includes support for the {@link jakarta.annotation.PostConstruct}
* and {@link jakarta.annotation.PreDestroy} annotations - as init annotation
* and destroy annotation, respectively - through inheriting from
* {@link InitDestroyAnnotationBeanPostProcessor} with pre-configured annotation types.
*
* <p>The central element is the {@link javax.annotation.Resource} annotation
* <p>The central element is the {@link jakarta.annotation.Resource} annotation
* for annotation-driven injection of named beans, by default from the containing
* Spring BeanFactory, with only {@code mappedName} references resolved in JNDI.
* The {@link #setAlwaysUseJndiLookup "alwaysUseJndiLookup" flag} enforces JNDI lookups
* equivalent to standard Java EE 5 resource injection for {@code name} references
* equivalent to standard Jakarta EE resource injection for {@code name} references
* and default names as well. The target beans can be simple POJOs, with no special
* requirements other than the type having to match.
*
* <p>The JAX-WS {@link javax.xml.ws.WebServiceRef} annotation is supported too,
* analogous to {@link javax.annotation.Resource} but with the capability of creating
* analogous to {@link jakarta.annotation.Resource} but with the capability of creating
* specific JAX-WS service endpoints. This may either point to an explicitly defined
* resource by name or operate on a locally specified JAX-WS service class. Finally,
* this post-processor also supports the EJB 3 {@link javax.ejb.EJB} annotation,
* analogous to {@link javax.annotation.Resource} as well, with the capability to
* this post-processor also supports the EJB 3 {@link jakarta.ejb.EJB} annotation,
* analogous to {@link jakarta.annotation.Resource} as well, with the capability to
* specify both a local bean name and a global JNDI name for fallback retrieval.
* The target beans can be plain POJOs as well as EJB 3 Session Beans in this case.
*
* <p>The common annotations supported by this post-processor are available in
* Java 6 (JDK 1.6) as well as in Java EE 5/6 (which provides a standalone jar for
* its common annotations as well, allowing for use in any Java 5 based application).
*
* <p>For default usage, resolving resource names as Spring bean names,
* simply define the following in your application context:
*
@ -114,7 +111,7 @@ import org.springframework.util.StringValueResolver;
* &lt;bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/&gt;</pre>
*
* For direct JNDI access, resolving resource names as JNDI resource references
* within the Java EE application's "java:comp/env/" namespace, use the following:
* within the Jakarta EE application's "java:comp/env/" namespace, use the following:
*
* <pre class="code">
* &lt;bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"&gt;
@ -156,7 +153,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
static {
webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef");
ejbClass = loadAnnotationType("javax.ejb.EJB");
ejbClass = loadAnnotationType("jakarta.ejb.EJB");
resourceAnnotationTypes.add(Resource.class);
if (webServiceRefClass != null) {
@ -191,7 +188,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
/**
* Create a new CommonAnnotationBeanPostProcessor,
* with the init and destroy annotation types set to
* {@link javax.annotation.PostConstruct} and {@link javax.annotation.PreDestroy},
* {@link jakarta.annotation.PostConstruct} and {@link jakarta.annotation.PreDestroy},
* respectively.
*/
public CommonAnnotationBeanPostProcessor() {
@ -229,11 +226,11 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
}
/**
* Set whether to always use JNDI lookups equivalent to standard Java EE 5 resource
* Set whether to always use JNDI lookups equivalent to standard Jakarta EE resource
* injection, <b>even for {@code name} attributes and default names</b>.
* <p>Default is "false": Resource names are used for Spring bean lookups in the
* containing BeanFactory; only {@code mappedName} attributes point directly
* into JNDI. Switch this flag to "true" for enforcing Java EE style JNDI lookups
* into JNDI. Switch this flag to "true" for enforcing Jakarta EE style JNDI lookups
* in any case, even for {@code name} attributes and default names.
* @see #setJndiFactory
* @see #setResourceFactory
@ -249,7 +246,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
* This factory will also be used if "alwaysUseJndiLookup" is set to "true" in order
* to enforce JNDI lookups even for {@code name} attributes and default names.
* <p>The default is a {@link org.springframework.jndi.support.SimpleJndiBeanFactory}
* for JNDI lookup behavior equivalent to standard Java EE 5 resource injection.
* for JNDI lookup behavior equivalent to standard Jakarta EE resource injection.
* @see #setResourceFactory
* @see #setAlwaysUseJndiLookup
*/
@ -266,7 +263,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
* if any, looking up resource names as Spring bean names. Specify the resource
* factory explicitly for programmatic usage of this post-processor.
* <p>Specifying Spring's {@link org.springframework.jndi.support.SimpleJndiBeanFactory}
* leads to JNDI lookup behavior equivalent to standard Java EE 5 resource injection,
* leads to JNDI lookup behavior equivalent to standard Jakarta EE resource injection,
* even for {@code name} attributes and default names. This is the same behavior
* that the "alwaysUseJndiLookup" flag enables.
* @see #setAlwaysUseJndiLookup

View File

@ -86,7 +86,7 @@ import org.springframework.stereotype.Component;
* <p>{@code @Configuration} is meta-annotated with {@link Component @Component}, therefore
* {@code @Configuration} classes are candidates for component scanning (typically using
* Spring XML's {@code <context:component-scan/>} element) and therefore may also take
* advantage of {@link Autowired @Autowired}/{@link javax.inject.Inject @Inject}
* advantage of {@link Autowired @Autowired}/{@link jakarta.inject.Inject @Inject}
* like any regular {@code @Component}. In particular, if a single constructor is present
* autowiring semantics will be applied transparently for that constructor:
*

View File

@ -26,7 +26,7 @@ import org.springframework.lang.Nullable;
/**
* Simple {@link ScopeMetadataResolver} implementation that follows JSR-330 scoping rules:
* defaulting to prototype scope unless {@link javax.inject.Singleton} is present.
* defaulting to prototype scope unless {@link jakarta.inject.Singleton} is present.
*
* <p>This scope resolver can be used with {@link ClassPathBeanDefinitionScanner} and
* {@link AnnotatedBeanDefinitionReader} for standard JSR-330 compliance. However,
@ -46,7 +46,7 @@ public class Jsr330ScopeMetadataResolver implements ScopeMetadataResolver {
public Jsr330ScopeMetadataResolver() {
registerScope("javax.inject.Singleton", BeanDefinition.SCOPE_SINGLETON);
registerScope("jakarta.inject.Singleton", BeanDefinition.SCOPE_SINGLETON);
}
@ -93,7 +93,7 @@ public class Jsr330ScopeMetadataResolver implements ScopeMetadataResolver {
String found = null;
for (String annType : annTypes) {
Set<String> metaAnns = annDef.getMetadata().getMetaAnnotationTypes(annType);
if (metaAnns.contains("javax.inject.Scope")) {
if (metaAnns.contains("jakarta.inject.Scope")) {
if (found != null) {
throw new IllegalStateException("Found ambiguous scope annotations on bean class [" +
definition.getBeanClassName() + "]: " + found + ", " + annType);

View File

@ -44,9 +44,9 @@ import java.lang.annotation.Target;
*
* <p>In addition to its role for component initialization, this annotation may also be placed
* on injection points marked with {@link org.springframework.beans.factory.annotation.Autowired}
* or {@link javax.inject.Inject}: In that context, it leads to the creation of a
* or {@link jakarta.inject.Inject}: In that context, it leads to the creation of a
* lazy-resolution proxy for all affected dependencies, as an alternative to using
* {@link org.springframework.beans.factory.ObjectFactory} or {@link javax.inject.Provider}.
* {@link org.springframework.beans.factory.ObjectFactory} or {@link jakarta.inject.Provider}.
*
* @author Chris Beams
* @author Juergen Hoeller

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,7 +19,6 @@ package org.springframework.context.annotation;
import java.util.Map;
import javax.management.MBeanServer;
import javax.naming.NamingException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@ -28,14 +27,10 @@ import org.springframework.context.EnvironmentAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.jmx.MBeanServerNotFoundException;
import org.springframework.jmx.export.annotation.AnnotationMBeanExporter;
import org.springframework.jmx.support.RegistrationPolicy;
import org.springframework.jmx.support.WebSphereMBeanServerFactoryBean;
import org.springframework.jndi.JndiLocatorDelegate;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
@ -116,15 +111,6 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
Assert.state(this.beanFactory != null, "No BeanFactory set");
exporter.setServer(this.beanFactory.getBean(server, MBeanServer.class));
}
else {
SpecificPlatform specificPlatform = SpecificPlatform.get();
if (specificPlatform != null) {
MBeanServer mbeanServer = specificPlatform.getMBeanServer();
if (mbeanServer != null) {
exporter.setServer(mbeanServer);
}
}
}
}
private void setupRegistrationPolicy(AnnotationMBeanExporter exporter, AnnotationAttributes enableMBeanExport) {
@ -132,58 +118,4 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
exporter.setRegistrationPolicy(registrationPolicy);
}
/**
* Specific platforms that might need custom MBean handling.
*/
public enum SpecificPlatform {
/**
* Weblogic.
*/
WEBLOGIC("weblogic.management.Helper") {
@Override
public MBeanServer getMBeanServer() {
try {
return new JndiLocatorDelegate().lookup("java:comp/env/jmx/runtime", MBeanServer.class);
}
catch (NamingException ex) {
throw new MBeanServerNotFoundException("Failed to retrieve WebLogic MBeanServer from JNDI", ex);
}
}
},
/**
* Websphere.
*/
WEBSPHERE("com.ibm.websphere.management.AdminServiceFactory") {
@Override
public MBeanServer getMBeanServer() {
WebSphereMBeanServerFactoryBean fb = new WebSphereMBeanServerFactoryBean();
fb.afterPropertiesSet();
return fb.getObject();
}
};
private final String identifyingClass;
SpecificPlatform(String identifyingClass) {
this.identifyingClass = identifyingClass;
}
@Nullable
public abstract MBeanServer getMBeanServer();
@Nullable
public static SpecificPlatform get() {
ClassLoader classLoader = MBeanExportConfiguration.class.getClassLoader();
for (SpecificPlatform environment : values()) {
if (ClassUtils.isPresent(environment.identifyingClass, classLoader)) {
return environment;
}
}
return null;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -76,12 +76,6 @@ class MBeanExportBeanDefinitionParser extends AbstractBeanDefinitionParser {
if (StringUtils.hasText(serverBeanName)) {
builder.addPropertyReference("server", serverBeanName);
}
else {
AbstractBeanDefinition specialServer = MBeanServerBeanDefinitionParser.findServerForSpecialEnvironment();
if (specialServer != null) {
builder.addPropertyValue("server", specialServer);
}
}
String registration = element.getAttribute(REGISTRATION_ATTRIBUTE);
RegistrationPolicy registrationPolicy = RegistrationPolicy.FAIL_ON_EXISTING;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -24,10 +24,6 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.jmx.support.MBeanServerFactoryBean;
import org.springframework.jmx.support.WebSphereMBeanServerFactoryBean;
import org.springframework.jndi.JndiObjectFactoryBean;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
@ -49,17 +45,6 @@ class MBeanServerBeanDefinitionParser extends AbstractBeanDefinitionParser {
private static final String AGENT_ID_ATTRIBUTE = "agent-id";
private static final boolean weblogicPresent;
private static final boolean webspherePresent;
static {
ClassLoader classLoader = MBeanServerBeanDefinitionParser.class.getClassLoader();
weblogicPresent = ClassUtils.isPresent("weblogic.management.Helper", classLoader);
webspherePresent = ClassUtils.isPresent("com.ibm.websphere.management.AdminServiceFactory", classLoader);
}
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
String id = element.getAttribute(ID_ATTRIBUTE);
@ -74,10 +59,7 @@ class MBeanServerBeanDefinitionParser extends AbstractBeanDefinitionParser {
bd.getPropertyValues().add("agentId", agentId);
return bd;
}
AbstractBeanDefinition specialServer = findServerForSpecialEnvironment();
if (specialServer != null) {
return specialServer;
}
RootBeanDefinition bd = new RootBeanDefinition(MBeanServerFactoryBean.class);
bd.getPropertyValues().add("locateExistingServerIfPossible", Boolean.TRUE);
@ -87,19 +69,4 @@ class MBeanServerBeanDefinitionParser extends AbstractBeanDefinitionParser {
return bd;
}
@Nullable
static AbstractBeanDefinition findServerForSpecialEnvironment() {
if (weblogicPresent) {
RootBeanDefinition bd = new RootBeanDefinition(JndiObjectFactoryBean.class);
bd.getPropertyValues().add("jndiName", "java:comp/env/jmx/runtime");
return bd;
}
else if (webspherePresent) {
return new RootBeanDefinition(WebSphereMBeanServerFactoryBean.class);
}
else {
return null;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,8 +30,6 @@ import org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver;
import org.springframework.instrument.classloading.glassfish.GlassFishLoadTimeWeaver;
import org.springframework.instrument.classloading.jboss.JBossLoadTimeWeaver;
import org.springframework.instrument.classloading.tomcat.TomcatLoadTimeWeaver;
import org.springframework.instrument.classloading.weblogic.WebLogicLoadTimeWeaver;
import org.springframework.instrument.classloading.websphere.WebSphereLoadTimeWeaver;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@ -45,10 +43,9 @@ import org.springframework.util.Assert;
* on a {@code @Configuration} class.
*
* <p>This class implements a runtime environment check for obtaining the
* appropriate weaver implementation. As of Spring Framework 5.0, it detects
* Oracle WebLogic 10+, GlassFish 4+, Tomcat 8+, WildFly 8+, IBM WebSphere 8.5+,
* {@link InstrumentationSavingAgent Spring's VM agent}, and any {@link ClassLoader}
* supported by Spring's {@link ReflectiveLoadTimeWeaver} (such as Liberty's).
* appropriate weaver implementation, including
* {@link InstrumentationSavingAgent Spring's VM agent} and any {@link ClassLoader}
* supported by Spring's {@link ReflectiveLoadTimeWeaver}.
*
* @author Juergen Hoeller
* @author Ramnivas Laddad
@ -120,12 +117,6 @@ public class DefaultContextLoadTimeWeaver implements LoadTimeWeaver, BeanClassLo
else if (name.startsWith("org.jboss.modules")) {
return new JBossLoadTimeWeaver(classLoader);
}
else if (name.startsWith("com.ibm.ws.classloader")) {
return new WebSphereLoadTimeWeaver(classLoader);
}
else if (name.startsWith("weblogic")) {
return new WebLogicLoadTimeWeaver(classLoader);
}
}
catch (Exception ex) {
if (logger.isInfoEnabled()) {

View File

@ -1,213 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ejb.access;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import javax.ejb.EJBHome;
import javax.ejb.EJBObject;
import javax.naming.NamingException;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.lang.Nullable;
import org.springframework.remoting.RemoteConnectFailureException;
import org.springframework.remoting.RemoteLookupFailureException;
/**
* Base class for interceptors proxying remote Stateless Session Beans.
* Designed for EJB 2.x, but works for EJB 3 Session Beans as well.
*
* <p>Such an interceptor must be the last interceptor in the advice chain.
* In this case, there is no target object.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public abstract class AbstractRemoteSlsbInvokerInterceptor extends AbstractSlsbInvokerInterceptor {
private boolean refreshHomeOnConnectFailure = false;
private volatile boolean homeAsComponent;
/**
* Set whether to refresh the EJB home on connect failure.
* Default is "false".
* <p>Can be turned on to allow for hot restart of the EJB server.
* If a cached EJB home throws an RMI exception that indicates a
* remote connect failure, a fresh home will be fetched and the
* invocation will be retried.
* @see java.rmi.ConnectException
* @see java.rmi.ConnectIOException
* @see java.rmi.NoSuchObjectException
*/
public void setRefreshHomeOnConnectFailure(boolean refreshHomeOnConnectFailure) {
this.refreshHomeOnConnectFailure = refreshHomeOnConnectFailure;
}
@Override
protected boolean isHomeRefreshable() {
return this.refreshHomeOnConnectFailure;
}
/**
* Check for EJB3-style home object that serves as EJB component directly.
*/
@Override
protected Method getCreateMethod(Object home) throws EjbAccessException {
if (this.homeAsComponent) {
return null;
}
if (!(home instanceof EJBHome)) {
// An EJB3 Session Bean...
this.homeAsComponent = true;
return null;
}
return super.getCreateMethod(home);
}
/**
* Fetches an EJB home object and delegates to {@code doInvoke}.
* <p>If configured to refresh on connect failure, it will call
* {@link #refreshAndRetry} on corresponding RMI exceptions.
* @see #getHome
* @see #doInvoke
* @see #refreshAndRetry
*/
@Override
@Nullable
public Object invokeInContext(MethodInvocation invocation) throws Throwable {
try {
return doInvoke(invocation);
}
catch (RemoteConnectFailureException ex) {
return handleRemoteConnectFailure(invocation, ex);
}
catch (RemoteException ex) {
if (isConnectFailure(ex)) {
return handleRemoteConnectFailure(invocation, ex);
}
else {
throw ex;
}
}
}
/**
* Determine whether the given RMI exception indicates a connect failure.
* <p>The default implementation delegates to RmiClientInterceptorUtils.
* @param ex the RMI exception to check
* @return whether the exception should be treated as connect failure
* @see org.springframework.remoting.rmi.RmiClientInterceptorUtils#isConnectFailure
*/
@SuppressWarnings("deprecation")
protected boolean isConnectFailure(RemoteException ex) {
return org.springframework.remoting.rmi.RmiClientInterceptorUtils.isConnectFailure(ex);
}
@Nullable
private Object handleRemoteConnectFailure(MethodInvocation invocation, Exception ex) throws Throwable {
if (this.refreshHomeOnConnectFailure) {
if (logger.isDebugEnabled()) {
logger.debug("Could not connect to remote EJB [" + getJndiName() + "] - retrying", ex);
}
else if (logger.isWarnEnabled()) {
logger.warn("Could not connect to remote EJB [" + getJndiName() + "] - retrying");
}
return refreshAndRetry(invocation);
}
else {
throw ex;
}
}
/**
* Refresh the EJB home object and retry the given invocation.
* Called by invoke on connect failure.
* @param invocation the AOP method invocation
* @return the invocation result, if any
* @throws Throwable in case of invocation failure
* @see #invoke
*/
@Nullable
protected Object refreshAndRetry(MethodInvocation invocation) throws Throwable {
try {
refreshHome();
}
catch (NamingException ex) {
throw new RemoteLookupFailureException("Failed to locate remote EJB [" + getJndiName() + "]", ex);
}
return doInvoke(invocation);
}
/**
* Perform the given invocation on the current EJB home.
* Template method to be implemented by subclasses.
* @param invocation the AOP method invocation
* @return the invocation result, if any
* @throws Throwable in case of invocation failure
* @see #getHome
* @see #newSessionBeanInstance
*/
@Nullable
protected abstract Object doInvoke(MethodInvocation invocation) throws Throwable;
/**
* Return a new instance of the stateless session bean.
* To be invoked by concrete remote SLSB invoker subclasses.
* <p>Can be overridden to change the algorithm.
* @throws NamingException if thrown by JNDI
* @throws InvocationTargetException if thrown by the create method
* @see #create
*/
protected Object newSessionBeanInstance() throws NamingException, InvocationTargetException {
if (logger.isDebugEnabled()) {
logger.debug("Trying to create reference to remote EJB");
}
Object ejbInstance = create();
if (logger.isDebugEnabled()) {
logger.debug("Obtained reference to remote EJB: " + ejbInstance);
}
return ejbInstance;
}
/**
* Remove the given EJB instance.
* To be invoked by concrete remote SLSB invoker subclasses.
* @param ejb the EJB instance to remove
* @see javax.ejb.EJBObject#remove
*/
protected void removeSessionBeanInstance(@Nullable EJBObject ejb) {
if (ejb != null && !this.homeAsComponent) {
try {
ejb.remove();
}
catch (Throwable ex) {
logger.warn("Could not invoke 'remove' on remote EJB proxy", ex);
}
}
}
}

View File

@ -1,238 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ejb.access;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.naming.Context;
import javax.naming.NamingException;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.jndi.JndiObjectLocator;
import org.springframework.lang.Nullable;
/**
* Base class for AOP interceptors invoking local or remote Stateless Session Beans.
* Designed for EJB 2.x, but works for EJB 3 Session Beans as well.
*
* <p>Such an interceptor must be the last interceptor in the advice chain.
* In this case, there is no direct target object: The call is handled in a
* special way, getting executed on an EJB instance retrieved via an EJB home.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public abstract class AbstractSlsbInvokerInterceptor extends JndiObjectLocator
implements MethodInterceptor {
private boolean lookupHomeOnStartup = true;
private boolean cacheHome = true;
private boolean exposeAccessContext = false;
/**
* The EJB's home object, potentially cached.
* The type must be Object as it could be either EJBHome or EJBLocalHome.
*/
@Nullable
private Object cachedHome;
/**
* The no-arg create() method required on EJB homes, potentially cached.
*/
@Nullable
private Method createMethod;
private final Object homeMonitor = new Object();
/**
* Set whether to look up the EJB home object on startup.
* Default is "true".
* <p>Can be turned off to allow for late start of the EJB server.
* In this case, the EJB home object will be fetched on first access.
* @see #setCacheHome
*/
public void setLookupHomeOnStartup(boolean lookupHomeOnStartup) {
this.lookupHomeOnStartup = lookupHomeOnStartup;
}
/**
* Set whether to cache the EJB home object once it has been located.
* Default is "true".
* <p>Can be turned off to allow for hot restart of the EJB server.
* In this case, the EJB home object will be fetched for each invocation.
* @see #setLookupHomeOnStartup
*/
public void setCacheHome(boolean cacheHome) {
this.cacheHome = cacheHome;
}
/**
* Set whether to expose the JNDI environment context for all access to the target
* EJB, i.e. for all method invocations on the exposed object reference.
* <p>Default is "false", i.e. to only expose the JNDI context for object lookup.
* Switch this flag to "true" in order to expose the JNDI environment (including
* the authorization context) for each EJB invocation, as needed by WebLogic
* for EJBs with authorization requirements.
*/
public void setExposeAccessContext(boolean exposeAccessContext) {
this.exposeAccessContext = exposeAccessContext;
}
/**
* Fetches EJB home on startup, if necessary.
* @see #setLookupHomeOnStartup
* @see #refreshHome
*/
@Override
public void afterPropertiesSet() throws NamingException {
super.afterPropertiesSet();
if (this.lookupHomeOnStartup) {
// look up EJB home and create method
refreshHome();
}
}
/**
* Refresh the cached home object, if applicable.
* Also caches the create method on the home object.
* @throws NamingException if thrown by the JNDI lookup
* @see #lookup
* @see #getCreateMethod
*/
protected void refreshHome() throws NamingException {
synchronized (this.homeMonitor) {
Object home = lookup();
if (this.cacheHome) {
this.cachedHome = home;
this.createMethod = getCreateMethod(home);
}
}
}
/**
* Determine the create method of the given EJB home object.
* @param home the EJB home object
* @return the create method
* @throws EjbAccessException if the method couldn't be retrieved
*/
@Nullable
protected Method getCreateMethod(Object home) throws EjbAccessException {
try {
// Cache the EJB create() method that must be declared on the home interface.
return home.getClass().getMethod("create");
}
catch (NoSuchMethodException ex) {
throw new EjbAccessException("EJB home [" + home + "] has no no-arg create() method");
}
}
/**
* Return the EJB home object to use. Called for each invocation.
* <p>Default implementation returns the home created on initialization,
* if any; else, it invokes lookup to get a new proxy for each invocation.
* <p>Can be overridden in subclasses, for example to cache a home object
* for a given amount of time before recreating it, or to test the home
* object whether it is still alive.
* @return the EJB home object to use for an invocation
* @throws NamingException if proxy creation failed
* @see #lookup
* @see #getCreateMethod
*/
protected Object getHome() throws NamingException {
if (!this.cacheHome || (this.lookupHomeOnStartup && !isHomeRefreshable())) {
return (this.cachedHome != null ? this.cachedHome : lookup());
}
else {
synchronized (this.homeMonitor) {
if (this.cachedHome == null) {
this.cachedHome = lookup();
this.createMethod = getCreateMethod(this.cachedHome);
}
return this.cachedHome;
}
}
}
/**
* Return whether the cached EJB home object is potentially
* subject to on-demand refreshing. Default is "false".
*/
protected boolean isHomeRefreshable() {
return false;
}
/**
* Prepares the thread context if necessary, and delegates to
* {@link #invokeInContext}.
*/
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Context ctx = (this.exposeAccessContext ? getJndiTemplate().getContext() : null);
try {
return invokeInContext(invocation);
}
finally {
getJndiTemplate().releaseContext(ctx);
}
}
/**
* Perform the given invocation on the current EJB home,
* within the thread context being prepared accordingly.
* Template method to be implemented by subclasses.
* @param invocation the AOP method invocation
* @return the invocation result, if any
* @throws Throwable in case of invocation failure
*/
@Nullable
protected abstract Object invokeInContext(MethodInvocation invocation) throws Throwable;
/**
* Invokes the {@code create()} method on the cached EJB home object.
* @return a new EJBObject or EJBLocalObject
* @throws NamingException if thrown by JNDI
* @throws InvocationTargetException if thrown by the create method
*/
protected Object create() throws NamingException, InvocationTargetException {
try {
Object home = getHome();
Method createMethodToUse = this.createMethod;
if (createMethodToUse == null) {
createMethodToUse = getCreateMethod(home);
}
if (createMethodToUse == null) {
return home;
}
// Invoke create() method on EJB home object.
return createMethodToUse.invoke(home, (Object[]) null);
}
catch (IllegalAccessException ex) {
throw new EjbAccessException("Could not access EJB home create() method", ex);
}
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ejb.access;
import org.springframework.core.NestedRuntimeException;
/**
* Exception that gets thrown when an EJB stub cannot be accessed properly.
*
* @author Juergen Hoeller
* @since 2.0
*/
@SuppressWarnings("serial")
public class EjbAccessException extends NestedRuntimeException {
/**
* Constructor for EjbAccessException.
* @param msg the detail message
*/
public EjbAccessException(String msg) {
super(msg);
}
/**
* Constructor for EjbAccessException.
* @param msg the detail message
* @param cause the root cause
*/
public EjbAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@ -1,179 +0,0 @@
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ejb.access;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.ejb.CreateException;
import javax.ejb.EJBLocalHome;
import javax.ejb.EJBLocalObject;
import javax.naming.NamingException;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.lang.Nullable;
/**
* Invoker for a local Stateless Session Bean.
* Designed for EJB 2.x, but works for EJB 3 Session Beans as well.
*
* <p>Caches the home object, since a local EJB home can never go stale.
* See {@link org.springframework.jndi.JndiObjectLocator} for info on
* how to specify the JNDI location of the target EJB.
*
* <p>In a bean container, this class is normally best used as a singleton. However,
* if that bean container pre-instantiates singletons (as do the XML ApplicationContext
* variants) you may have a problem if the bean container is loaded before the EJB
* container loads the target EJB. That is because by default the JNDI lookup will be
* performed in the init method of this class and cached, but the EJB will not have been
* bound at the target location yet. The best solution is to set the lookupHomeOnStartup
* property to false, in which case the home will be fetched on first access to the EJB.
* (This flag is only true by default for backwards compatibility reasons).
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see AbstractSlsbInvokerInterceptor#setLookupHomeOnStartup
* @see AbstractSlsbInvokerInterceptor#setCacheHome
*/
public class LocalSlsbInvokerInterceptor extends AbstractSlsbInvokerInterceptor {
private volatile boolean homeAsComponent;
/**
* This implementation "creates" a new EJB instance for each invocation.
* Can be overridden for custom invocation strategies.
* <p>Alternatively, override {@link #getSessionBeanInstance} and
* {@link #releaseSessionBeanInstance} to change EJB instance creation,
* for example to hold a single shared EJB instance.
*/
@Override
@Nullable
public Object invokeInContext(MethodInvocation invocation) throws Throwable {
Object ejb = null;
try {
ejb = getSessionBeanInstance();
Method method = invocation.getMethod();
if (method.getDeclaringClass().isInstance(ejb)) {
// directly implemented
return method.invoke(ejb, invocation.getArguments());
}
else {
// not directly implemented
Method ejbMethod = ejb.getClass().getMethod(method.getName(), method.getParameterTypes());
return ejbMethod.invoke(ejb, invocation.getArguments());
}
}
catch (InvocationTargetException ex) {
Throwable targetEx = ex.getTargetException();
if (logger.isDebugEnabled()) {
logger.debug("Method of local EJB [" + getJndiName() + "] threw exception", targetEx);
}
if (targetEx instanceof CreateException) {
throw new EjbAccessException("Could not create local EJB [" + getJndiName() + "]", targetEx);
}
else {
throw targetEx;
}
}
catch (NamingException ex) {
throw new EjbAccessException("Failed to locate local EJB [" + getJndiName() + "]", ex);
}
catch (IllegalAccessException ex) {
throw new EjbAccessException("Could not access method [" + invocation.getMethod().getName() +
"] of local EJB [" + getJndiName() + "]", ex);
}
finally {
if (ejb instanceof EJBLocalObject) {
releaseSessionBeanInstance((EJBLocalObject) ejb);
}
}
}
/**
* Check for EJB3-style home object that serves as EJB component directly.
*/
@Override
protected Method getCreateMethod(Object home) throws EjbAccessException {
if (this.homeAsComponent) {
return null;
}
if (!(home instanceof EJBLocalHome)) {
// An EJB3 Session Bean...
this.homeAsComponent = true;
return null;
}
return super.getCreateMethod(home);
}
/**
* Return an EJB instance to delegate the call to.
* Default implementation delegates to newSessionBeanInstance.
* @throws NamingException if thrown by JNDI
* @throws InvocationTargetException if thrown by the create method
* @see #newSessionBeanInstance
*/
protected Object getSessionBeanInstance() throws NamingException, InvocationTargetException {
return newSessionBeanInstance();
}
/**
* Release the given EJB instance.
* Default implementation delegates to removeSessionBeanInstance.
* @param ejb the EJB instance to release
* @see #removeSessionBeanInstance
*/
protected void releaseSessionBeanInstance(EJBLocalObject ejb) {
removeSessionBeanInstance(ejb);
}
/**
* Return a new instance of the stateless session bean.
* Can be overridden to change the algorithm.
* @throws NamingException if thrown by JNDI
* @throws InvocationTargetException if thrown by the create method
* @see #create
*/
protected Object newSessionBeanInstance() throws NamingException, InvocationTargetException {
if (logger.isDebugEnabled()) {
logger.debug("Trying to create reference to local EJB");
}
Object ejbInstance = create();
if (logger.isDebugEnabled()) {
logger.debug("Obtained reference to local EJB: " + ejbInstance);
}
return ejbInstance;
}
/**
* Remove the given EJB instance.
* @param ejb the EJB instance to remove
* @see javax.ejb.EJBLocalObject#remove()
*/
protected void removeSessionBeanInstance(@Nullable EJBLocalObject ejb) {
if (ejb != null && !this.homeAsComponent) {
try {
ejb.remove();
}
catch (Throwable ex) {
logger.warn("Could not invoke 'remove' on local EJB proxy", ex);
}
}
}
}

View File

@ -1,116 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ejb.access;
import javax.naming.NamingException;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
* Convenient {@link FactoryBean} for local Stateless Session Bean (SLSB) proxies.
* Designed for EJB 2.x, but works for EJB 3 Session Beans as well.
*
* <p>See {@link org.springframework.jndi.JndiObjectLocator} for info on
* how to specify the JNDI location of the target EJB.
*
* <p>If you want control over interceptor chaining, use an AOP ProxyFactoryBean
* with LocalSlsbInvokerInterceptor rather than rely on this class.
*
* <p>In a bean container, this class is normally best used as a singleton. However,
* if that bean container pre-instantiates singletons (as do the XML ApplicationContext
* variants) you may have a problem if the bean container is loaded before the EJB
* container loads the target EJB. That is because by default the JNDI lookup will be
* performed in the init method of this class and cached, but the EJB will not have been
* bound at the target location yet. The best solution is to set the "lookupHomeOnStartup"
* property to "false", in which case the home will be fetched on first access to the EJB.
* (This flag is only true by default for backwards compatibility reasons).
*
* @author Rod Johnson
* @author Colin Sampaleanu
* @since 09.05.2003
* @see AbstractSlsbInvokerInterceptor#setLookupHomeOnStartup
* @see AbstractSlsbInvokerInterceptor#setCacheHome
*/
public class LocalStatelessSessionProxyFactoryBean extends LocalSlsbInvokerInterceptor
implements FactoryBean<Object>, BeanClassLoaderAware {
/** The business interface of the EJB we're proxying. */
@Nullable
private Class<?> businessInterface;
@Nullable
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
/** EJBLocalObject. */
@Nullable
private Object proxy;
/**
* Set the business interface of the EJB we're proxying.
* This will normally be a super-interface of the EJB local component interface.
* Using a business methods interface is a best practice when implementing EJBs.
* @param businessInterface set the business interface of the EJB
*/
public void setBusinessInterface(@Nullable Class<?> businessInterface) {
this.businessInterface = businessInterface;
}
/**
* Return the business interface of the EJB we're proxying.
*/
@Nullable
public Class<?> getBusinessInterface() {
return this.businessInterface;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@Override
public void afterPropertiesSet() throws NamingException {
super.afterPropertiesSet();
if (this.businessInterface == null) {
throw new IllegalArgumentException("businessInterface is required");
}
this.proxy = new ProxyFactory(this.businessInterface, this).getProxy(this.beanClassLoader);
}
@Override
@Nullable
public Object getObject() {
return this.proxy;
}
@Override
public Class<?> getObjectType() {
return this.businessInterface;
}
@Override
public boolean isSingleton() {
return true;
}
}

View File

@ -1,188 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ejb.access;
import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBObject;
import javax.naming.NamingException;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.lang.Nullable;
import org.springframework.remoting.RemoteLookupFailureException;
/**
* Basic invoker for a remote Stateless Session Bean.
* Designed for EJB 2.x, but works for EJB 3 Session Beans as well.
*
* <p>"Creates" a new EJB instance for each invocation, or caches the session
* bean instance for all invocations (see {@link #setCacheSessionBean}).
* See {@link org.springframework.jndi.JndiObjectLocator} for info on
* how to specify the JNDI location of the target EJB.
*
* <p>In a bean container, this class is normally best used as a singleton. However,
* if that bean container pre-instantiates singletons (as do the XML ApplicationContext
* variants) you may have a problem if the bean container is loaded before the EJB
* container loads the target EJB. That is because by default the JNDI lookup will be
* performed in the init method of this class and cached, but the EJB will not have been
* bound at the target location yet. The best solution is to set the "lookupHomeOnStartup"
* property to "false", in which case the home will be fetched on first access to the EJB.
* (This flag is only true by default for backwards compatibility reasons).
*
* <p>This invoker is typically used with an RMI business interface, which serves
* as super-interface of the EJB component interface. Alternatively, this invoker
* can also proxy a remote SLSB with a matching non-RMI business interface, i.e. an
* interface that mirrors the EJB business methods but does not declare RemoteExceptions.
* In the latter case, RemoteExceptions thrown by the EJB stub will automatically get
* converted to Spring's unchecked RemoteAccessException.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 09.05.2003
* @see org.springframework.remoting.RemoteAccessException
* @see AbstractSlsbInvokerInterceptor#setLookupHomeOnStartup
* @see AbstractSlsbInvokerInterceptor#setCacheHome
* @see AbstractRemoteSlsbInvokerInterceptor#setRefreshHomeOnConnectFailure
*/
public class SimpleRemoteSlsbInvokerInterceptor extends AbstractRemoteSlsbInvokerInterceptor
implements DisposableBean {
private boolean cacheSessionBean = false;
@Nullable
private Object beanInstance;
private final Object beanInstanceMonitor = new Object();
/**
* Set whether to cache the actual session bean object.
* <p>Off by default for standard EJB compliance. Turn this flag
* on to optimize session bean access for servers that are
* known to allow for caching the actual session bean object.
* @see #setCacheHome
*/
public void setCacheSessionBean(boolean cacheSessionBean) {
this.cacheSessionBean = cacheSessionBean;
}
/**
* This implementation "creates" a new EJB instance for each invocation.
* Can be overridden for custom invocation strategies.
* <p>Alternatively, override {@link #getSessionBeanInstance} and
* {@link #releaseSessionBeanInstance} to change EJB instance creation,
* for example to hold a single shared EJB component instance.
*/
@Override
@Nullable
@SuppressWarnings("deprecation")
protected Object doInvoke(MethodInvocation invocation) throws Throwable {
Object ejb = null;
try {
ejb = getSessionBeanInstance();
return org.springframework.remoting.rmi.RmiClientInterceptorUtils.invokeRemoteMethod(invocation, ejb);
}
catch (NamingException ex) {
throw new RemoteLookupFailureException("Failed to locate remote EJB [" + getJndiName() + "]", ex);
}
catch (InvocationTargetException ex) {
Throwable targetEx = ex.getTargetException();
if (targetEx instanceof RemoteException) {
RemoteException rex = (RemoteException) targetEx;
throw org.springframework.remoting.rmi.RmiClientInterceptorUtils.convertRmiAccessException(
invocation.getMethod(), rex, isConnectFailure(rex), getJndiName());
}
else if (targetEx instanceof CreateException) {
throw org.springframework.remoting.rmi.RmiClientInterceptorUtils.convertRmiAccessException(
invocation.getMethod(), targetEx, "Could not create remote EJB [" + getJndiName() + "]");
}
throw targetEx;
}
finally {
if (ejb instanceof EJBObject) {
releaseSessionBeanInstance((EJBObject) ejb);
}
}
}
/**
* Return an EJB component instance to delegate the call to.
* <p>The default implementation delegates to {@link #newSessionBeanInstance}.
* @return the EJB component instance
* @throws NamingException if thrown by JNDI
* @throws InvocationTargetException if thrown by the create method
* @see #newSessionBeanInstance
*/
protected Object getSessionBeanInstance() throws NamingException, InvocationTargetException {
if (this.cacheSessionBean) {
synchronized (this.beanInstanceMonitor) {
if (this.beanInstance == null) {
this.beanInstance = newSessionBeanInstance();
}
return this.beanInstance;
}
}
else {
return newSessionBeanInstance();
}
}
/**
* Release the given EJB instance.
* <p>The default implementation delegates to {@link #removeSessionBeanInstance}.
* @param ejb the EJB component instance to release
* @see #removeSessionBeanInstance
*/
protected void releaseSessionBeanInstance(EJBObject ejb) {
if (!this.cacheSessionBean) {
removeSessionBeanInstance(ejb);
}
}
/**
* Reset the cached session bean instance, if necessary.
*/
@Override
protected void refreshHome() throws NamingException {
super.refreshHome();
if (this.cacheSessionBean) {
synchronized (this.beanInstanceMonitor) {
this.beanInstance = null;
}
}
}
/**
* Remove the cached session bean instance, if necessary.
*/
@Override
public void destroy() {
if (this.cacheSessionBean) {
synchronized (this.beanInstanceMonitor) {
if (this.beanInstance instanceof EJBObject) {
removeSessionBeanInstance((EJBObject) this.beanInstance);
}
}
}
}
}

View File

@ -1,130 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ejb.access;
import javax.naming.NamingException;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
* Convenient {@link FactoryBean} for remote SLSB proxies.
* Designed for EJB 2.x, but works for EJB 3 Session Beans as well.
*
* <p>See {@link org.springframework.jndi.JndiObjectLocator} for info on
* how to specify the JNDI location of the target EJB.
*
* <p>If you want control over interceptor chaining, use an AOP ProxyFactoryBean
* with SimpleRemoteSlsbInvokerInterceptor rather than rely on this class.
*
* <p>In a bean container, this class is normally best used as a singleton. However,
* if that bean container pre-instantiates singletons (as do the XML ApplicationContext
* variants) you may have a problem if the bean container is loaded before the EJB
* container loads the target EJB. That is because by default the JNDI lookup will be
* performed in the init method of this class and cached, but the EJB will not have been
* bound at the target location yet. The best solution is to set the lookupHomeOnStartup
* property to false, in which case the home will be fetched on first access to the EJB.
* (This flag is only true by default for backwards compatibility reasons).
*
* <p>This proxy factory is typically used with an RMI business interface, which serves
* as super-interface of the EJB component interface. Alternatively, this factory
* can also proxy a remote SLSB with a matching non-RMI business interface, i.e. an
* interface that mirrors the EJB business methods but does not declare RemoteExceptions.
* In the latter case, RemoteExceptions thrown by the EJB stub will automatically get
* converted to Spring's unchecked RemoteAccessException.
*
* @author Rod Johnson
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @since 09.05.2003
* @see org.springframework.remoting.RemoteAccessException
* @see AbstractSlsbInvokerInterceptor#setLookupHomeOnStartup
* @see AbstractSlsbInvokerInterceptor#setCacheHome
* @see AbstractRemoteSlsbInvokerInterceptor#setRefreshHomeOnConnectFailure
*/
public class SimpleRemoteStatelessSessionProxyFactoryBean extends SimpleRemoteSlsbInvokerInterceptor
implements FactoryBean<Object>, BeanClassLoaderAware {
/** The business interface of the EJB we're proxying. */
@Nullable
private Class<?> businessInterface;
@Nullable
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
/** EJBObject. */
@Nullable
private Object proxy;
/**
* Set the business interface of the EJB we're proxying.
* This will normally be a super-interface of the EJB remote component interface.
* Using a business methods interface is a best practice when implementing EJBs.
* <p>You can also specify a matching non-RMI business interface, i.e. an interface
* that mirrors the EJB business methods but does not declare RemoteExceptions.
* In this case, RemoteExceptions thrown by the EJB stub will automatically get
* converted to Spring's generic RemoteAccessException.
* @param businessInterface the business interface of the EJB
*/
public void setBusinessInterface(@Nullable Class<?> businessInterface) {
this.businessInterface = businessInterface;
}
/**
* Return the business interface of the EJB we're proxying.
*/
@Nullable
public Class<?> getBusinessInterface() {
return this.businessInterface;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@Override
public void afterPropertiesSet() throws NamingException {
super.afterPropertiesSet();
if (this.businessInterface == null) {
throw new IllegalArgumentException("businessInterface is required");
}
this.proxy = new ProxyFactory(this.businessInterface, this).getProxy(this.beanClassLoader);
}
@Override
@Nullable
public Object getObject() {
return this.proxy;
}
@Override
public Class<?> getObjectType() {
return this.businessInterface;
}
@Override
public boolean isSingleton() {
return true;
}
}

View File

@ -1,27 +0,0 @@
/**
* This package contains classes that allow easy access to EJBs.
* The basis are AOP interceptors run before and after the EJB invocation.
* In particular, the classes in this package allow transparent access
* to stateless session beans (SLSBs) with local interfaces, avoiding
* the need for application code using them to use EJB-specific APIs
* and JNDI lookups, and work with business interfaces that could be
* implemented without using EJB. This provides a valuable decoupling
* of client (such as web components) and business objects (which may
* or may not be EJBs). This gives us the choice of introducing EJB
* into an application (or removing EJB from an application) without
* affecting code using business objects.
*
* <p>The motivation for the classes in this package is discussed in Chapter 11 of
* <a href="https://www.amazon.com/exec/obidos/tg/detail/-/0764543857/">Expert One-On-One J2EE Design and Development</a>
* by Rod Johnson (Wrox, 2002).
*
* <p>However, the implementation and naming of classes in this package has changed.
* It now uses FactoryBeans and AOP, rather than the custom bean definitions described in
* <i>Expert One-on-One J2EE</i>.
*/
@NonNullApi
@NonNullFields
package org.springframework.ejb.access;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,12 +18,12 @@ package org.springframework.ejb.config;
import org.w3c.dom.Element;
import org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean;
import org.springframework.jndi.JndiObjectFactoryBean;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser}
* implementation for parsing '{@code local-slsb}' tags and
* creating {@link LocalStatelessSessionProxyFactoryBean} definitions.
* creating plain {@link JndiObjectFactoryBean} definitions.
*
* @author Rob Harrop
* @author Juergen Hoeller
@ -32,8 +32,8 @@ import org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean;
class LocalStatelessSessionBeanDefinitionParser extends AbstractJndiLocatingBeanDefinitionParser {
@Override
protected String getBeanClassName(Element element) {
return "org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean";
protected Class<?> getBeanClass(Element element) {
return JndiObjectFactoryBean.class;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,12 +18,12 @@ package org.springframework.ejb.config;
import org.w3c.dom.Element;
import org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean;
import org.springframework.jndi.JndiObjectFactoryBean;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser}
* implementation for parsing '{@code remote-slsb}' tags and
* creating {@link SimpleRemoteStatelessSessionProxyFactoryBean} definitions.
* creating plain {@link JndiObjectFactoryBean} definitions.
*
* @author Rob Harrop
* @author Juergen Hoeller
@ -32,8 +32,8 @@ import org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBe
class RemoteStatelessSessionBeanDefinitionParser extends AbstractJndiLocatingBeanDefinitionParser {
@Override
protected String getBeanClassName(Element element) {
return "org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean";
protected Class<?> getBeanClass(Element element) {
return JndiObjectFactoryBean.class;
}
}

View File

@ -1,5 +1,5 @@
/**
* Support package for EJB/Java EE-related configuration,
* Support package for EJB/Jakarta EE-related configuration,
* with XML schema being the primary configuration format.
*/
@NonNullApi

View File

@ -1,117 +0,0 @@
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.instrument.classloading.weblogic;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.util.Assert;
/**
* Reflective wrapper around a WebLogic 10 class loader. Used to
* encapsulate the classloader-specific methods (discovered and
* called through reflection) from the load-time weaver.
*
* @author Costin Leau
* @author Juergen Hoeller
* @since 2.5
*/
class WebLogicClassLoaderAdapter {
private static final String GENERIC_CLASS_LOADER_NAME = "weblogic.utils.classloaders.GenericClassLoader";
private static final String CLASS_PRE_PROCESSOR_NAME = "weblogic.utils.classloaders.ClassPreProcessor";
private final ClassLoader classLoader;
private final Class<?> wlPreProcessorClass;
private final Method addPreProcessorMethod;
private final Method getClassFinderMethod;
private final Method getParentMethod;
private final Constructor<?> wlGenericClassLoaderConstructor;
public WebLogicClassLoaderAdapter(ClassLoader classLoader) {
Class<?> wlGenericClassLoaderClass;
try {
wlGenericClassLoaderClass = classLoader.loadClass(GENERIC_CLASS_LOADER_NAME);
this.wlPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
this.addPreProcessorMethod = classLoader.getClass().getMethod(
"addInstanceClassPreProcessor", this.wlPreProcessorClass);
this.getClassFinderMethod = classLoader.getClass().getMethod("getClassFinder");
this.getParentMethod = classLoader.getClass().getMethod("getParent");
this.wlGenericClassLoaderConstructor = wlGenericClassLoaderClass.getConstructor(
this.getClassFinderMethod.getReturnType(), ClassLoader.class);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Could not initialize WebLogic LoadTimeWeaver because WebLogic 10 API classes are not available", ex);
}
if (!wlGenericClassLoaderClass.isInstance(classLoader)) {
throw new IllegalArgumentException(
"ClassLoader must be an instance of [" + wlGenericClassLoaderClass.getName() + "]: " + classLoader);
}
this.classLoader = classLoader;
}
public void addTransformer(ClassFileTransformer transformer) {
Assert.notNull(transformer, "ClassFileTransformer must not be null");
try {
InvocationHandler adapter = new WebLogicClassPreProcessorAdapter(transformer, this.classLoader);
Object adapterInstance = Proxy.newProxyInstance(this.wlPreProcessorClass.getClassLoader(),
new Class<?>[] {this.wlPreProcessorClass}, adapter);
this.addPreProcessorMethod.invoke(this.classLoader, adapterInstance);
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("WebLogic addInstanceClassPreProcessor method threw exception", ex.getCause());
}
catch (Throwable ex) {
throw new IllegalStateException("Could not invoke WebLogic addInstanceClassPreProcessor method", ex);
}
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
public ClassLoader getThrowawayClassLoader() {
try {
Object classFinder = this.getClassFinderMethod.invoke(this.classLoader);
Object parent = this.getParentMethod.invoke(this.classLoader);
// arguments for 'clone'-like method
return (ClassLoader) this.wlGenericClassLoaderConstructor.newInstance(classFinder, parent);
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("WebLogic GenericClassLoader constructor failed", ex.getCause());
}
catch (Throwable ex) {
throw new IllegalStateException("Could not construct WebLogic GenericClassLoader", ex);
}
}
}

View File

@ -1,97 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.instrument.classloading.weblogic;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Hashtable;
import org.springframework.lang.Nullable;
/**
* Adapter that implements WebLogic ClassPreProcessor interface, delegating to a
* standard JDK {@link ClassFileTransformer} underneath.
*
* <p>To avoid compile time checks again the vendor API, a dynamic proxy is
* being used.
*
* @author Costin Leau
* @author Juergen Hoeller
* @since 2.5
*/
class WebLogicClassPreProcessorAdapter implements InvocationHandler {
private final ClassFileTransformer transformer;
private final ClassLoader loader;
/**
* Construct a new {@link WebLogicClassPreProcessorAdapter}.
*/
public WebLogicClassPreProcessorAdapter(ClassFileTransformer transformer, ClassLoader loader) {
this.transformer = transformer;
this.loader = loader;
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if ("equals".equals(name)) {
return (proxy == args[0]);
}
else if ("hashCode".equals(name)) {
return hashCode();
}
else if ("toString".equals(name)) {
return toString();
}
else if ("initialize".equals(name)) {
initialize((Hashtable<?, ?>) args[0]);
return null;
}
else if ("preProcess".equals(name)) {
return preProcess((String) args[0], (byte[]) args[1]);
}
else {
throw new IllegalArgumentException("Unknown method: " + method);
}
}
public void initialize(Hashtable<?, ?> params) {
}
public byte[] preProcess(String className, byte[] classBytes) {
try {
byte[] result = this.transformer.transform(this.loader, className, null, null, classBytes);
return (result != null ? result : classBytes);
}
catch (IllegalClassFormatException ex) {
throw new IllegalStateException("Cannot transform due to illegal class format", ex);
}
}
@Override
public String toString() {
return getClass().getName() + " for transformer: " + this.transformer;
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.instrument.classloading.weblogic;
import java.lang.instrument.ClassFileTransformer;
import org.springframework.core.OverridingClassLoader;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* {@link LoadTimeWeaver} implementation for WebLogic's instrumentable
* ClassLoader.
*
* <p><b>NOTE:</b> Requires BEA WebLogic version 10 or higher.
*
* @author Costin Leau
* @author Juergen Hoeller
* @since 2.5
*/
public class WebLogicLoadTimeWeaver implements LoadTimeWeaver {
private final WebLogicClassLoaderAdapter classLoader;
/**
* Creates a new instance of the {@link WebLogicLoadTimeWeaver} class using
* the default {@link ClassLoader class loader}.
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
public WebLogicLoadTimeWeaver() {
this(ClassUtils.getDefaultClassLoader());
}
/**
* Creates a new instance of the {@link WebLogicLoadTimeWeaver} class using
* the supplied {@link ClassLoader}.
* @param classLoader the {@code ClassLoader} to delegate to for weaving
*/
public WebLogicLoadTimeWeaver(@Nullable ClassLoader classLoader) {
Assert.notNull(classLoader, "ClassLoader must not be null");
this.classLoader = new WebLogicClassLoaderAdapter(classLoader);
}
@Override
public void addTransformer(ClassFileTransformer transformer) {
this.classLoader.addTransformer(transformer);
}
@Override
public ClassLoader getInstrumentableClassLoader() {
return this.classLoader.getClassLoader();
}
@Override
public ClassLoader getThrowawayClassLoader() {
return new OverridingClassLoader(this.classLoader.getClassLoader(),
this.classLoader.getThrowawayClassLoader());
}
}

View File

@ -1,9 +0,0 @@
/**
* Support for class instrumentation on BEA WebLogic 10+.
*/
@NonNullApi
@NonNullFields
package org.springframework.instrument.classloading.weblogic;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

Some files were not shown because too many files have changed in this diff Show More