Spring Boot client to connect to existing JBoss EAP7 ActiveMQ - spring-boot

I've been searching the web but I cannot find an example on how to connect to ActiveMQ on JBoss (up and running) with a Spring-Boot client.
There'se a lot of tutorials from Spring but using an embedded Broker.
Any pointers would be great!
Thanks in advance,
ML
With the info provided, I've got this:
#Configuration
#SpringBootApplication
#EnableJms
public class Application {
#Bean
ActiveMQConnectionFactory activeMQConnectionFactory() {
final String host = "http://127.0.0.1:8080";
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(host);
factory.setUserName("user");
factory.setPassword("pwd");
factory.setTrustAllPackages(true);
return factory;
}
#Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
// This provides all boot's default to this factory, including the
// message converter
configurer.configure(factory, connectionFactory);
// You could still override some of Boot's default if necessary.
return factory;
}
#Bean // Serialize message content to json using TextMessage
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
public static void main(String[] args) {
// Launch the application
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
// Send a message with a POJO - the template reuse the message converter
System.out.println("Sending an email message.");
jmsTemplate.convertAndSend("TestQ", new Email("info#example.com", "Hello"));
}
}
my dependencies in pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-optional</artifactId>
<version>5.7.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
But I've got this exception:
2017-06-01 17:55:54.176 INFO 2053 --- [ main] hello.Application : Started Application in 2.02 seconds (JVM running for 5.215)
Sending an email message.
[WARNING]
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:527)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Could not create Transport. Reason: java.lang.IllegalArgumentException: Invalid connect parameters: {wireFormat.host=127.0.0.1}
at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:316)
at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:487)
at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:570)
at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:658)
at hello.Application.main(Application.java:69)
... 6 more
Caused by: javax.jms.JMSException: Could not create Transport. Reason: java.lang.IllegalArgumentException: Invalid connect parameters: {wireFormat.host=127.0.0.1}
at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:36)
at org.apache.activemq.ActiveMQConnectionFactory.createTransport(ActiveMQConnectionFactory.java:333)
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:346)
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:304)
at org.apache.activemq.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:244)
at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:180)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:474)
... 9 more
Caused by: java.lang.IllegalArgumentException: Invalid connect parameters: {wireFormat.host=127.0.0.1}
at org.apache.activemq.transport.TransportFactory.doConnect(TransportFactory.java:126)
at org.apache.activemq.transport.TransportFactory.connect(TransportFactory.java:65)
at org.apache.activemq.ActiveMQConnectionFactory.createTransport(ActiveMQConnectionFactory.java:331)
... 14 more
I don't know what is this:
Caused by: java.lang.IllegalArgumentException: Invalid connect
parameters: {wireFormat.host=127.0.0.1}
thanks

For configuration, but change the broker url to your external ActiveMQ server: see http://activemq.apache.org/uri-protocols.html for different protocols (e.g. tcp). You may also need to include a user and password.
I started with this tutorial https://spring.io/guides/gs/messaging-jms/ and made my own edits to get it to work the way I wanted with ActiveMQ, you can also look here for other options: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-messaging.html. There are a few different ways to do this in Spring.
Also included the factory bean as well. From here, I use #JmsListener annotation to listen for messages and jmstemplate to post messages.
import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
#Configuration
#EnableJms
public class JMSConfiguration {
private static final Logger logger = LoggerFactory.getLogger(JMSConfiguration.class);
#Bean ActiveMQConnectionFactory activeMQConnectionFactory() {
ActiveMQConnectionFactory factory =
new ActiveMQConnectionFactory("tcp://somehost:61616");
factory.setTrustAllPackages(true);
return factory;
}
#Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
// This provides all boot's default to this factory, including the
// message converter
configurer.configure(factory, connectionFactory);
// You could still override some of Boot's default if necessary.
return factory;
}
}
Dependencies: spring-boot-starter-activemq
Spring version: 1.4.3.RELEASE

Related

Spring server doesn't start with actuator dependency

