diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java index bbdd58d3cd6..4175af2e798 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsProperties.java @@ -29,6 +29,8 @@ public class JmsProperties { private boolean pubSubDomain = false; + private String jndiName; + public boolean isPubSubDomain() { return this.pubSubDomain; } @@ -37,4 +39,12 @@ public class JmsProperties { this.pubSubDomain = pubSubDomain; } + public String getJndiName() { + return this.jndiName; + } + + public void setJndiName(String jndiName) { + this.jndiName = jndiName; + } + } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JndiConnectionFactoryAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JndiConnectionFactoryAutoConfiguration.java index 7244eb09efb..5b519861b07 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JndiConnectionFactoryAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JndiConnectionFactoryAutoConfiguration.java @@ -21,14 +21,19 @@ import java.util.Arrays; import javax.jms.ConnectionFactory; import javax.naming.NamingException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionalOnJndi; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration.JndiOrPropertyCondition; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.AnnotationUtils; import org.springframework.jndi.JndiLocatorDelegate; +import org.springframework.util.StringUtils; /** * {@link EnableAutoConfiguration Auto-configuration} for JMS provided from JNDI. @@ -39,12 +44,26 @@ import org.springframework.jndi.JndiLocatorDelegate; @Configuration @AutoConfigureBefore(JmsAutoConfiguration.class) @ConditionalOnMissingBean(ConnectionFactory.class) -@ConditionalOnJndi({ "java:/JmsXA", "java:/XAConnectionFactory" }) +@Conditional(JndiOrPropertyCondition.class) public class JndiConnectionFactoryAutoConfiguration { + // Keep these in sync with the condition below + private static String[] JNDI_LOCATIONS = { "java:/JmsXA", "java:/XAConnectionFactory" }; + + @Autowired + private JmsProperties properties; + @Bean public ConnectionFactory connectionFactory() throws NamingException { - for (String name : getJndiLocations()) { + if (StringUtils.hasLength(this.properties.getJndiName())) { + return new JndiLocatorDelegate().lookup(this.properties.getJndiName(), + ConnectionFactory.class); + } + return findJndiConnectionFactory(); + } + + private ConnectionFactory findJndiConnectionFactory() { + for (String name : JNDI_LOCATIONS) { try { return new JndiLocatorDelegate().lookup(name, ConnectionFactory.class); } @@ -54,11 +73,26 @@ public class JndiConnectionFactoryAutoConfiguration { } throw new IllegalStateException( "Unable to find ConnectionFactory in JNDI locations " - + Arrays.asList(getJndiLocations())); + + Arrays.asList(JNDI_LOCATIONS)); } - private String[] getJndiLocations() { - return AnnotationUtils.getAnnotation(getClass(), ConditionalOnJndi.class).value(); + /** + * Condition for JNDI name or a specific property + */ + static class JndiOrPropertyCondition extends AnyNestedCondition { + + public JndiOrPropertyCondition() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @ConditionalOnJndi({ "java:/JmsXA", "java:/XAConnectionFactory" }) + static class Jndi { + } + + @ConditionalOnProperty(prefix = "spring.jms", name = "jndi-name") + static class Property { + } + } } diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index bad7bee55ae..8ccf60ec4f6 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -282,6 +282,7 @@ content into your application; rather pick only the properties that you need. spring.hornetq.embedded.cluster-password= # customer password (randomly generated by default) # JMS ({sc-spring-boot-autoconfigure}/jms/JmsProperties.{sc-ext}[JmsProperties]) + spring.datasource.jndi-name= # JNDI location of a JMS ConnectionFactory spring.jms.pub-sub-domain= # false for queue (default), true for topic # SPRING BATCH ({sc-spring-boot-autoconfigure}/batch/BatchDatabaseInitializer.{sc-ext}[BatchDatabaseInitializer]) diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 677c701db3e..81237d7dfb5 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -1855,6 +1855,20 @@ resolved against their provided names. +[[boot-features-jms-jndi]] +==== Using a JNDI ConnectionFactory +If you are running your application in an Application Server Spring Boot will attempt to +locate a JMS `ConnectionFactory` using JNDI. By default the locations `java:/JmsXA` and +`java:/XAConnectionFactory` will checked. You can use the +`spring.jms.jndi-name` property if you need to specify an alternative location: + +[source,properties,indent=0] +---- + spring.jms.jndi-name=java:/MyConnectionFactory +---- + + + [[boot-features-using-jms-template]] [[boot-features-using-jms-sending]] ==== Sending a message