diff --git a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java index d9acb722b08..8a3ca5a9f88 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java @@ -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. @@ -146,22 +146,27 @@ import org.springframework.util.StringValueResolver; public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable { + // Defensive reference to JNDI API for JDK 9+ (optional java.naming module) + private static final boolean jndiPresent = ClassUtils.isPresent( + "javax.naming.InitialContext", CommonAnnotationBeanPostProcessor.class.getClassLoader()); + + private static final Set> resourceAnnotationTypes = new LinkedHashSet<>(4); + @Nullable private static final Class webServiceRefClass; @Nullable private static final Class ejbClass; - private static final Set> resourceAnnotationTypes = new LinkedHashSet<>(4); - static { - webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef"); - ejbClass = loadAnnotationType("javax.ejb.EJB"); - resourceAnnotationTypes.add(Resource.class); + + webServiceRefClass = loadAnnotationType("javax.xml.ws.WebServiceRef"); if (webServiceRefClass != null) { resourceAnnotationTypes.add(webServiceRefClass); } + + ejbClass = loadAnnotationType("javax.ejb.EJB"); if (ejbClass != null) { resourceAnnotationTypes.add(ejbClass); } @@ -174,7 +179,8 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean private boolean alwaysUseJndiLookup = false; - private transient BeanFactory jndiFactory = new SimpleJndiBeanFactory(); + @Nullable + private transient BeanFactory jndiFactory; @Nullable private transient BeanFactory resourceFactory; @@ -199,6 +205,11 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean setInitAnnotationType(PostConstruct.class); setDestroyAnnotationType(PreDestroy.class); ignoreResourceType("javax.xml.ws.WebServiceContext"); + + // java.naming module present on JDK 9+? + if (jndiPresent) { + this.jndiFactory = new SimpleJndiBeanFactory(); + } } @@ -464,6 +475,7 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean public void releaseTarget(Object target) { } }; + ProxyFactory pf = new ProxyFactory(); pf.setTargetSource(ts); if (element.lookupType.isInterface()) { @@ -484,12 +496,23 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean protected Object getResource(LookupElement element, @Nullable String requestingBeanName) throws NoSuchBeanDefinitionException { + // JNDI lookup to perform? + String jndiName = null; if (StringUtils.hasLength(element.mappedName)) { - return this.jndiFactory.getBean(element.mappedName, element.lookupType); + jndiName = element.mappedName; + } + else if (this.alwaysUseJndiLookup) { + jndiName = element.name; } - if (this.alwaysUseJndiLookup) { - return this.jndiFactory.getBean(element.name, element.lookupType); + if (jndiName != null) { + if (this.jndiFactory == null) { + throw new NoSuchBeanDefinitionException(element.lookupType, + "No JNDI factory configured - specify the 'jndiFactory' property"); + } + return this.jndiFactory.getBean(jndiName, element.lookupType); } + + // Regular resource autowiring if (this.resourceFactory == null) { throw new NoSuchBeanDefinitionException(element.lookupType, "No resource factory configured - specify the 'resourceFactory' property"); diff --git a/spring-web/src/main/java/org/springframework/web/context/support/StandardServletEnvironment.java b/spring-web/src/main/java/org/springframework/web/context/support/StandardServletEnvironment.java index 3ec9b92be64..4d49afb974a 100644 --- a/spring-web/src/main/java/org/springframework/web/context/support/StandardServletEnvironment.java +++ b/spring-web/src/main/java/org/springframework/web/context/support/StandardServletEnvironment.java @@ -27,6 +27,7 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.jndi.JndiLocatorDelegate; import org.springframework.jndi.JndiPropertySource; import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; import org.springframework.web.context.ConfigurableWebEnvironment; /** @@ -39,6 +40,7 @@ import org.springframework.web.context.ConfigurableWebEnvironment; * documentation for details. * * @author Chris Beams + * @author Juergen Hoeller * @since 3.1 * @see StandardEnvironment */ @@ -54,6 +56,11 @@ public class StandardServletEnvironment extends StandardEnvironment implements C public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiProperties"; + // Defensive reference to JNDI API for JDK 9+ (optional java.naming module) + private static final boolean jndiPresent = ClassUtils.isPresent( + "javax.naming.InitialContext", StandardServletEnvironment.class.getClassLoader()); + + /** * Create a new {@code StandardServletEnvironment} instance. */ @@ -100,7 +107,7 @@ public class StandardServletEnvironment extends StandardEnvironment implements C protected void customizePropertySources(MutablePropertySources propertySources) { propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME)); propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)); - if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) { + if (jndiPresent && JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) { propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME)); } super.customizePropertySources(propertySources);