If I add spring boot actuator dependency my server doesn't start. I get the following error:
SEVERE [main] org.apache.catalina.startup.HostConfig.deployDescriptor Error deploying deployment descriptor [tomcat path\conf\Catalina\localhost\test.xml]
java.lang.IllegalStateException: Error starting child
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:720)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:692)
...
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/agromarket]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:717)
... 37 more
Caused by: java.lang.ClassCastException: org.apache.logging.slf4j.SLF4JLoggerContext cannot be cast to org.apache.logging.log4j.core.LoggerContext
at rs.navigator.alexandar.sync.WebAppInitializer.onStartup(WebAppInitializer.java:34)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5161)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
Dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Any ideas why? From my knowledge even if the versions aren't compatible the server should still be able to start.
Edit:
My WebAppInitializer:
public class WebAppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
System.out.println(("------------------ Sync context initialized and application started ------------------"));
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
// ctx.register(ServletContextListener.class);
// ctx.register(SecurityConfiguration.class);
// ctx.register(SpringFoxConfig.class);
// ctx.register(WebMvcConfigure.class);
// ctx.register(JPAConfiguration.class);
// ctx.setServletContext(servletContext);
// Reconfigure log4j
// ServletContext sctx = ctx.getServletContext();
System.setProperty("logFilename", servletContext.getContextPath().substring(1));
org.apache.logging.log4j.core.LoggerContext sctxLog =
(org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
sctxLog.reconfigure();
//Dispatcher servlet
ServletRegistration.Dynamic servlet = servletContext.addServlet("mvc-dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
ctx.close();
}
}
Error stack after adding #EnableAutoConfiguration
If you want benefit from the automatic features of Spring Boot, your #Configuration class must be annotated with #EnableAutoConfiguration.
Since the auto-configuration already creates a DispatcherServlet bound to /, you can safely change your WebAppInitializer class to:
#SpringBootApplication
public class WebAppInitializer extends SpringBootServletInitializer {
}

Spring - Websockets - JSR-356

I implemented websockets into my application. I copied the configuration and dependencies from jHipster generated app, but I am getting the following errors:
java.lang.IllegalArgumentException: No 'javax.websocket.server.ServerContainer' ServletContext attribute. Are you running in a Servlet container that supports JSR-356?
and
org.apache.catalina.connector.ClientAbortException: java.io.IOException: An established connection was aborted by the software in your host machine
I believe these errors are the reason for the socket connection not being consistent and the therefore the client is not able to send and/or receive any messages.
I searched for a solution but other post didn't help (ie. adding glassfish dependencies).
These are my ws dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-messaging</artifactId>
</dependency>
Do I need to include some other dependencies or is the problem elsewhere?
I found a solution here.
I added these 2 beans:
#Bean
public TomcatServletWebServerFactory tomcatContainerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();;
factory.setTomcatContextCustomizers(Collections.singletonList(tomcatContextCustomizer()));
return factory;
}
#Bean
public TomcatContextCustomizer tomcatContextCustomizer() {
return new TomcatContextCustomizer() {
#Override
public void customize(Context context) {
context.addServletContainerInitializer(new WsSci(), null);
}
};
}

Spring Boot JMS No JmsTemplate bean available

I'm trying to send a message with JMS from my application.
I add in my pom
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
<version>1.1</version>
</dependency>
The spring getting started say
JmsTemplate and ConnectionFactory are created automatically by Spring Boot. In this case, the ActiveMQ broker runs embedded.
and in my batch writer
#Autowired
JmsTemplate jmsTemplate,
void writer(List<String> items) {
jmsTemplate.convertAndSend(items);
}
But the bean JmsTemplate is not found
No qualifying bean of type 'org.springframework.jms.core.JmsTemplate' available: expected at least 1 bean which qualifies as autowire candidate
I tried to add an message converter in the #configuration
#Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
I tried to add the #EnableJMS (even if it's just for listener...)
But it dosen't work...
I don't understand why, on tutorials it looks like easy...
To work we need to create a jmsTemplate bean
#Bean
public ConnectionFactory getConnectionFactory() {
TibjmsConnectionFactory connectionFactory = new TibjmsConnectionFactory(urlBrocker);
return connectionFactory;
}
#Bean
public JmsTemplate jmsTemplate() {
JmsTemplate template = new JmsTemplate();
template.setConnectionFactory(getConnectionFactory());
template.setPubSubDomain(false); // false for a Queue, true for a Topic
return template;
}

Spring Boot Runs on Tomcat 8.5.x but not 8.0.37 java.lang.NoClassDefFoundError: org/apache/coyote/UpgradeProtocol

