Allow custom JNDI ConnectionFactory lookup

Add a `spring.jms.jndi-name` property to allow a JMS ConnectionFactory
to be obtained from a custom JNDI location.

Fixes gh-1471
This commit is contained in:
Phillip Webb 2014-09-03 18:35:45 -07:00
parent 6ee18fbabd
commit f7cffce695
4 changed files with 65 additions and 6 deletions

View File

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

View File

@ -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 {
}
}
}

View File

@ -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])

View File

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