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:
@@ -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"));
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.springframework.util.Assert;
|
||||
* Standalone application context, accepting <em>component classes</em> as input —
|
||||
* 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...)}.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
* <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/></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">
|
||||
* <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.springframework.lang.Nullable;
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="queueConnectionFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
* <property name="proxyInterfaces" value="javax.jms.QueueConnectionFactory"/>
|
||||
* <property name="proxyInterfaces" value="jakarta.jms.QueueConnectionFactory"/>
|
||||
* <property name="targetSource" ref="queueConnectionFactoryTarget"/>
|
||||
* </bean></pre>
|
||||
*
|
||||
|
||||
@@ -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}.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user