relatively new to Spring so I am guessing I am not doing something correctly. I have been converting an older java soap service to spring. I am able to run it locally on tomcat 8.5 and up, but when I run it on tomcat 8.0.37 (which is what the server I will deploy it to is on) I get the error below. I came across this error in another project, but realized in the other project I was unnecessarily creating a servlet, so once I ripped out the servlet code I was good to go. In this instance I need to create a servlet. The error is looking for "org/apache/coyote/UpgradeProtocol" which is not in Tomcat 8.0.37. Not sure what in my code is trying to use it. Any suggestions are appreciated, thanks.
Tomcat dependencies in pom...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.7.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
error...
2019-01-17 16:05:12,539 SEVERE Class= org.apache.catalina.core.ContainerBase Method= addChildInternal Message= ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/exampleServices]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:162)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:940)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1816)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'containerFactory' defined in class path resource [com/removed/exampleServices/exampleServicesConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory]: Factory method 'containerFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/coyote/UpgradeProtocol
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:591)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1246)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1096)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:548)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:157)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:137)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5303)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
config class below, I assume the issue is with how I am creating my TomcatServletWebServerFactory or my ServletRegistrationBean
#ComponentScan({"com.example.exampleservices", "com.example.examplesoapservices"})
#Configuration
#EnableAWSF
public class exampleservicesConfiguration {
static {
// Statically initialize SystemImpl so it doesn't slow down first
// request
try {
SystemImpl.getInstance();
} catch (exampleException e) {
throw new RuntimeException(e);
}
}
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new WSSpringServlet(), "/exampleservicesSOAP/*", "/exampleservicesSOAPV3/*");
//ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new WSSpringServlet(), "/exampleservicesPort/*", "/exampleservicesPortV3/*");
servletRegistrationBean.setEnabled(true);
servletRegistrationBean.setLoadOnStartup(0);
return servletRegistrationBean;
}
#Bean
#SneakyThrows
public SpringBinding springBinding(exampleservicesSOAPImpl exampleservicesSOAPImpl, AWSFHandlers awsfHandlers) throws Exception {
SpringBinding springBinding = new SpringBinding();
springBinding.setUrl("/exampleservicesSOAP");
SpringService springService = new SpringService();
springService.setBean(exampleservicesSOAPImpl);
springService.setHandlers(awsfHandlers.getAwsfHandlers());
springBinding.setService(springService.getObject());
return springBinding;
}
#Bean
#SneakyThrows
public SpringBinding springBindingV3(exampleservicesSOAPV3Impl exampleservicesSOAPV3Impl, AWSFHandlers awsfHandlers) throws Exception {
SpringBinding springBinding = new SpringBinding();
springBinding.setUrl("/exampleservicesSOAPV3");
SpringService springService = new SpringService();
springService.setBean(exampleservicesSOAPV3Impl);
springService.setHandlers(awsfHandlers.getAwsfHandlers());
springBinding.setService(springService.getObject());
return springBinding;
}
#Bean
public Executor threadPoolTaskExecutor(){
return new ThreadPoolTaskExecutor();
}
#Bean
public TomcatServletWebServerFactory containerFactory() {
return new TomcatServletWebServerFactory () {
protected void customizeConnector(Connector connector) {
super.customizeConnector(connector);
}
};
}
#Bean
public Jaxb2Marshaller jaxb2Marshaller() {
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setContextPath(exJAXBContext.JAXB_CONTEXT_PATH);
return jaxb2Marshaller;
}
#Bean
private static JAXBContext initContext() {
try {
return JAXBContext.newInstance(BasicServiceComponents.eesvcof.getClass().getPackage().getName() + ":" + BasicServiceComponents.eesvcofV3.getClass().getPackage().getName());
} catch (JAXBException e) {
e.printStackTrace();
return null;
}
}
private static final JAXBContext context = initContext();
#Bean
public Marshaller marshaller() {
Marshaller marshaller = null;
try {
marshaller = this.context.createMarshaller();
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//any setters
return marshaller;
}
#Bean
public Unmarshaller unmarshaller() {
Unmarshaller unmarshaller = null;
try {
unmarshaller = this.context.createUnmarshaller();
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//any setters
return unmarshaller;
}
}
Well , most probably it is because Spring Boot 2.0 series requires Tomcat 8.5 which is mentioned in the release note. That UpgradeProtocol is something related to HTTP2 which does not exist in Tomcat 8.0 , so your best bet is try to disable HTTP2 in the application.properties :
server.http2.enabled=false
So the code that was breaking is
#Bean
public TomcatServletWebServerFactory containerFactory() {
return new TomcatServletWebServerFactory () {
protected void customizeConnector(Connector connector) {
super.customizeConnector(connector);
}
};
}
When I was testing before I was commenting this out and when I would run locally I would get a different error. Someone I work with suggested removing this bean (I guess it is not needed with spring 2) and also removing my pom code that specifies the tomcat version. This worked. So locally spring is managing my Tomcat version. I believe spring sets Tomcat to 8.5.35 for the spring 2.0.7 release. When I deploy my code it now runs fine on Tomcat 8.0.35. So you do not need that bean, and when running locally just let spring set your own Tomcat version. I am not sure why that bean works on Tomcat 8.5.35 but I don't need it anyways.

Spring Boot Embedded Tomcat - No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 3

I am working on my spring boot application and running with embedded tomcat 8.x. I am trying to configure three different oracle data sources using JNDI and followed this link. Below are my different files:
application-dev.properties
spring.oracle.datasource.oracleDS1.jndi-name=jdbc/oracleDS1
spring.oracle.datasource.oracleDS2.jndi-name=jdbc/oracleDS2
spring.oracle.datasource.oracleDS3.jndi-name=jdbc/oracleDS3
OracleDataSourceConfiguration
package com.adp.orbis.requesttracker.orbisrequesttracker;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
#Configuration
public class OracleDataSourceConfiguration {
#Value("${spring.oracle.datasource.oracleDS1.jndi-name}")
private String oracleDS1;
#Value("${spring.oracle.datasource.oracleDS2.jndi-name}")
private String oracleDS2;
#Value("${spring.oracle.datasource.oracleDS3.jndi-name}")
private String oracleDS3;
#Bean(name="dataSource1", destroyMethod = "")
#Profile("dev")
#Primary
public DataSource evolutionDataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
return dataSourceLookup.getDataSource(oracleDS1);
}
#Bean(name="dataSource2", destroyMethod = "")
#Profile("dev")
#Primary
public DataSource orbisQueryOnlyDataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
return dataSourceLookup.getDataSource(oracleDS2);
}
#Bean(name="dataSource3", destroyMethod = "")
#Profile("dev")
public DataSource orbisExportDataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
return dataSourceLookup.getDataSource(oracleDS3);
}
}
TomcatEmbeddedServletContainerFactory
#Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {
#Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatEmbeddedServletContainer(tomcat);
}
#Override
protected void postProcessContext(Context context) {
ContextResource oracleDS1JNDIResource = new ContextResource();
oracleDS1JNDIResource.setName("jdbc/oracleDS1");
oracleDS1JNDIResource.setType(DataSource.class.getName());
oracleDS1JNDIResource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
oracleDS1JNDIResource.setProperty("url", "jdbc:oracle:thin:#localhost:1521/mydbservice1");
oracleDS1JNDIResource.setProperty("username", "db-user-name");
oracleDS1JNDIResource.setProperty("password", "db-user-pass");
oracleDS1JNDIResource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
context.getNamingResources().addResource(oracleDS1JNDIResource);
ContextResource oracleDS2JNDIResource = new ContextResource();
oracleDS2JNDIResource.setName("jdbc/oracleDS2");
oracleDS2JNDIResource.setType(DataSource.class.getName());
oracleDS2JNDIResource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
oracleDS2JNDIResource.setProperty("url", "jdbc:oracle:thin:#localhost:1521/mydbservice2");
oracleDS2JNDIResource.setProperty("username", "db-user-name");
oracleDS2JNDIResource.setProperty("password", "db-user-pass");
oracleDS2JNDIResource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
context.getNamingResources().addResource(oracleDS2JNDIResource);
ContextResource oracleDS3JNDIResource = new ContextResource();
oracleDS3JNDIResource.setName("jdbc/oracleDS3");
oracleDS3JNDIResource.setType(DataSource.class.getName());
oracleDS3JNDIResource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
oracleDS3JNDIResource.setProperty("url", "jdbc:oracle:thin:#localhost:1521/mydbservice3");
oracleDS3JNDIResource.setProperty("username", "db-user-name");
oracleDS3JNDIResource.setProperty("password", "db-user-pass");
oracleDS3JNDIResource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
context.getNamingResources().addResource(oracleDS3JNDIResource);
}
};
}
But when I run this spring boot application, it throws below exception. Could you please help me what I am missing here? I tried adding #Primary with all DataSource bean. But no luck.
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 3: dataSource1,dataSource2,dataSource3
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 3: dataSource1,dataSource2,dataSource3
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1041) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:345) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1092) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.init(DataSourceInitializer.java:77) ~[spring-boot-autoconfigure-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_112]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_112]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_112]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_112]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
... 38 common frames omitted
There should be atleast 1 bean with name dataSource. So either replace any one of the existing bean with name for exp dataSource1 to dataSource, or create a new one.
Trying to say, change
#Bean(name="dataSource1", destroyMethod = "")
#Profile("dev")
#Primary
public DataSource evolutionDataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
return dataSourceLookup.getDataSource(oracleDS1);
}
To
#Bean(name="dataSource", destroyMethod = "")
#Profile("dev")
#Primary
public DataSource evolutionDataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
return dataSourceLookup.getDataSource(oracleDS1);
}
OR Simply remove #Primary from any of the existing dataSource* beans. At most 1 bean can have #Primary under same #Profile
I am able to resolve this issue. The problem was, I had defined all data sources in my spring boot application and it was also importing dependent spring context file. That means, I had same data sources configured into my imported spring context file too. I removed all data source beans from OracleDataSourceConfiguration(as mentioned in my question on top) and used TomcatEmbeddedServletContainerFactory to initialize JNDI data sources (referred this) with the same name which are mentioned in my imported spring context file. It worked for me.
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myDataSource" />

Resources