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

@@ -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;

View File

@@ -1,120 +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.websphere;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import org.springframework.util.Assert;
/**
* Reflective wrapper around a WebSphere 7+ 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 3.1
*/
class WebSphereClassLoaderAdapter {
private static final String COMPOUND_CLASS_LOADER_NAME = "com.ibm.ws.classloader.CompoundClassLoader";
private static final String CLASS_PRE_PROCESSOR_NAME = "com.ibm.websphere.classloader.ClassLoaderInstancePreDefinePlugin";
private static final String PLUGINS_FIELD = "preDefinePlugins";
private ClassLoader classLoader;
private Class<?> wsPreProcessorClass;
private Method addPreDefinePlugin;
private Constructor<? extends ClassLoader> cloneConstructor;
private Field transformerList;
public WebSphereClassLoaderAdapter(ClassLoader classLoader) {
Class<?> wsCompoundClassLoaderClass;
try {
wsCompoundClassLoaderClass = classLoader.loadClass(COMPOUND_CLASS_LOADER_NAME);
this.cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass);
this.cloneConstructor.setAccessible(true);
this.wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
this.addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", this.wsPreProcessorClass);
this.transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD);
this.transformerList.setAccessible(true);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Could not initialize WebSphere LoadTimeWeaver because WebSphere API classes are not available", ex);
}
if (!wsCompoundClassLoaderClass.isInstance(classLoader)) {
throw new IllegalArgumentException(
"ClassLoader must be an instance of [" + COMPOUND_CLASS_LOADER_NAME + "]: " + classLoader);
}
this.classLoader = classLoader;
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
public void addTransformer(ClassFileTransformer transformer) {
Assert.notNull(transformer, "ClassFileTransformer must not be null");
try {
InvocationHandler adapter = new WebSphereClassPreDefinePlugin(transformer);
Object adapterInstance = Proxy.newProxyInstance(this.wsPreProcessorClass.getClassLoader(),
new Class<?>[] {this.wsPreProcessorClass}, adapter);
this.addPreDefinePlugin.invoke(this.classLoader, adapterInstance);
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("WebSphere addPreDefinePlugin method threw exception", ex.getCause());
}
catch (Throwable ex) {
throw new IllegalStateException("Could not invoke WebSphere addPreDefinePlugin method", ex);
}
}
public ClassLoader getThrowawayClassLoader() {
try {
ClassLoader loader = this.cloneConstructor.newInstance(getClassLoader());
// Clear out the transformers (copied as well)
List<?> list = (List<?>) this.transformerList.get(loader);
list.clear();
return loader;
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("WebSphere CompoundClassLoader constructor failed", ex.getCause());
}
catch (Throwable ex) {
throw new IllegalStateException("Could not construct WebSphere CompoundClassLoader", ex);
}
}
}

View File

@@ -1,95 +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.instrument.classloading.websphere;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.security.CodeSource;
import org.springframework.util.FileCopyUtils;
/**
* Adapter that implements WebSphere 7.0 ClassPreProcessPlugin 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
* @since 3.1
*/
class WebSphereClassPreDefinePlugin implements InvocationHandler {
private final ClassFileTransformer transformer;
/**
* Create a new {@link WebSphereClassPreDefinePlugin}.
* @param transformer the {@link ClassFileTransformer} to be adapted
* (must not be {@code null})
*/
public WebSphereClassPreDefinePlugin(ClassFileTransformer transformer) {
this.transformer = transformer;
ClassLoader classLoader = transformer.getClass().getClassLoader();
// First force the full class loading of the weaver by invoking transformation on a dummy class
try {
String dummyClass = Dummy.class.getName().replace('.', '/');
byte[] bytes = FileCopyUtils.copyToByteArray(classLoader.getResourceAsStream(dummyClass + ".class"));
transformer.transform(classLoader, dummyClass, null, null, bytes);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot load transformer", ex);
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
case "equals":
return (proxy == args[0]);
case "hashCode":
return hashCode();
case "toString":
return toString();
case "transformClass":
return transform((String) args[0], (byte[]) args[1], (CodeSource) args[2], (ClassLoader) args[3]);
default:
throw new IllegalArgumentException("Unknown method: " + method);
}
}
protected byte[] transform(String className, byte[] classfileBuffer, CodeSource codeSource, ClassLoader classLoader)
throws Exception {
// NB: WebSphere passes className as "." without class while the transformer expects a VM "/" format
byte[] result = this.transformer.transform(classLoader, className.replace('.', '/'), null, null, classfileBuffer);
return (result != null ? result : classfileBuffer);
}
@Override
public String toString() {
return getClass().getName() + " for transformer: " + this.transformer;
}
private static class Dummy {
}
}

View File

@@ -1,75 +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.websphere;
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 WebSphere's instrumentable ClassLoader.
* Compatible with WebSphere 7 as well as 8 and 9.
*
* @author Costin Leau
* @since 3.1
*/
public class WebSphereLoadTimeWeaver implements LoadTimeWeaver {
private final WebSphereClassLoaderAdapter classLoader;
/**
* Create a new instance of the {@link WebSphereLoadTimeWeaver} class using
* the default {@link ClassLoader class loader}.
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
public WebSphereLoadTimeWeaver() {
this(ClassUtils.getDefaultClassLoader());
}
/**
* Create a new instance of the {@link WebSphereLoadTimeWeaver} class using
* the supplied {@link ClassLoader}.
* @param classLoader the {@code ClassLoader} to delegate to for weaving
*/
public WebSphereLoadTimeWeaver(@Nullable ClassLoader classLoader) {
Assert.notNull(classLoader, "ClassLoader must not be null");
this.classLoader = new WebSphereClassLoaderAdapter(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 IBM WebSphere Application Server 7+.
*/
@NonNullApi
@NonNullFields
package org.springframework.instrument.classloading.websphere;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

View File

@@ -1,105 +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.jmx.support;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.management.MBeanServer;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jmx.MBeanServerNotFoundException;
import org.springframework.lang.Nullable;
/**
* {@link FactoryBean} that obtains a WebSphere {@link javax.management.MBeanServer}
* reference through WebSphere's proprietary {@code AdminServiceFactory} API,
* available on WebSphere 5.1 and higher.
*
* <p>Exposes the {@code MBeanServer} for bean references.
*
* <p>This {@code FactoryBean} is a direct alternative to {@link MBeanServerFactoryBean},
* which uses standard JMX 1.2 API to access the platform's {@link MBeanServer}.
*
* <p>See the javadocs for WebSphere's
* <a href="https://www.ibm.com/support/knowledgecenter/SSEQTJ_9.0.0/com.ibm.websphere.javadoc.doc/web/apidocs/com/ibm/websphere/management/AdminServiceFactory.html">{@code AdminServiceFactory}</a>
* and
* <a href="https://www.ibm.com/support/knowledgecenter/SSEQTJ_9.0.0/com.ibm.websphere.javadoc.doc/web/apidocs/com/ibm/websphere/management/MBeanFactory.html">{@code MBeanFactory}</a>.
*
* @author Juergen Hoeller
* @author Rob Harrop
* @since 2.0.3
* @see javax.management.MBeanServer
* @see MBeanServerFactoryBean
*/
public class WebSphereMBeanServerFactoryBean implements FactoryBean<MBeanServer>, InitializingBean {
private static final String ADMIN_SERVICE_FACTORY_CLASS = "com.ibm.websphere.management.AdminServiceFactory";
private static final String GET_MBEAN_FACTORY_METHOD = "getMBeanFactory";
private static final String GET_MBEAN_SERVER_METHOD = "getMBeanServer";
@Nullable
private MBeanServer mbeanServer;
@Override
public void afterPropertiesSet() throws MBeanServerNotFoundException {
try {
/*
* this.mbeanServer = AdminServiceFactory.getMBeanFactory().getMBeanServer();
*/
Class<?> adminServiceClass = getClass().getClassLoader().loadClass(ADMIN_SERVICE_FACTORY_CLASS);
Method getMBeanFactoryMethod = adminServiceClass.getMethod(GET_MBEAN_FACTORY_METHOD);
Object mbeanFactory = getMBeanFactoryMethod.invoke(null);
Method getMBeanServerMethod = mbeanFactory.getClass().getMethod(GET_MBEAN_SERVER_METHOD);
this.mbeanServer = (MBeanServer) getMBeanServerMethod.invoke(mbeanFactory);
}
catch (ClassNotFoundException ex) {
throw new MBeanServerNotFoundException("Could not find WebSphere's AdminServiceFactory class", ex);
}
catch (InvocationTargetException ex) {
throw new MBeanServerNotFoundException(
"WebSphere's AdminServiceFactory.getMBeanFactory/getMBeanServer method failed", ex.getTargetException());
}
catch (Exception ex) {
throw new MBeanServerNotFoundException(
"Could not access WebSphere's AdminServiceFactory.getMBeanFactory/getMBeanServer method", ex);
}
}
@Override
@Nullable
public MBeanServer getObject() {
return this.mbeanServer;
}
@Override
public Class<? extends MBeanServer> getObjectType() {
return (this.mbeanServer != null ? this.mbeanServer.getClass() : MBeanServer.class);
}
@Override
public boolean isSingleton() {
return true;
}
}

View File

@@ -77,7 +77,7 @@ public class JndiLocatorDelegate extends JndiLocatorSupport {
}
/**
* Check whether a default JNDI environment, as in a Java EE environment,
* Check whether a default JNDI environment, as in a Jakarta EE environment,
* is available on this JVM.
* @return {@code true} if a default InitialContext can be used,
* {@code false} if not

View File

@@ -27,7 +27,7 @@ import org.springframework.util.Assert;
* bean properties.
*
* <p>JNDI names may or may not include the "java:comp/env/" prefix expected
* by Java EE applications when accessing a locally mapped (ENC - Environmental
* by Jakarta EE applications when accessing a locally mapped (ENC - Environmental
* Naming Context) resource. If it doesn't, the "java:comp/env/" prefix will
* be prepended if the "resourceRef" property is true (the default is
* <strong>false</strong>) and no other scheme (e.g. "java:") is given.
@@ -40,7 +40,7 @@ import org.springframework.util.Assert;
*/
public abstract class JndiLocatorSupport extends JndiAccessor {
/** JNDI prefix used in a Java EE container. */
/** JNDI prefix used in a Jakarta EE container. */
public static final String CONTAINER_PREFIX = "java:comp/env/";
@@ -48,7 +48,7 @@ public abstract class JndiLocatorSupport extends JndiAccessor {
/**
* Set whether the lookup occurs in a Java EE container, i.e. if the prefix
* Set whether the lookup occurs in a Jakarta EE container, i.e. if the prefix
* "java:comp/env/" needs to be added if the JNDI name doesn't already
* contain it. Default is "false".
* <p>Note: Will only get applied if no other scheme (e.g. "java:") is given.
@@ -58,7 +58,7 @@ public abstract class JndiLocatorSupport extends JndiAccessor {
}
/**
* Return whether the lookup occurs in a Java EE container.
* Return whether the lookup occurs in a Jakarta EE container.
*/
public boolean isResourceRef() {
return this.resourceRef;

View File

@@ -28,7 +28,7 @@ import org.springframework.util.StringUtils;
* providing configurable lookup of a specific JNDI resource.
*
* <p>Exposes a {@link #setJndiName "jndiName"} property. This may or may not
* include the "java:comp/env/" prefix expected by Java EE applications when
* include the "java:comp/env/" prefix expected by Jakarta EE applications when
* accessing a locally mapped (Environmental Naming Context) resource. If it
* doesn't, the "java:comp/env/" prefix will be prepended if the "resourceRef"
* property is true (the default is <strong>false</strong>) and no other scheme

View File

@@ -39,7 +39,7 @@ import org.springframework.lang.Nullable;
* &lt;/bean&gt;
*
* &lt;bean id="queueConnectionFactory" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
* &lt;property name="proxyInterfaces" value="javax.jms.QueueConnectionFactory"/&gt;
* &lt;property name="proxyInterfaces" value="jakarta.jms.QueueConnectionFactory"/&gt;
* &lt;property name="targetSource" ref="queueConnectionFactoryTarget"/&gt;
* &lt;/bean&gt;</pre>
*

View File

@@ -44,7 +44,7 @@ import org.springframework.lang.Nullable;
* the {@link org.springframework.beans.factory.ListableBeanFactory} interface.
*
* <p>This factory resolves given bean names as JNDI names within the
* Java EE application's "java:comp/env/" namespace. It caches the resolved
* Jakarta EE application's "java:comp/env/" namespace. It caches the resolved
* types for all obtained objects, and optionally also caches shareable
* objects (if they are explicitly marked as
* {@link #addShareableResource shareable resource}.

View File

@@ -39,7 +39,7 @@ import org.springframework.lang.Nullable;
* and adding extended trigger capabilities.
*
* <p>This interface is roughly equivalent to a JSR-236
* {@code ManagedScheduledExecutorService} as supported in Java EE 7
* {@code ManagedScheduledExecutorService} as supported in Jakarta EE
* environments but aligned with Spring's {@code TaskExecutor} model.
*
* @author Juergen Hoeller

View File

@@ -41,7 +41,7 @@ import java.lang.annotation.Target;
* {@code Future} that can be used to track the result of the asynchronous method
* execution. However, since the target method needs to implement the same signature,
* it will have to return a temporary {@code Future} handle that just passes a value
* through: e.g. Spring's {@link AsyncResult}, EJB 3.1's {@link javax.ejb.AsyncResult},
* through: e.g. Spring's {@link AsyncResult}, EJB 3.1's {@link jakarta.ejb.AsyncResult},
* or {@link java.util.concurrent.CompletableFuture#completedFuture(Object)}.
*
* @author Juergen Hoeller

View File

@@ -42,7 +42,7 @@ import org.springframework.util.function.SingletonSupplier;
* annotation. This annotation can be used at the method and type level in
* implementation classes as well as in service interfaces.
*
* <p>This advisor detects the EJB 3.1 {@code javax.ejb.Asynchronous}
* <p>This advisor detects the EJB 3.1 {@code jakarta.ejb.Asynchronous}
* annotation as well, treating it exactly like Spring's own {@code Async}.
* Furthermore, a custom async annotation type may get specified through the
* {@link #setAsyncAnnotationType "asyncAnnotationType"} property.
@@ -99,7 +99,7 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
asyncAnnotationTypes.add(Async.class);
try {
asyncAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader()));
ClassUtils.forName("jakarta.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
// If EJB 3.1 API not present, simply ignore.
@@ -112,7 +112,7 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
/**
* Set the 'async' annotation type.
* <p>The default async annotation type is the {@link Async} annotation, as well
* as the EJB 3.1 {@code javax.ejb.Asynchronous} annotation (if present).
* as the EJB 3.1 {@code jakarta.ejb.Asynchronous} annotation (if present).
* <p>This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation type to indicate that a method is to
* be executed asynchronously.

View File

@@ -42,7 +42,7 @@ import org.springframework.util.function.SingletonSupplier;
* be provided as well as the annotation type that indicates a method should be
* invoked asynchronously. If no annotation type is specified, this post-
* processor will detect both Spring's {@link Async @Async} annotation as well
* as the EJB 3.1 {@code javax.ejb.Asynchronous} annotation.
* as the EJB 3.1 {@code jakarta.ejb.Asynchronous} annotation.
*
* <p>For methods having a {@code void} return type, any exception thrown
* during the asynchronous method invocation cannot be accessed by the
@@ -130,7 +130,7 @@ public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAd
/**
* Set the 'async' annotation type to be detected at either class or method
* level. By default, both the {@link Async} annotation and the EJB 3.1
* {@code javax.ejb.Asynchronous} annotation will be detected.
* {@code jakarta.ejb.Asynchronous} annotation will be detected.
* <p>This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation type to indicate that a method (or all
* methods of a given class) should be invoked asynchronously.

View File

@@ -43,7 +43,7 @@ import org.springframework.core.Ordered;
* }</pre>
*
* {@code MyAsyncBean} is a user-defined type with one or more methods annotated with
* either Spring's {@code @Async} annotation, the EJB 3.1 {@code @javax.ejb.Asynchronous}
* either Spring's {@code @Async} annotation, the EJB 3.1 {@code @jakarta.ejb.Asynchronous}
* annotation, or any custom annotation specified via the {@link #annotation} attribute.
* The aspect is added transparently for any registered bean, for instance via this
* configuration:
@@ -166,7 +166,7 @@ public @interface EnableAsync {
* Indicate the 'async' annotation type to be detected at either class
* or method level.
* <p>By default, both Spring's @{@link Async} annotation and the EJB 3.1
* {@code @javax.ejb.Asynchronous} annotation will be detected.
* {@code @jakarta.ejb.Asynchronous} annotation will be detected.
* <p>This attribute exists so that developers can provide their own
* custom annotation type to indicate that a method (or all methods of
* a given class) should be invoked asynchronously.

View File

@@ -23,8 +23,8 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.enterprise.concurrent.ManagedExecutors;
import javax.enterprise.concurrent.ManagedTask;
import jakarta.enterprise.concurrent.ManagedExecutors;
import jakarta.enterprise.concurrent.ManagedTask;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.core.task.TaskDecorator;
@@ -41,11 +41,11 @@ import org.springframework.util.concurrent.ListenableFuture;
* Also detects an extended {@code java.util.concurrent.ExecutorService}, adapting
* the {@link org.springframework.core.task.AsyncTaskExecutor} interface accordingly.
*
* <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedExecutorService}
* in order to expose {@link javax.enterprise.concurrent.ManagedTask} adapters for it,
* <p>Autodetects a JSR-236 {@link jakarta.enterprise.concurrent.ManagedExecutorService}
* in order to expose {@link jakarta.enterprise.concurrent.ManagedTask} adapters for it,
* exposing a long-running hint based on {@link SchedulingAwareRunnable} and an identity
* name based on the given Runnable/Callable's {@code toString()}. For JSR-236 style
* lookup in a Java EE 7 environment, consider using {@link DefaultManagedTaskExecutor}.
* lookup in a Jakarta EE environment, consider using {@link DefaultManagedTaskExecutor}.
*
* <p>Note that there is a pre-built {@link ThreadPoolTaskExecutor} that allows
* for defining a {@link java.util.concurrent.ThreadPoolExecutor} in bean style,
@@ -70,7 +70,7 @@ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, Sche
static {
try {
managedExecutorServiceClass = ClassUtils.forName(
"javax.enterprise.concurrent.ManagedExecutorService",
"jakarta.enterprise.concurrent.ManagedExecutorService",
ConcurrentTaskScheduler.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
@@ -95,8 +95,8 @@ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, Sche
/**
* Create a new ConcurrentTaskExecutor, using the given {@link java.util.concurrent.Executor}.
* <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedExecutorService}
* in order to expose {@link javax.enterprise.concurrent.ManagedTask} adapters for it.
* <p>Autodetects a JSR-236 {@link jakarta.enterprise.concurrent.ManagedExecutorService}
* in order to expose {@link jakarta.enterprise.concurrent.ManagedTask} adapters for it.
* @param executor the {@link java.util.concurrent.Executor} to delegate to
*/
public ConcurrentTaskExecutor(@Nullable Executor executor) {
@@ -107,8 +107,8 @@ public class ConcurrentTaskExecutor implements AsyncListenableTaskExecutor, Sche
/**
* Specify the {@link java.util.concurrent.Executor} to delegate to.
* <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedExecutorService}
* in order to expose {@link javax.enterprise.concurrent.ManagedTask} adapters for it.
* <p>Autodetects a JSR-236 {@link jakarta.enterprise.concurrent.ManagedExecutorService}
* in order to expose {@link jakarta.enterprise.concurrent.ManagedTask} adapters for it.
*/
public final void setConcurrentExecutor(@Nullable Executor executor) {
this.concurrentExecutor = (executor != null ? executor : Executors.newSingleThreadExecutor());

View File

@@ -25,8 +25,8 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.enterprise.concurrent.LastExecution;
import javax.enterprise.concurrent.ManagedScheduledExecutorService;
import jakarta.enterprise.concurrent.LastExecution;
import jakarta.enterprise.concurrent.ManagedScheduledExecutorService;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.lang.Nullable;
@@ -44,11 +44,11 @@ import org.springframework.util.ErrorHandler;
* Extends {@link ConcurrentTaskExecutor} in order to implement the
* {@link org.springframework.scheduling.SchedulingTaskExecutor} interface as well.
*
* <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
* <p>Autodetects a JSR-236 {@link jakarta.enterprise.concurrent.ManagedScheduledExecutorService}
* in order to use it for trigger-based scheduling if possible, instead of Spring's
* local trigger management which ends up delegating to regular delay-based scheduling
* against the {@code java.util.concurrent.ScheduledExecutorService} API. For JSR-236 style
* lookup in a Java EE 7 environment, consider using {@link DefaultManagedTaskScheduler}.
* lookup in a Jakarta EE environment, consider using {@link DefaultManagedTaskScheduler}.
*
* <p>Note that there is a pre-built {@link ThreadPoolTaskScheduler} that allows for
* defining a {@link java.util.concurrent.ScheduledThreadPoolExecutor} in bean style,
@@ -73,7 +73,7 @@ public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements T
static {
try {
managedScheduledExecutorServiceClass = ClassUtils.forName(
"javax.enterprise.concurrent.ManagedScheduledExecutorService",
"jakarta.enterprise.concurrent.ManagedScheduledExecutorService",
ConcurrentTaskScheduler.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
@@ -106,7 +106,7 @@ public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements T
/**
* Create a new ConcurrentTaskScheduler, using the given
* {@link java.util.concurrent.ScheduledExecutorService} as shared delegate.
* <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
* <p>Autodetects a JSR-236 {@link jakarta.enterprise.concurrent.ManagedScheduledExecutorService}
* in order to use it for trigger-based scheduling if possible,
* instead of Spring's local trigger management.
* @param scheduledExecutor the {@link java.util.concurrent.ScheduledExecutorService}
@@ -121,7 +121,7 @@ public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements T
/**
* Create a new ConcurrentTaskScheduler, using the given {@link java.util.concurrent.Executor}
* and {@link java.util.concurrent.ScheduledExecutorService} as delegates.
* <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
* <p>Autodetects a JSR-236 {@link jakarta.enterprise.concurrent.ManagedScheduledExecutorService}
* in order to use it for trigger-based scheduling if possible,
* instead of Spring's local trigger management.
* @param concurrentExecutor the {@link java.util.concurrent.Executor} to delegate to
@@ -150,7 +150,7 @@ public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements T
/**
* Specify the {@link java.util.concurrent.ScheduledExecutorService} to delegate to.
* <p>Autodetects a JSR-236 {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
* <p>Autodetects a JSR-236 {@link jakarta.enterprise.concurrent.ManagedScheduledExecutorService}
* in order to use it for trigger-based scheduling if possible,
* instead of Spring's local trigger management.
* <p>Note: This will only apply to {@link TaskScheduler} invocations.
@@ -275,7 +275,7 @@ public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements T
public ScheduledFuture<?> schedule(Runnable task, final Trigger trigger) {
ManagedScheduledExecutorService executor = (ManagedScheduledExecutorService) scheduledExecutor;
return executor.schedule(task, new javax.enterprise.concurrent.Trigger() {
return executor.schedule(task, new jakarta.enterprise.concurrent.Trigger() {
@Override
@Nullable
public Date getNextRunTime(@Nullable LastExecution le, Date taskScheduledTime) {

View File

@@ -31,10 +31,10 @@ import org.springframework.lang.Nullable;
/**
* JNDI-based variant of {@link CustomizableThreadFactory}, performing a default lookup
* for JSR-236's "java:comp/DefaultManagedThreadFactory" in a Java EE 7 environment,
* for JSR-236's "java:comp/DefaultManagedThreadFactory" in a Jakarta EE environment,
* falling back to the local {@link CustomizableThreadFactory} setup if not found.
*
* <p>This is a convenient way to use managed threads when running in a Java EE 7
* <p>This is a convenient way to use managed threads when running in a Jakarta EE
* environment, simply using regular local threads otherwise - without conditional
* setup (i.e. without profiles).
*
@@ -77,7 +77,7 @@ public class DefaultManagedAwareThreadFactory extends CustomizableThreadFactory
}
/**
* Set whether the lookup occurs in a Java EE container, i.e. if the prefix
* Set whether the lookup occurs in a Jakarta EE container, i.e. if the prefix
* "java:comp/env/" needs to be added if the JNDI name doesn't already
* contain it. PersistenceAnnotationBeanPostProcessor's default is "true".
* @see org.springframework.jndi.JndiLocatorSupport#setResourceRef

View File

@@ -28,16 +28,16 @@ import org.springframework.lang.Nullable;
/**
* JNDI-based variant of {@link ConcurrentTaskExecutor}, performing a default lookup for
* JSR-236's "java:comp/DefaultManagedExecutorService" in a Java EE 7/8 environment.
* JSR-236's "java:comp/DefaultManagedExecutorService" in a Jakarta EE/8 environment.
*
* <p>Note: This class is not strictly JSR-236 based; it can work with any regular
* {@link java.util.concurrent.Executor} that can be found in JNDI.
* The actual adapting to {@link javax.enterprise.concurrent.ManagedExecutorService}
* The actual adapting to {@link jakarta.enterprise.concurrent.ManagedExecutorService}
* happens in the base class {@link ConcurrentTaskExecutor} itself.
*
* @author Juergen Hoeller
* @since 4.0
* @see javax.enterprise.concurrent.ManagedExecutorService
* @see jakarta.enterprise.concurrent.ManagedExecutorService
*/
public class DefaultManagedTaskExecutor extends ConcurrentTaskExecutor implements InitializingBean {
@@ -64,7 +64,7 @@ public class DefaultManagedTaskExecutor extends ConcurrentTaskExecutor implement
}
/**
* Set whether the lookup occurs in a Java EE container, i.e. if the prefix
* Set whether the lookup occurs in a Jakarta EE container, i.e. if the prefix
* "java:comp/env/" needs to be added if the JNDI name doesn't already
* contain it. PersistenceAnnotationBeanPostProcessor's default is "true".
* @see org.springframework.jndi.JndiLocatorSupport#setResourceRef

View File

@@ -28,16 +28,16 @@ import org.springframework.lang.Nullable;
/**
* JNDI-based variant of {@link ConcurrentTaskScheduler}, performing a default lookup for
* JSR-236's "java:comp/DefaultManagedScheduledExecutorService" in a Java EE 7 environment.
* JSR-236's "java:comp/DefaultManagedScheduledExecutorService" in a Jakarta EE environment.
*
* <p>Note: This class is not strictly JSR-236 based; it can work with any regular
* {@link java.util.concurrent.ScheduledExecutorService} that can be found in JNDI.
* The actual adapting to {@link javax.enterprise.concurrent.ManagedScheduledExecutorService}
* The actual adapting to {@link jakarta.enterprise.concurrent.ManagedScheduledExecutorService}
* happens in the base class {@link ConcurrentTaskScheduler} itself.
*
* @author Juergen Hoeller
* @since 4.0
* @see javax.enterprise.concurrent.ManagedScheduledExecutorService
* @see jakarta.enterprise.concurrent.ManagedScheduledExecutorService
*/
public class DefaultManagedTaskScheduler extends ConcurrentTaskScheduler implements InitializingBean {
@@ -64,7 +64,7 @@ public class DefaultManagedTaskScheduler extends ConcurrentTaskScheduler impleme
}
/**
* Set whether the lookup occurs in a Java EE container, i.e. if the prefix
* Set whether the lookup occurs in a Jakarta EE container, i.e. if the prefix
* "java:comp/env/" needs to be added if the JNDI name doesn't already
* contain it. PersistenceAnnotationBeanPostProcessor's default is "true".
* @see org.springframework.jndi.JndiLocatorSupport#setResourceRef

View File

@@ -71,7 +71,7 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
/**
* Set the ThreadFactory to use for the ExecutorService's thread pool.
* Default is the underlying ExecutorService's default thread factory.
* <p>In a Java EE 7 or other managed environment with JSR-236 support,
* <p>In a Jakarta EE or other managed environment with JSR-236 support,
* consider specifying a JNDI-located ManagedThreadFactory: by default,
* to be found at "java:comp/DefaultManagedThreadFactory".
* Use the "jee:jndi-lookup" namespace element in XML or the programmatic
@@ -79,7 +79,7 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
* Alternatively, consider using Spring's {@link DefaultManagedAwareThreadFactory}
* with its fallback to local threads in case of no managed thread factory found.
* @see java.util.concurrent.Executors#defaultThreadFactory()
* @see javax.enterprise.concurrent.ManagedThreadFactory
* @see jakarta.enterprise.concurrent.ManagedThreadFactory
* @see DefaultManagedAwareThreadFactory
*/
public void setThreadFactory(@Nullable ThreadFactory threadFactory) {

View File

@@ -1,6 +1,6 @@
/**
* Scheduling convenience classes for the {@code java.util.concurrent}
* and {@code javax.enterprise.concurrent} packages, allowing to set up a
* and {@code jakarta.enterprise.concurrent} packages, allowing to set up a
* ThreadPoolExecutor or ScheduledThreadPoolExecutor as a bean in a Spring
* context. Provides support for the native {@code java.util.concurrent}
* interfaces as well as the Spring {@code TaskExecutor} mechanism.

View File

@@ -29,7 +29,7 @@ import org.springframework.core.annotation.AliasFor;
* Domain-Driven Design (Evans, 2003) as "a mechanism for encapsulating storage,
* retrieval, and search behavior which emulates a collection of objects".
*
* <p>Teams implementing traditional Java EE patterns such as "Data Access Object"
* <p>Teams implementing traditional Jakarta EE patterns such as "Data Access Object"
* may also apply this stereotype to DAO classes, though care should be taken to
* understand the distinction between Data Access Object and DDD-style repositories
* before doing so. This annotation is a general-purpose stereotype and individual teams

View File

@@ -76,7 +76,7 @@ public class ObjectError extends DefaultMessageSourceResolvable {
/**
* Preserve the source behind this error: possibly an {@link Exception}
* (typically {@link org.springframework.beans.PropertyAccessException})
* or a Bean Validation {@link javax.validation.ConstraintViolation}.
* or a Bean Validation {@link jakarta.validation.ConstraintViolation}.
* <p>Note that any such source object is being stored as transient:
* that is, it won't be part of a serialized error representation.
* @param source the source object
@@ -92,7 +92,7 @@ public class ObjectError extends DefaultMessageSourceResolvable {
/**
* Unwrap the source behind this error: possibly an {@link Exception}
* (typically {@link org.springframework.beans.PropertyAccessException})
* or a Bean Validation {@link javax.validation.ConstraintViolation}.
* or a Bean Validation {@link jakarta.validation.ConstraintViolation}.
* <p>The cause of the outermost exception will be introspected as well,
* e.g. the underlying conversion exception or exception thrown from a setter
* (instead of having to unwrap the {@code PropertyAccessException} in turn).
@@ -117,7 +117,7 @@ public class ObjectError extends DefaultMessageSourceResolvable {
/**
* Check the source behind this error: possibly an {@link Exception}
* (typically {@link org.springframework.beans.PropertyAccessException})
* or a Bean Validation {@link javax.validation.ConstraintViolation}.
* or a Bean Validation {@link jakarta.validation.ConstraintViolation}.
* <p>The cause of the outermost exception will be introspected as well,
* e.g. the underlying conversion exception or exception thrown from a setter
* (instead of having to unwrap the {@code PropertyAccessException} in turn).

View File

@@ -42,7 +42,7 @@ public interface SmartValidator extends Validator {
* @param target the object that is to be validated
* @param errors contextual state about the validation process
* @param validationHints one or more hint objects to be passed to the validation engine
* @see javax.validation.Validator#validate(Object, Class[])
* @see jakarta.validation.Validator#validate(Object, Class[])
*/
void validate(Object target, Errors errors, Object... validationHints);
@@ -56,7 +56,7 @@ public interface SmartValidator extends Validator {
* @param errors contextual state about the validation process
* @param validationHints one or more hint objects to be passed to the validation engine
* @since 5.1
* @see javax.validation.Validator#validateValue(Class, String, Object, Class[])
* @see jakarta.validation.Validator#validateValue(Class, String, Object, Class[])
*/
default void validateValue(
Class<?> targetType, String fieldName, @Nullable Object value, Errors errors, Object... validationHints) {

View File

@@ -23,7 +23,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Variant of JSR-303's {@link javax.validation.Valid}, supporting the
* Variant of JSR-303's {@link jakarta.validation.Valid}, supporting the
* specification of validation groups. Designed for convenient use with
* Spring's JSR-303 support but not JSR-303 specific.
*
@@ -43,7 +43,7 @@ import java.lang.annotation.Target;
*
* @author Juergen Hoeller
* @since 3.1
* @see javax.validation.Validator#validate(Object, Class[])
* @see jakarta.validation.Validator#validate(Object, Class[])
* @see org.springframework.validation.SmartValidator#validate(Object, org.springframework.validation.Errors, Object...)
* @see org.springframework.validation.beanvalidation.SpringValidatorAdapter
* @see org.springframework.validation.beanvalidation.MethodValidationPostProcessor

View File

@@ -34,7 +34,7 @@ public abstract class ValidationAnnotationUtils {
/**
* Determine any validation hints by the given annotation.
* <p>This implementation checks for {@code @javax.validation.Valid},
* <p>This implementation checks for {@code @jakarta.validation.Valid},
* Spring's {@link org.springframework.validation.annotation.Validated},
* and custom annotations whose name starts with "Valid".
* @param ann the annotation (potentially a validation annotation)
@@ -45,7 +45,7 @@ public abstract class ValidationAnnotationUtils {
public static Object[] determineValidationHints(Annotation ann) {
Class<? extends Annotation> annotationType = ann.annotationType();
String annotationName = annotationType.getName();
if ("javax.validation.Valid".equals(annotationName)) {
if ("jakarta.validation.Valid".equals(annotationName)) {
return EMPTY_OBJECT_ARRAY;
}
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);

View File

@@ -19,10 +19,10 @@ package org.springframework.validation.beanvalidation;
import java.util.Iterator;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.BeansException;
@@ -60,7 +60,7 @@ public class BeanValidationPostProcessor implements BeanPostProcessor, Initializ
* Set the JSR-303 ValidatorFactory to delegate to for validating beans,
* using its default Validator.
* <p>Default is the default ValidatorFactory's default Validator.
* @see javax.validation.ValidatorFactory#getValidator()
* @see jakarta.validation.ValidatorFactory#getValidator()
*/
public void setValidatorFactory(ValidatorFactory validatorFactory) {
this.validator = validatorFactory.getValidator();
@@ -105,7 +105,7 @@ public class BeanValidationPostProcessor implements BeanPostProcessor, Initializ
/**
* Perform validation of the given bean.
* @param bean the bean instance to validate
* @see javax.validation.Validator#validate
* @see jakarta.validation.Validator#validate
*/
protected void doValidate(Object bean) {
Assert.state(this.validator != null, "No Validator set");

View File

@@ -16,12 +16,12 @@
package org.springframework.validation.beanvalidation;
import javax.validation.MessageInterpolator;
import javax.validation.TraversableResolver;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorContext;
import javax.validation.ValidatorFactory;
import jakarta.validation.MessageInterpolator;
import jakarta.validation.TraversableResolver;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorContext;
import jakarta.validation.ValidatorFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
@@ -48,7 +48,7 @@ public class CustomValidatorBean extends SpringValidatorAdapter implements Valid
/**
* Set the ValidatorFactory to obtain the target Validator from.
* <p>Default is {@link javax.validation.Validation#buildDefaultValidatorFactory()}.
* <p>Default is {@link jakarta.validation.Validation#buildDefaultValidatorFactory()}.
*/
public void setValidatorFactory(ValidatorFactory validatorFactory) {
this.validatorFactory = validatorFactory;

View File

@@ -27,20 +27,20 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.validation.Configuration;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.MessageInterpolator;
import javax.validation.ParameterNameProvider;
import javax.validation.TraversableResolver;
import javax.validation.Validation;
import javax.validation.ValidationException;
import javax.validation.ValidationProviderResolver;
import javax.validation.Validator;
import javax.validation.ValidatorContext;
import javax.validation.ValidatorFactory;
import javax.validation.bootstrap.GenericBootstrap;
import javax.validation.bootstrap.ProviderSpecificBootstrap;
import jakarta.validation.ClockProvider;
import jakarta.validation.Configuration;
import jakarta.validation.ConstraintValidatorFactory;
import jakarta.validation.MessageInterpolator;
import jakarta.validation.ParameterNameProvider;
import jakarta.validation.TraversableResolver;
import jakarta.validation.Validation;
import jakarta.validation.ValidationException;
import jakarta.validation.ValidationProviderResolver;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorContext;
import jakarta.validation.ValidatorFactory;
import jakarta.validation.bootstrap.GenericBootstrap;
import jakarta.validation.bootstrap.ProviderSpecificBootstrap;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import org.springframework.beans.factory.DisposableBean;
@@ -57,11 +57,11 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
/**
* This is the central class for {@code javax.validation} (JSR-303) setup in a Spring
* application context: It bootstraps a {@code javax.validation.ValidationFactory} and
* This is the central class for {@code jakarta.validation} (JSR-303) setup in a Spring
* application context: It bootstraps a {@code jakarta.validation.ValidationFactory} and
* exposes it through the Spring {@link org.springframework.validation.Validator} interface
* as well as through the JSR-303 {@link javax.validation.Validator} interface and the
* {@link javax.validation.ValidatorFactory} interface itself.
* as well as through the JSR-303 {@link jakarta.validation.Validator} interface and the
* {@link jakarta.validation.ValidatorFactory} interface itself.
*
* <p>When talking to an instance of this bean through the Spring or JSR-303 Validator interfaces,
* you'll be talking to the default Validator of the underlying ValidatorFactory. This is very
@@ -69,22 +69,15 @@ import org.springframework.util.ReflectionUtils;
* you will almost always use the default Validator anyway. This can also be injected directly
* into any target dependency of type {@link org.springframework.validation.Validator}!
*
* <p><b>As of Spring 5.0, this class requires Bean Validation 1.1+, with special support
* for Hibernate Validator 5.x</b> (see {@link #setValidationMessageSource}).
* This class is also runtime-compatible with Bean Validation 2.0 and Hibernate Validator 6.0,
* with one special note: If you'd like to call BV 2.0's {@code getClockProvider()} method,
* obtain the native {@code ValidatorFactory} through {@code #unwrap(ValidatorFactory.class)}
* and call the {@code getClockProvider()} method on the returned native reference there.
*
* <p>This class is also being used by Spring's MVC configuration namespace, in case of the
* {@code javax.validation} API being present but no explicit Validator having been configured.
* {@code jakarta.validation} API being present but no explicit Validator having been configured.
*
* @author Juergen Hoeller
* @since 3.0
* @see javax.validation.ValidatorFactory
* @see javax.validation.Validator
* @see javax.validation.Validation#buildDefaultValidatorFactory()
* @see javax.validation.ValidatorFactory#getValidator()
* @see jakarta.validation.ValidatorFactory
* @see jakarta.validation.Validator
* @see jakarta.validation.Validation#buildDefaultValidatorFactory()
* @see jakarta.validation.ValidatorFactory#getValidator()
*/
public class LocalValidatorFactoryBean extends SpringValidatorAdapter
implements ValidatorFactory, ApplicationContextAware, InitializingBean, DisposableBean {
@@ -123,8 +116,8 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
/**
* Specify the desired provider class, if any.
* <p>If not specified, JSR-303's default search mechanism will be used.
* @see javax.validation.Validation#byProvider(Class)
* @see javax.validation.Validation#byDefaultProvider()
* @see jakarta.validation.Validation#byProvider(Class)
* @see jakarta.validation.Validation#byDefaultProvider()
*/
@SuppressWarnings("rawtypes")
public void setProviderClass(Class providerClass) {
@@ -208,7 +201,7 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
* Specify bean validation properties to be passed to the validation provider.
* <p>Can be populated with a String "value" (parsed via PropertiesEditor)
* or a "props" element in XML bean definitions.
* @see javax.validation.Configuration#addProperty(String, String)
* @see jakarta.validation.Configuration#addProperty(String, String)
*/
public void setValidationProperties(Properties jpaProperties) {
CollectionUtils.mergePropertiesIntoMap(jpaProperties, this.validationPropertyMap);
@@ -217,7 +210,7 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
/**
* Specify bean validation properties to be passed to the validation provider as a Map.
* <p>Can be populated with a "map" or "props" element in XML bean definitions.
* @see javax.validation.Configuration#addProperty(String, String)
* @see jakarta.validation.Configuration#addProperty(String, String)
*/
public void setValidationPropertyMap(@Nullable Map<String, String> validationProperties) {
if (validationProperties != null) {
@@ -400,18 +393,11 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
return this.validatorFactory.getParameterNameProvider();
}
// Bean Validation 2.0: currently not implemented here since it would imply
// a hard dependency on the new javax.validation.ClockProvider interface.
// To be resolved once Spring Framework requires Bean Validation 2.0+.
// Obtain the native ValidatorFactory through unwrap(ValidatorFactory.class)
// instead which will fully support a getClockProvider() call as well.
/*
@Override
public javax.validation.ClockProvider getClockProvider() {
public ClockProvider getClockProvider() {
Assert.notNull(this.validatorFactory, "No target ValidatorFactory set");
return this.validatorFactory.getClockProvider();
}
*/
@Override
@SuppressWarnings("unchecked")

View File

@@ -18,7 +18,7 @@ package org.springframework.validation.beanvalidation;
import java.util.Locale;
import javax.validation.MessageInterpolator;
import jakarta.validation.MessageInterpolator;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.util.Assert;

View File

@@ -19,13 +19,12 @@ package org.springframework.validation.beanvalidation;
import java.lang.reflect.Method;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.executable.ExecutableValidator;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import jakarta.validation.executable.ExecutableValidator;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
@@ -57,7 +56,7 @@ import org.springframework.validation.annotation.Validated;
* @author Juergen Hoeller
* @since 3.1
* @see MethodValidationPostProcessor
* @see javax.validation.executable.ExecutableValidator
* @see jakarta.validation.executable.ExecutableValidator
*/
public class MethodValidationInterceptor implements MethodInterceptor {

View File

@@ -18,9 +18,8 @@ package org.springframework.validation.beanvalidation;
import java.lang.annotation.Annotation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
@@ -55,7 +54,7 @@ import org.springframework.validation.annotation.Validated;
* @author Juergen Hoeller
* @since 3.1
* @see MethodValidationInterceptor
* @see javax.validation.executable.ExecutableValidator
* @see jakarta.validation.executable.ExecutableValidator
*/
@SuppressWarnings("serial")
public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor
@@ -101,7 +100,7 @@ public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvis
* Set the JSR-303 ValidatorFactory to delegate to for validating methods,
* using its default Validator.
* <p>Default is the default ValidatorFactory's default Validator.
* @see javax.validation.ValidatorFactory#getValidator()
* @see jakarta.validation.ValidatorFactory#getValidator()
*/
public void setValidatorFactory(ValidatorFactory validatorFactory) {
this.validator = validatorFactory.getValidator();

View File

@@ -16,8 +16,7 @@
package org.springframework.validation.beanvalidation;
import javax.validation.ValidationException;
import jakarta.validation.ValidationException;
import org.apache.commons.logging.LogFactory;
/**
@@ -26,7 +25,7 @@ import org.apache.commons.logging.LogFactory;
* in case of no Bean Validation provider being available.
*
* <p>This is the actual class used by Spring's MVC configuration namespace,
* in case of the {@code javax.validation} API being present but no explicit
* in case of the {@code jakarta.validation} API being present but no explicit
* Validator having been configured.
*
* @author Juergen Hoeller

View File

@@ -16,8 +16,8 @@
package org.springframework.validation.beanvalidation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorFactory;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.util.Assert;

View File

@@ -25,13 +25,13 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.validation.ConstraintViolation;
import javax.validation.ElementKind;
import javax.validation.Path;
import javax.validation.ValidationException;
import javax.validation.executable.ExecutableValidator;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ElementKind;
import jakarta.validation.Path;
import jakarta.validation.ValidationException;
import jakarta.validation.executable.ExecutableValidator;
import jakarta.validation.metadata.BeanDescriptor;
import jakarta.validation.metadata.ConstraintDescriptor;
import org.springframework.beans.NotReadablePropertyException;
import org.springframework.context.MessageSourceResolvable;
@@ -63,7 +63,7 @@ import org.springframework.validation.SmartValidator;
* @see CustomValidatorBean
* @see LocalValidatorFactoryBean
*/
public class SpringValidatorAdapter implements SmartValidator, javax.validation.Validator {
public class SpringValidatorAdapter implements SmartValidator, jakarta.validation.Validator {
private static final Set<String> internalAnnotationAttributes = new HashSet<>(4);
@@ -74,14 +74,14 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
}
@Nullable
private javax.validation.Validator targetValidator;
private jakarta.validation.Validator targetValidator;
/**
* Create a new SpringValidatorAdapter for the given JSR-303 Validator.
* @param targetValidator the JSR-303 Validator to wrap
*/
public SpringValidatorAdapter(javax.validation.Validator targetValidator) {
public SpringValidatorAdapter(jakarta.validation.Validator targetValidator) {
Assert.notNull(targetValidator, "Target Validator must not be null");
this.targetValidator = targetValidator;
}
@@ -89,7 +89,7 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
SpringValidatorAdapter() {
}
void setTargetValidator(javax.validation.Validator targetValidator) {
void setTargetValidator(jakarta.validation.Validator targetValidator) {
this.targetValidator = targetValidator;
}
@@ -199,7 +199,7 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
* @param violation the current JSR-303 ConstraintViolation
* @return the Spring-reported field (for use with {@link Errors})
* @since 4.2
* @see javax.validation.ConstraintViolation#getPropertyPath()
* @see jakarta.validation.ConstraintViolation#getPropertyPath()
* @see org.springframework.validation.FieldError#getField()
*/
protected String determineField(ConstraintViolation<Object> violation) {
@@ -239,7 +239,7 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
* @param descriptor the JSR-303 ConstraintDescriptor for the current violation
* @return a corresponding error code (for use with {@link Errors})
* @since 4.2
* @see javax.validation.metadata.ConstraintDescriptor#getAnnotation()
* @see jakarta.validation.metadata.ConstraintDescriptor#getAnnotation()
* @see org.springframework.validation.MessageCodesResolver
*/
protected String determineErrorCode(ConstraintDescriptor<?> descriptor) {
@@ -305,7 +305,7 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
* which contains the current field's value
* @return the invalid value to expose as part of the field error
* @since 4.2
* @see javax.validation.ConstraintViolation#getInvalidValue()
* @see jakarta.validation.ConstraintViolation#getInvalidValue()
* @see org.springframework.validation.FieldError#getRejectedValue()
*/
@Nullable
@@ -387,7 +387,7 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
}
catch (ValidationException ex) {
// Ignore if just being asked for plain JSR-303 Validator
if (javax.validation.Validator.class == type) {
if (jakarta.validation.Validator.class == type) {
return (T) this.targetValidator;
}
throw ex;

View File

@@ -13,7 +13,7 @@
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines configuration elements for access to traditional Java EE components
Defines configuration elements for access to traditional Jakarta EE components
such as JNDI resources and EJB session beans.
]]></xsd:documentation>
</xsd:annotation>
@@ -95,62 +95,23 @@
</xsd:complexType>
</xsd:element>
<xsd:element name="local-slsb" type="ejbType">
<xsd:element name="local-slsb" type="jndiLocatingType">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean"><![CDATA[
<xsd:documentation source="java:org.springframework.jndi.JndiObjectFactoryBean"><![CDATA[
Exposes a reference to a local EJB Stateless SessionBean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="remote-slsb">
<xsd:element name="remote-slsb" type="jndiLocatingType">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean"><![CDATA[
<xsd:documentation source="java:org.springframework.jndi.JndiObjectFactoryBean"><![CDATA[
Exposes a reference to a remote EJB Stateless SessionBean.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="ejbType">
<xsd:attribute name="home-interface" type="xsd:string">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[
The home interface that will be narrowed to before performing
the parameterless SLSB create() call that returns the actual
SLSB proxy.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="refresh-home-on-connect-failure" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether to refresh the EJB home on connect failure.
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.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cache-session-bean" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether to cache the actual session bean object.
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.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<!-- base types -->
<xsd:complexType name="jndiLocatingType" abstract="true">
<xsd:complexType name="jndiLocatingType">
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:sequence>
@@ -178,7 +139,7 @@
<xsd:annotation>
<xsd:documentation><![CDATA[
The JNDI name to look up. This may be a fully-qualified JNDI path
or a local Java EE environment naming context path in which case the
or a local Jakarta EE environment naming context path in which case the
prefix "java:comp/env/" will be prepended if applicable.
]]></xsd:documentation>
</xsd:annotation>
@@ -186,7 +147,7 @@
<xsd:attribute name="resource-ref" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether the lookup occurs in a Java EE container, i.e. if the
Controls whether the lookup occurs in a Jakarta EE container, i.e. if the
prefix "java:comp/env/" needs to be added if the JNDI name doesn't
already contain it. Default is "true" (since Spring 2.5).
]]></xsd:documentation>
@@ -222,37 +183,6 @@
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="ejbType">
<xsd:complexContent>
<xsd:extension base="jndiLocatingType">
<xsd:attribute name="lookup-home-on-startup" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether the lookup of the EJB home object is performed
immediately on startup (if true, the default), or on first access
(if false).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cache-home" type="xsd:boolean" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether the EJB home object is cached once it has been located.
On by default; turn this flag off to always reobtain fresh home objects.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="business-interface" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation source="java:java.lang.Class"><![CDATA[
The business interface of the EJB being proxied.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:simpleType name="environmentRefType">
<xsd:annotation>
<xsd:appinfo>

View File

@@ -18,7 +18,7 @@ package example.scannable;
import java.util.concurrent.Future;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

View File

@@ -20,7 +20,7 @@ import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Future;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;

View File

@@ -16,9 +16,8 @@
package org.springframework.beans.factory.annotation;
import javax.inject.Inject;
import javax.inject.Named;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

View File

@@ -21,10 +21,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Qualifier;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.inject.Qualifier;
import org.junit.jupiter.api.Test;
import org.springframework.aop.scope.ScopedProxyUtils;
@@ -40,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Integration tests for handling JSR-303 {@link javax.inject.Qualifier} annotations.
* Integration tests for handling JSR-303 {@link jakarta.inject.Qualifier} annotations.
*
* @author Juergen Hoeller
* @since 3.0

View File

@@ -16,8 +16,7 @@
package org.springframework.context.annotation;
import javax.annotation.PreDestroy;
import jakarta.annotation.PreDestroy;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@@ -18,11 +18,10 @@ package org.springframework.context.annotation;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.EJB;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import jakarta.ejb.EJB;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;

View File

@@ -16,8 +16,7 @@
package org.springframework.context.annotation;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -23,8 +23,7 @@ import java.lang.annotation.Target;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import jakarta.annotation.PostConstruct;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@@ -16,8 +16,7 @@
package org.springframework.context.annotation;
import javax.annotation.Resource;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -26,8 +26,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.Properties;
import javax.inject.Inject;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanDefinitionStoreException;

View File

@@ -20,9 +20,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.jupiter.api.Test;
@@ -49,8 +48,8 @@ import static org.assertj.core.api.Assertions.assertThat;
* <li>{@link InitializingBean} &amp; {@link DisposableBean} interfaces</li>
* <li>Custom {@link RootBeanDefinition#getInitMethodName() init} &amp;
* {@link RootBeanDefinition#getDestroyMethodName() destroy} methods</li>
* <li>JSR 250's {@link javax.annotation.PostConstruct @PostConstruct} &amp;
* {@link javax.annotation.PreDestroy @PreDestroy} annotations</li>
* <li>JSR 250's {@link jakarta.annotation.PostConstruct @PostConstruct} &amp;
* {@link jakarta.annotation.PreDestroy @PreDestroy} annotations</li>
* </ul>
*
* @author Sam Brannen

View File

@@ -22,8 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Optional;
import javax.inject.Provider;
import jakarta.inject.Provider;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;

View File

@@ -22,9 +22,8 @@ import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
import javax.annotation.Resource;
import javax.inject.Provider;
import jakarta.annotation.Resource;
import jakarta.inject.Provider;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanClassLoaderAware;

View File

@@ -16,8 +16,7 @@
package org.springframework.context.annotation.configuration;
import javax.annotation.Resource;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

View File

@@ -16,7 +16,7 @@
package org.springframework.context.annotation6;
import javax.inject.Named;
import jakarta.inject.Named;
@Named
public class Jsr330NamedForScanning {

View File

@@ -30,9 +30,8 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

View File

@@ -1,207 +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.ejb.access;
import javax.ejb.CreateException;
import javax.ejb.EJBLocalHome;
import javax.ejb.EJBLocalObject;
import javax.naming.Context;
import javax.naming.NamingException;
import org.junit.jupiter.api.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.jndi.JndiTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* @author Rod Johnson
* @author Juergen Hoeller
* @author Chris Beams
*/
public class LocalSlsbInvokerInterceptorTests {
/**
* Test that it performs the correct lookup.
*/
@Test
public void testPerformsLookup() throws Exception {
LocalInterfaceWithBusinessMethods ejb = mock(LocalInterfaceWithBusinessMethods.class);
String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
configuredInterceptor(mockContext, jndiName);
verify(mockContext).close();
}
@Test
public void testLookupFailure() throws Exception {
final NamingException nex = new NamingException();
final String jndiName= "foobar";
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) throws NamingException {
assertThat(jndiName.equals(name)).isTrue();
throw nex;
}
};
LocalSlsbInvokerInterceptor si = new LocalSlsbInvokerInterceptor();
si.setJndiName("foobar");
// default resourceRef=false should cause this to fail, as java:/comp/env will not
// automatically be added
si.setJndiTemplate(jt);
assertThatExceptionOfType(NamingException.class)
.isThrownBy(si::afterPropertiesSet)
.isSameAs(nex);
}
@Test
public void testInvokesMethodOnEjbInstance() throws Exception {
Object retVal = new Object();
LocalInterfaceWithBusinessMethods ejb = mock(LocalInterfaceWithBusinessMethods.class);
given(ejb.targetMethod()).willReturn(retVal);
String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
LocalSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
ProxyFactory pf = new ProxyFactory(new Class<?>[] { BusinessMethods.class });
pf.addAdvice(si);
BusinessMethods target = (BusinessMethods) pf.getProxy();
assertThat(target.targetMethod() == retVal).isTrue();
verify(mockContext).close();
verify(ejb).remove();
}
@Test
public void testInvokesMethodOnEjbInstanceWithSeparateBusinessMethods() throws Exception {
Object retVal = new Object();
LocalInterface ejb = mock(LocalInterface.class);
given(ejb.targetMethod()).willReturn(retVal);
String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
LocalSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
ProxyFactory pf = new ProxyFactory(new Class<?>[] { BusinessMethods.class });
pf.addAdvice(si);
BusinessMethods target = (BusinessMethods) pf.getProxy();
assertThat(target.targetMethod() == retVal).isTrue();
verify(mockContext).close();
verify(ejb).remove();
}
private void testException(Exception expected) throws Exception {
LocalInterfaceWithBusinessMethods ejb = mock(LocalInterfaceWithBusinessMethods.class);
given(ejb.targetMethod()).willThrow(expected);
String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
LocalSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
ProxyFactory pf = new ProxyFactory(new Class<?>[] { LocalInterfaceWithBusinessMethods.class });
pf.addAdvice(si);
LocalInterfaceWithBusinessMethods target = (LocalInterfaceWithBusinessMethods) pf.getProxy();
assertThatExceptionOfType(Exception.class)
.isThrownBy(target::targetMethod)
.isSameAs(expected);
verify(mockContext).close();
}
@Test
public void testApplicationException() throws Exception {
testException(new ApplicationException());
}
protected Context mockContext(final String jndiName, final Object ejbInstance)
throws Exception {
SlsbHome mockHome = mock(SlsbHome.class);
given(mockHome.create()).willReturn((LocalInterface)ejbInstance);
Context mockCtx = mock(Context.class);
given(mockCtx.lookup("java:comp/env/" + jndiName)).willReturn(mockHome);
return mockCtx;
}
protected LocalSlsbInvokerInterceptor configuredInterceptor(final Context mockCtx, final String jndiName)
throws Exception {
LocalSlsbInvokerInterceptor si = new LocalSlsbInvokerInterceptor();
si.setJndiTemplate(new JndiTemplate() {
@Override
protected Context createInitialContext() throws NamingException {
return mockCtx;
}
});
si.setJndiName(jndiName);
si.setResourceRef(true);
si.afterPropertiesSet();
return si;
}
/**
* Needed so that we can mock the create() method.
*/
private interface SlsbHome extends EJBLocalHome {
LocalInterface create() throws CreateException;
}
private interface BusinessMethods {
Object targetMethod() throws ApplicationException;
}
private interface LocalInterface extends EJBLocalObject {
Object targetMethod() throws ApplicationException;
}
private interface LocalInterfaceWithBusinessMethods extends LocalInterface, BusinessMethods {
}
@SuppressWarnings("serial")
private class ApplicationException extends Exception {
public ApplicationException() {
super("appException");
}
}
}

View File

@@ -1,197 +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.ejb.access;
import java.lang.reflect.Proxy;
import javax.ejb.CreateException;
import javax.ejb.EJBLocalHome;
import javax.ejb.EJBLocalObject;
import javax.naming.NamingException;
import org.junit.jupiter.api.Test;
import org.springframework.jndi.JndiTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
/**
* @author Rod Johnson
* @author Juergen Hoeller
* @author Chris Beams
* @since 21.05.2003
*/
public class LocalStatelessSessionProxyFactoryBeanTests {
@Test
public void testInvokesMethod() throws Exception {
final int value = 11;
final String jndiName = "foo";
MyEjb myEjb = mock(MyEjb.class);
given(myEjb.getValue()).willReturn(value);
final MyHome home = mock(MyHome.class);
given(home.create()).willReturn(myEjb);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) throws NamingException {
// parameterize
assertThat(name.equals("java:comp/env/" + jndiName)).isTrue();
return home;
}
};
LocalStatelessSessionProxyFactoryBean fb = new LocalStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
fb.setResourceRef(true);
fb.setBusinessInterface(MyBusinessMethods.class);
fb.setJndiTemplate(jt);
// Need lifecycle methods
fb.afterPropertiesSet();
MyBusinessMethods mbm = (MyBusinessMethods) fb.getObject();
assertThat(Proxy.isProxyClass(mbm.getClass())).isTrue();
assertThat(mbm.getValue() == value).isTrue();
verify(myEjb).remove();
}
@Test
public void testInvokesMethodOnEjb3StyleBean() throws Exception {
final int value = 11;
final String jndiName = "foo";
final MyEjb myEjb = mock(MyEjb.class);
given(myEjb.getValue()).willReturn(value);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) throws NamingException {
// parameterize
assertThat(name.equals("java:comp/env/" + jndiName)).isTrue();
return myEjb;
}
};
LocalStatelessSessionProxyFactoryBean fb = new LocalStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
fb.setResourceRef(true);
fb.setBusinessInterface(MyBusinessMethods.class);
fb.setJndiTemplate(jt);
// Need lifecycle methods
fb.afterPropertiesSet();
MyBusinessMethods mbm = (MyBusinessMethods) fb.getObject();
assertThat(Proxy.isProxyClass(mbm.getClass())).isTrue();
assertThat(mbm.getValue() == value).isTrue();
}
@Test
public void testCreateException() throws Exception {
final String jndiName = "foo";
final CreateException cex = new CreateException();
final MyHome home = mock(MyHome.class);
given(home.create()).willThrow(cex);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) throws NamingException {
// parameterize
assertThat(name.equals(jndiName)).isTrue();
return home;
}
};
LocalStatelessSessionProxyFactoryBean fb = new LocalStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
fb.setResourceRef(false); // no java:comp/env prefix
fb.setBusinessInterface(MyBusinessMethods.class);
assertThat(MyBusinessMethods.class).isEqualTo(fb.getBusinessInterface());
fb.setJndiTemplate(jt);
// Need lifecycle methods
fb.afterPropertiesSet();
MyBusinessMethods mbm = (MyBusinessMethods) fb.getObject();
assertThat(Proxy.isProxyClass(mbm.getClass())).isTrue();
assertThatExceptionOfType(EjbAccessException.class).isThrownBy(
mbm::getValue)
.withCause(cex);
}
@Test
public void testNoBusinessInterfaceSpecified() throws Exception {
// Will do JNDI lookup to get home but won't call create
// Could actually try to figure out interface from create?
final String jndiName = "foo";
final MyHome home = mock(MyHome.class);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) throws NamingException {
// parameterize
assertThat(name.equals("java:comp/env/" + jndiName)).isTrue();
return home;
}
};
LocalStatelessSessionProxyFactoryBean fb = new LocalStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
fb.setResourceRef(true);
// Don't set business interface
fb.setJndiTemplate(jt);
// Check it's a singleton
assertThat(fb.isSingleton()).isTrue();
assertThatIllegalArgumentException().isThrownBy(
fb::afterPropertiesSet)
.withMessageContaining("businessInterface");
// Expect no methods on home
verifyNoInteractions(home);
}
public interface MyHome extends EJBLocalHome {
MyBusinessMethods create() throws CreateException;
}
public interface MyBusinessMethods {
int getValue();
}
public interface MyEjb extends EJBLocalObject, MyBusinessMethods {
}
}

View File

@@ -1,349 +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.rmi.ConnectException;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.EJBObject;
import javax.naming.Context;
import javax.naming.NamingException;
import org.junit.jupiter.api.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.jndi.JndiTemplate;
import org.springframework.remoting.RemoteAccessException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* @author Rod Johnson
* @author Juergen Hoeller
* @author Chris Beams
*/
public class SimpleRemoteSlsbInvokerInterceptorTests {
private Context mockContext(
String jndiName, RemoteInterface ejbInstance)
throws Exception {
SlsbHome mockHome = mock(SlsbHome.class);
given(mockHome.create()).willReturn(ejbInstance);
Context mockCtx = mock(Context.class);
given(mockCtx.lookup("java:comp/env/" + jndiName)).willReturn(mockHome);
return mockCtx;
}
private SimpleRemoteSlsbInvokerInterceptor configuredInterceptor(
final Context mockCtx, String jndiName) throws Exception {
SimpleRemoteSlsbInvokerInterceptor si = createInterceptor();
si.setJndiTemplate(new JndiTemplate() {
@Override
protected Context createInitialContext() {
return mockCtx;
}
});
si.setResourceRef(true);
si.setJndiName(jndiName);
return si;
}
protected SimpleRemoteSlsbInvokerInterceptor createInterceptor() {
return new SimpleRemoteSlsbInvokerInterceptor();
}
protected Object configuredProxy(SimpleRemoteSlsbInvokerInterceptor si, Class<?> ifc) throws NamingException {
si.afterPropertiesSet();
ProxyFactory pf = new ProxyFactory(new Class<?>[] {ifc});
pf.addAdvice(si);
return pf.getProxy();
}
@Test
public void testPerformsLookup() throws Exception {
RemoteInterface ejb = mock(RemoteInterface.class);
String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
SimpleRemoteSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
configuredProxy(si, RemoteInterface.class);
verify(mockContext).close();
}
@Test
public void testPerformsLookupWithAccessContext() throws Exception {
RemoteInterface ejb = mock(RemoteInterface.class);
String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
SimpleRemoteSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
si.setExposeAccessContext(true);
RemoteInterface target = (RemoteInterface) configuredProxy(si, RemoteInterface.class);
assertThat(target.targetMethod()).isNull();
verify(mockContext, times(2)).close();
verify(ejb).targetMethod();
}
@Test
public void testLookupFailure() throws Exception {
final NamingException nex = new NamingException();
final String jndiName = "foobar";
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) throws NamingException {
assertThat(jndiName.equals(name)).isTrue();
throw nex;
}
};
SimpleRemoteSlsbInvokerInterceptor si = new SimpleRemoteSlsbInvokerInterceptor();
si.setJndiName("foobar");
// default resourceRef=false should cause this to fail, as java:/comp/env will not
// automatically be added
si.setJndiTemplate(jt);
assertThatExceptionOfType(NamingException.class)
.isThrownBy(si::afterPropertiesSet)
.isSameAs(nex);
}
@Test
public void testInvokesMethodOnEjbInstance() throws Exception {
doTestInvokesMethodOnEjbInstance(true, true);
}
@Test
public void testInvokesMethodOnEjbInstanceWithLazyLookup() throws Exception {
doTestInvokesMethodOnEjbInstance(false, true);
}
@Test
public void testInvokesMethodOnEjbInstanceWithLazyLookupAndNoCache() throws Exception {
doTestInvokesMethodOnEjbInstance(false, false);
}
@Test
public void testInvokesMethodOnEjbInstanceWithNoCache() throws Exception {
doTestInvokesMethodOnEjbInstance(true, false);
}
private void doTestInvokesMethodOnEjbInstance(boolean lookupHomeOnStartup, boolean cacheHome) throws Exception {
Object retVal = new Object();
final RemoteInterface ejb = mock(RemoteInterface.class);
given(ejb.targetMethod()).willReturn(retVal);
int lookupCount = 1;
if (!cacheHome) {
lookupCount++;
if (lookupHomeOnStartup) {
lookupCount++;
}
}
final String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
SimpleRemoteSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
si.setLookupHomeOnStartup(lookupHomeOnStartup);
si.setCacheHome(cacheHome);
RemoteInterface target = (RemoteInterface) configuredProxy(si, RemoteInterface.class);
assertThat(target.targetMethod() == retVal).isTrue();
assertThat(target.targetMethod() == retVal).isTrue();
verify(mockContext, times(lookupCount)).close();
verify(ejb, times(2)).remove();
}
@Test
public void testInvokesMethodOnEjbInstanceWithRemoteException() throws Exception {
final RemoteInterface ejb = mock(RemoteInterface.class);
given(ejb.targetMethod()).willThrow(new RemoteException());
ejb.remove();
final String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
SimpleRemoteSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
RemoteInterface target = (RemoteInterface) configuredProxy(si, RemoteInterface.class);
assertThatExceptionOfType(RemoteException.class).isThrownBy(
target::targetMethod);
verify(mockContext).close();
verify(ejb, times(2)).remove();
}
@Test
public void testInvokesMethodOnEjbInstanceWithConnectExceptionWithRefresh() throws Exception {
doTestInvokesMethodOnEjbInstanceWithConnectExceptionWithRefresh(true, true);
}
@Test
public void testInvokesMethodOnEjbInstanceWithConnectExceptionWithRefreshAndLazyLookup() throws Exception {
doTestInvokesMethodOnEjbInstanceWithConnectExceptionWithRefresh(false, true);
}
@Test
public void testInvokesMethodOnEjbInstanceWithConnectExceptionWithRefreshAndLazyLookupAndNoCache() throws Exception {
doTestInvokesMethodOnEjbInstanceWithConnectExceptionWithRefresh(false, false);
}
@Test
public void testInvokesMethodOnEjbInstanceWithConnectExceptionWithRefreshAndNoCache() throws Exception {
doTestInvokesMethodOnEjbInstanceWithConnectExceptionWithRefresh(true, false);
}
private void doTestInvokesMethodOnEjbInstanceWithConnectExceptionWithRefresh(
boolean lookupHomeOnStartup, boolean cacheHome) throws Exception {
final RemoteInterface ejb = mock(RemoteInterface.class);
given(ejb.targetMethod()).willThrow(new ConnectException(""));
int lookupCount = 2;
if (!cacheHome) {
lookupCount++;
if (lookupHomeOnStartup) {
lookupCount++;
}
}
final String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
SimpleRemoteSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
si.setRefreshHomeOnConnectFailure(true);
si.setLookupHomeOnStartup(lookupHomeOnStartup);
si.setCacheHome(cacheHome);
RemoteInterface target = (RemoteInterface) configuredProxy(si, RemoteInterface.class);
assertThatExceptionOfType(ConnectException.class).isThrownBy(
target::targetMethod);
verify(mockContext, times(lookupCount)).close();
verify(ejb, times(2)).remove();
}
@Test
public void testInvokesMethodOnEjbInstanceWithBusinessInterface() throws Exception {
Object retVal = new Object();
final RemoteInterface ejb = mock(RemoteInterface.class);
given(ejb.targetMethod()).willReturn(retVal);
final String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
SimpleRemoteSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
BusinessInterface target = (BusinessInterface) configuredProxy(si, BusinessInterface.class);
assertThat(target.targetMethod() == retVal).isTrue();
verify(mockContext).close();
verify(ejb).remove();
}
@Test
public void testInvokesMethodOnEjbInstanceWithBusinessInterfaceWithRemoteException() throws Exception {
final RemoteInterface ejb = mock(RemoteInterface.class);
given(ejb.targetMethod()).willThrow(new RemoteException());
final String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
SimpleRemoteSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
BusinessInterface target = (BusinessInterface) configuredProxy(si, BusinessInterface.class);
assertThatExceptionOfType(RemoteAccessException.class).isThrownBy(
target::targetMethod);
verify(mockContext).close();
verify(ejb).remove();
}
@Test
public void testApplicationException() throws Exception {
doTestException(new ApplicationException());
}
@Test
public void testRemoteException() throws Exception {
doTestException(new RemoteException());
}
private void doTestException(Exception expected) throws Exception {
final RemoteInterface ejb = mock(RemoteInterface.class);
given(ejb.targetMethod()).willThrow(expected);
final String jndiName= "foobar";
Context mockContext = mockContext(jndiName, ejb);
SimpleRemoteSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
RemoteInterface target = (RemoteInterface) configuredProxy(si, RemoteInterface.class);
assertThatExceptionOfType(Exception.class)
.isThrownBy(target::targetMethod)
.isSameAs(expected);
verify(mockContext).close();
verify(ejb).remove();
}
/**
* Needed so that we can mock create() method.
*/
protected interface SlsbHome extends EJBHome {
EJBObject create() throws RemoteException, CreateException;
}
protected interface RemoteInterface extends EJBObject {
// Also business exception!?
Object targetMethod() throws RemoteException, ApplicationException;
}
protected interface BusinessInterface {
Object targetMethod() throws ApplicationException;
}
@SuppressWarnings("serial")
protected class ApplicationException extends Exception {
public ApplicationException() {
super("appException");
}
}
}

View File

@@ -1,288 +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.ejb.access;
import java.lang.reflect.Proxy;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.EJBObject;
import javax.naming.NamingException;
import org.junit.jupiter.api.Test;
import org.springframework.jndi.JndiTemplate;
import org.springframework.remoting.RemoteAccessException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
/**
* @author Rod Johnson
* @author Juergen Hoeller
* @since 21.05.2003
*/
public class SimpleRemoteStatelessSessionProxyFactoryBeanTests extends SimpleRemoteSlsbInvokerInterceptorTests {
@Override
protected SimpleRemoteSlsbInvokerInterceptor createInterceptor() {
return new SimpleRemoteStatelessSessionProxyFactoryBean();
}
@Override
protected Object configuredProxy(SimpleRemoteSlsbInvokerInterceptor si, Class<?> ifc) throws NamingException {
SimpleRemoteStatelessSessionProxyFactoryBean fb = (SimpleRemoteStatelessSessionProxyFactoryBean) si;
fb.setBusinessInterface(ifc);
fb.afterPropertiesSet();
return fb.getObject();
}
@Test
public void testInvokesMethod() throws Exception {
final int value = 11;
final String jndiName = "foo";
MyEjb myEjb = mock(MyEjb.class);
given(myEjb.getValue()).willReturn(value);
final MyHome home = mock(MyHome.class);
given(home.create()).willReturn(myEjb);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) {
// parameterize
assertThat(name.equals("java:comp/env/" + jndiName)).isTrue();
return home;
}
};
SimpleRemoteStatelessSessionProxyFactoryBean fb = new SimpleRemoteStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
fb.setResourceRef(true);
fb.setBusinessInterface(MyBusinessMethods.class);
fb.setJndiTemplate(jt);
// Need lifecycle methods
fb.afterPropertiesSet();
MyBusinessMethods mbm = (MyBusinessMethods) fb.getObject();
assertThat(Proxy.isProxyClass(mbm.getClass())).isTrue();
assertThat(mbm.getValue()).as("Returns expected value").isEqualTo(value);
verify(myEjb).remove();
}
@Test
public void testInvokesMethodOnEjb3StyleBean() throws Exception {
final int value = 11;
final String jndiName = "foo";
final MyEjb myEjb = mock(MyEjb.class);
given(myEjb.getValue()).willReturn(value);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) {
// parameterize
assertThat(name.equals("java:comp/env/" + jndiName)).isTrue();
return myEjb;
}
};
SimpleRemoteStatelessSessionProxyFactoryBean fb = new SimpleRemoteStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
fb.setResourceRef(true);
fb.setBusinessInterface(MyBusinessMethods.class);
fb.setJndiTemplate(jt);
// Need lifecycle methods
fb.afterPropertiesSet();
MyBusinessMethods mbm = (MyBusinessMethods) fb.getObject();
assertThat(Proxy.isProxyClass(mbm.getClass())).isTrue();
assertThat(mbm.getValue()).as("Returns expected value").isEqualTo(value);
}
@Override
@Test
public void testRemoteException() throws Exception {
final RemoteException rex = new RemoteException();
final String jndiName = "foo";
MyEjb myEjb = mock(MyEjb.class);
given(myEjb.getValue()).willThrow(rex);
// TODO might want to control this behaviour...
// Do we really want to call remove after a remote exception?
final MyHome home = mock(MyHome.class);
given(home.create()).willReturn(myEjb);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) {
// parameterize
assertThat(name.equals("java:comp/env/" + jndiName)).isTrue();
return home;
}
};
SimpleRemoteStatelessSessionProxyFactoryBean fb = new SimpleRemoteStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
fb.setResourceRef(true);
fb.setBusinessInterface(MyBusinessMethods.class);
fb.setJndiTemplate(jt);
// Need lifecycle methods
fb.afterPropertiesSet();
MyBusinessMethods mbm = (MyBusinessMethods) fb.getObject();
assertThat(Proxy.isProxyClass(mbm.getClass())).isTrue();
assertThatExceptionOfType(RemoteException.class)
.isThrownBy(mbm::getValue)
.isSameAs(rex);
verify(myEjb).remove();
}
@Test
public void testCreateException() throws Exception {
final String jndiName = "foo";
final CreateException cex = new CreateException();
final MyHome home = mock(MyHome.class);
given(home.create()).willThrow(cex);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) {
// parameterize
assertThat(name.equals(jndiName)).isTrue();
return home;
}
};
SimpleRemoteStatelessSessionProxyFactoryBean fb = new SimpleRemoteStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
// rely on default setting of resourceRef=false, no auto addition of java:/comp/env prefix
fb.setBusinessInterface(MyBusinessMethods.class);
assertThat(MyBusinessMethods.class).isEqualTo(fb.getBusinessInterface());
fb.setJndiTemplate(jt);
// Need lifecycle methods
fb.afterPropertiesSet();
MyBusinessMethods mbm = (MyBusinessMethods) fb.getObject();
assertThat(Proxy.isProxyClass(mbm.getClass())).isTrue();
assertThatExceptionOfType(RemoteException.class).isThrownBy(mbm::getValue);
}
@Test
public void testCreateExceptionWithLocalBusinessInterface() throws Exception {
final String jndiName = "foo";
final CreateException cex = new CreateException();
final MyHome home = mock(MyHome.class);
given(home.create()).willThrow(cex);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) {
// parameterize
assertThat(name.equals(jndiName)).isTrue();
return home;
}
};
SimpleRemoteStatelessSessionProxyFactoryBean fb = new SimpleRemoteStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
// rely on default setting of resourceRef=false, no auto addition of java:/comp/env prefix
fb.setBusinessInterface(MyLocalBusinessMethods.class);
assertThat(MyLocalBusinessMethods.class).isEqualTo(fb.getBusinessInterface());
fb.setJndiTemplate(jt);
// Need lifecycle methods
fb.afterPropertiesSet();
MyLocalBusinessMethods mbm = (MyLocalBusinessMethods) fb.getObject();
assertThat(Proxy.isProxyClass(mbm.getClass())).isTrue();
assertThatExceptionOfType(RemoteAccessException.class).isThrownBy(
mbm::getValue)
.withCause(cex);
}
@Test
public void testNoBusinessInterfaceSpecified() throws Exception {
// Will do JNDI lookup to get home but won't call create
// Could actually try to figure out interface from create?
final String jndiName = "foo";
final MyHome home = mock(MyHome.class);
JndiTemplate jt = new JndiTemplate() {
@Override
public Object lookup(String name) throws NamingException {
// parameterize
assertThat(name.equals(jndiName)).isTrue();
return home;
}
};
SimpleRemoteStatelessSessionProxyFactoryBean fb = new SimpleRemoteStatelessSessionProxyFactoryBean();
fb.setJndiName(jndiName);
// rely on default setting of resourceRef=false, no auto addition of java:/comp/env prefix
// Don't set business interface
fb.setJndiTemplate(jt);
// Check it's a singleton
assertThat(fb.isSingleton()).isTrue();
assertThatIllegalArgumentException().isThrownBy(
fb::afterPropertiesSet)
.withMessageContaining("businessInterface");
// Expect no methods on home
verifyNoInteractions(home);
}
protected interface MyHome extends EJBHome {
MyBusinessMethods create() throws CreateException, RemoteException;
}
protected interface MyBusinessMethods {
int getValue() throws RemoteException;
}
protected interface MyLocalBusinessMethods {
int getValue();
}
protected interface MyEjb extends EJBObject, MyBusinessMethods {
}
}

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.
@@ -35,20 +35,21 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class JeeNamespaceHandlerEventTests {
private CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
private final CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
private final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
private XmlBeanDefinitionReader reader;
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
@BeforeEach
public void setUp() throws Exception {
public void setup() throws Exception {
this.reader = new XmlBeanDefinitionReader(this.beanFactory);
this.reader.setEventListener(this.eventListener);
this.reader.loadBeanDefinitions(new ClassPathResource("jeeNamespaceHandlerTests.xml", getClass()));
}
@Test
public void testJndiLookupComponentEventReceived() {
ComponentDefinition component = this.eventListener.getComponentDefinition("simple");

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.
@@ -26,8 +26,6 @@ import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.beans.testfixture.beans.ITestBean;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean;
import org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean;
import org.springframework.jndi.JndiObjectFactoryBean;
import static org.assertj.core.api.Assertions.assertThat;
@@ -93,46 +91,17 @@ public class JeeNamespaceHandlerTests {
@Test
public void testSimpleLocalSlsb() {
BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("simpleLocalEjb");
assertThat(beanDefinition.getBeanClassName()).isEqualTo(LocalStatelessSessionProxyFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "businessInterface", ITestBean.class.getName());
assertThat(beanDefinition.getBeanClassName()).isEqualTo(JndiObjectFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "jndiName", "ejb/MyLocalBean");
}
@Test
public void testSimpleRemoteSlsb() {
BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("simpleRemoteEjb");
assertThat(beanDefinition.getBeanClassName()).isEqualTo(SimpleRemoteStatelessSessionProxyFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "businessInterface", ITestBean.class.getName());
assertThat(beanDefinition.getBeanClassName()).isEqualTo(JndiObjectFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "jndiName", "ejb/MyRemoteBean");
}
@Test
public void testComplexLocalSlsb() {
BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("complexLocalEjb");
assertThat(beanDefinition.getBeanClassName()).isEqualTo(LocalStatelessSessionProxyFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "businessInterface", ITestBean.class.getName());
assertPropertyValue(beanDefinition, "jndiName", "ejb/MyLocalBean");
assertPropertyValue(beanDefinition, "cacheHome", "true");
assertPropertyValue(beanDefinition, "lookupHomeOnStartup", "true");
assertPropertyValue(beanDefinition, "resourceRef", "true");
assertPropertyValue(beanDefinition, "jndiEnvironment", "foo=bar");
}
@Test
public void testComplexRemoteSlsb() {
BeanDefinition beanDefinition = this.beanFactory.getMergedBeanDefinition("complexRemoteEjb");
assertThat(beanDefinition.getBeanClassName()).isEqualTo(SimpleRemoteStatelessSessionProxyFactoryBean.class.getName());
assertPropertyValue(beanDefinition, "businessInterface", ITestBean.class.getName());
assertPropertyValue(beanDefinition, "jndiName", "ejb/MyRemoteBean");
assertPropertyValue(beanDefinition, "cacheHome", "true");
assertPropertyValue(beanDefinition, "lookupHomeOnStartup", "true");
assertPropertyValue(beanDefinition, "resourceRef", "true");
assertPropertyValue(beanDefinition, "jndiEnvironment", "foo=bar");
assertPropertyValue(beanDefinition, "homeInterface", "org.springframework.beans.testfixture.beans.ITestBean");
assertPropertyValue(beanDefinition, "refreshHomeOnConnectFailure", "true");
assertPropertyValue(beanDefinition, "cacheSessionBean", "true");
}
@Test
public void testLazyInitJndiLookup() {
BeanDefinition definition = this.beanFactory.getMergedBeanDefinition("lazyDataSource");

View File

@@ -16,10 +16,9 @@
package org.springframework.validation.beanvalidation;
import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import jakarta.annotation.PostConstruct;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.junit.jupiter.api.Test;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
@@ -99,7 +98,7 @@ public class BeanValidationPostProcessorTests {
bd.getPropertyValues().add("stringValue", "s");
ac.registerBeanDefinition("bean", bd);
assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(() -> ac.refresh())
.isThrownBy(ac::refresh)
.havingRootCause()
.withMessageContainingAll("stringValue", "invalid");
ac.close();

View File

@@ -19,12 +19,11 @@ package org.springframework.validation.beanvalidation;
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 jakarta.validation.ValidationException;
import jakarta.validation.Validator;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.Default;
import org.junit.jupiter.api.Test;
import org.springframework.aop.framework.ProxyFactory;
@@ -49,15 +48,17 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
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<?>) proxyFactory.getProxy());
doTestProxyValidation((MyValidInterface<String>) proxyFactory.getProxy());
}
@Test
@SuppressWarnings("unchecked")
public void testMethodValidationPostProcessor() {
StaticApplicationContext ac = new StaticApplicationContext();
ac.registerSingleton("mvpp", MethodValidationPostProcessor.class);
@@ -70,8 +71,7 @@ public class MethodValidationTests {
ac.close();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void doTestProxyValidation(MyValidInterface proxy) {
private void doTestProxyValidation(MyValidInterface<String> proxy) {
assertThat(proxy.myValidMethod("value", 5)).isNotNull();
assertThatExceptionOfType(ValidationException.class).isThrownBy(() ->
proxy.myValidMethod("value", 15));
@@ -90,8 +90,8 @@ public class MethodValidationTests {
}
@Test
@SuppressWarnings("resource")
public void testLazyValidatorForMethodValidation() {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
LazyMethodValidationConfig.class, CustomValidatorBean.class,
MyValidBean.class, MyValidFactoryBean.class);
@@ -99,8 +99,8 @@ public class MethodValidationTests {
}
@Test
@SuppressWarnings("resource")
public void testLazyValidatorForMethodValidationWithProxyTargetClass() {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
LazyMethodValidationConfigWithProxyTargetClass.class, CustomValidatorBean.class,
MyValidBean.class, MyValidFactoryBean.class);

View File

@@ -26,23 +26,24 @@ 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 jakarta.validation.Constraint;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Payload;
import jakarta.validation.Valid;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -228,6 +229,48 @@ public class SpringValidatorAdapterTests {
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")
@@ -485,4 +528,34 @@ public class SpringValidatorAdapterTests {
}
}
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

@@ -28,16 +28,15 @@ 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 jakarta.validation.Constraint;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Payload;
import jakarta.validation.Valid;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import jakarta.validation.constraints.NotNull;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.HibernateValidatorFactory;
import org.junit.jupiter.api.Test;

View File

@@ -40,39 +40,14 @@
</util:properties>
<!-- Local EJB Tests -->
<jee:local-slsb id="simpleLocalEjb" jndi-name="ejb/MyLocalBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean"/>
<jee:local-slsb id="complexLocalEjb"
jndi-name="ejb/MyLocalBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean"
cache-home="true"
lookup-home-on-startup="true"
resource-ref="true">
<jee:environment>foo=bar</jee:environment>
</jee:local-slsb>
<jee:local-slsb id="simpleLocalEjb" jndi-name="ejb/MyLocalBean"/>
<!-- Remote EJB Tests -->
<jee:remote-slsb id="simpleRemoteEjb" jndi-name="ejb/MyRemoteBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean"/>
<jee:remote-slsb id="complexRemoteEjb"
jndi-name="ejb/MyRemoteBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean"
cache-home="true"
lookup-home-on-startup="true"
resource-ref="true"
home-interface="org.springframework.beans.testfixture.beans.ITestBean"
refresh-home-on-connect-failure="true"
cache-session-bean="true">
<jee:environment>foo=bar</jee:environment>
</jee:remote-slsb>
<jee:remote-slsb id="simpleRemoteEjb" jndi-name="ejb/MyRemoteBean"/>
<!-- Lazy beans Tests-->
<jee:jndi-lookup id="lazyDataSource" jndi-name="jdbc/MyDataSource" lazy-init="true" />
<jee:local-slsb id="lazyLocalBean" jndi-name="ejb/MyLocalBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean" lazy-init="true" />
<jee:remote-slsb id="lazyRemoteBean" jndi-name="ejb/MyRemoteBean"
business-interface="org.springframework.beans.testfixture.beans.ITestBean" lazy-init="true" />
<jee:jndi-lookup id="lazyDataSource" jndi-name="jdbc/MyDataSource" lazy-init="true"/>
<jee:local-slsb id="lazyLocalBean" jndi-name="ejb/MyLocalBean" lazy-init="true"/>
<jee:remote-slsb id="lazyRemoteBean" jndi-name="ejb/MyRemoteBean" lazy-init="true"/>
</beans>

View File

@@ -42,7 +42,7 @@ import org.springframework.util.ReflectionUtils;
* configure JNDI appropriately, so that {@code new InitialContext()}
* will expose the required objects. Also usable for standalone applications,
* e.g. for binding a JDBC DataSource to a well-known JNDI location, to be
* able to use traditional Java EE data access code outside of a Java EE
* able to use traditional Jakarta EE data access code outside of a Jakarta EE
* container.
*
* <p>There are various choices for DataSource implementations: