I recently changed some of my application to use the the following:
org.springframework.jndi.JndiTemplate
org.springframework.jms.connection.CachingConnectionFactory
org.springframework.jms.core.JmsTemplate
Everything is working fine and I'm able to deploy my war files and send JMS messages to the queue.
However something peculiar happens when my managed server restarts. The deployables will all go into a fail state which requires me to then manually start them up.
This started happening after the change to use caching connection factory, jndi template and jms template.
My SpringConfig file:
<!-- Service Controller begin -->
<bean id="appUtils" class="com.foo.util.AppUtil" lazy-init="true" />
<bean id="jms_jndiTemplate" class="org.springframework.jndi.JndiTemplate" lazy-init="true">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">#{jmsJndiFactory}</prop>
<prop key="java.naming.provider.url">#{jmsIp}</prop>
</props>
</property>
</bean>
<bean id="jmsUtils" class="com.foo.JmsUtil" >
<property name="template">
<bean class="org.springframework.jms.core.JmsTemplate" lazy-init="true">
<property name="connectionFactory">
<bean class="org.springframework.jms.connection.CachingConnectionFactory" lazy-init="true">
<property name="sessionCacheSize" value="10" />
<property name="targetConnectionFactory">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jms_jndiTemplate" />
<property name="jndiName" ref="jmsFactory" />
</bean>
</property>
</bean>
</property>
</bean>
</property>
<property name="destination">
<bean class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiTemplate" ref="jms_jndiTemplate" />
<property name="jndiName" ref="jmsQueue" />
</bean>
</property>
</bean>
ApplicationContext file:
<bean id="jmsQueue" class="java.lang.String" ><constructor-arg value="${jmsQueue.local}" /></bean>
<bean id="jmsFactory" class="java.lang.String" ><constructor-arg value="${jmsFactory.local}" /></bean>
<bean id="jmsJndiFactory" class="java.lang.String" ><constructor-arg value="${jmsJndiFactory.local}" /></bean>
<bean id="jmsIp" class="java.lang.String" ><constructor-arg value="${jmsIp.local}" /></bean>
applicationProperties file:
jmsQueue.local=jms/Queue
jmsFactory.local=jms/ConnectionFactory
jmsJndiFactory.local=weblogic.jndi.WLInitialContextFactory
jmsIp.local=t3://localhost:7031
Anyone has any idea as to why this might be happening? I'm using Weblogic. Any help would be greatly appreciated.
Thanks!
Edit: Forgot to mention that the error causing the failed state is
javax.naming.NameNotFoundException: Unable to resolve 'jms.Queue'. Resolved 'jms'; remaining name 'Queue'.
This is a JNDI error. The message means "I tried to find jms/Queue in the JNDI context but I only got as far as jms; there is no Queue child below".
Check the resources which you configured for the application in WebSphere.
Related
I am using a data source defined in tomcat in my spring configuration as shown in the below xml.
It can happen sometimes that this data source may not be defined in the context.xml of tomcat.
In such cases , the context initialization fails since myDS is not found.
Is it possible to configure the datasource as optional so that application initialisation is not impacted ?
There can be a run time error when this data source is accessed , which is acceptable
<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myDS"/>
</bean>
<bean id="myEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="packagesToScan" value="com..XX.XX" />
<property name="persistenceUnitName" value="myPU" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="#{systemProperties['showSql'] == null ? 'true' : systemProperties['showSql'] }" />
</bean>
</property>
<property name="persistenceUnitPostProcessors">
<list>
<ref bean="wrkflw-punitpostprocessor" />
</list>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">#{systemProperties['dbDialect']}</prop>
</props>
</property>
</bean>
Thanks
Muhad
You may check the DelegatingDataSource, you could encapsulate the logic to load the datasource from JNDI within its instantiation. For your application there will be always a DataSource there, but in some cases (whenever its not able to load the DataSource from JNDI) there is no delegation.
Searching in the web I found a lot of example of how spring have to be configured (file.xml) for publish/subscriber mode for active MQ but I need how beans need to be configured for Websphere MQ
Anyone have been configured both product with success?
The following is bean definition of a Websphere MQ ConnectionFactory:
<bean id="wmqConnectionFactory" class="com.ibm.mq.jms.MQConnectionFactory">
<property name="queueManager">
<value>QUEUE_MANAGER</value>
</property>
<property name="hostName">
<value>127.0.0.1</value>
</property>
<property name="port">
<value>1414</value>
</property>
<property name="transportType">
<value>1</value>
</property>
<property name="channel">
<value>SYSTEM.DEF.SVRCONN</value>
</property>
</bean>
you may need to provide a username and password, and you can accomplish that by wrapping it in a UserCredentialsConnectionFactoryAdapter:
<bean id="userCredentialsAdapter" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="wmqConnectionFactory" />
<property name="username" value=" " />
<property name="password" value=" " />
</bean>
It is also a good idea to wrap it in a CachingConnectionFactory, so that sessions, consumers and producers are cached, this wrapper also switches the auto-recovery to true:
<bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="userCredentialsAdapter"/>
<property name="cacheConsumers" value="true" />
<property name="cacheProducers" value="true" />
<property name="sessionCacheSize" value="10" />
</bean>
with this configuration, you can use the cachingConnectionFactory with whatever bean you need.
I could not found any decent, clear example to learn JMS component with Spring configuration. So I wrote something like this:
<bean id="weblogic" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<bean id="jmsJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://${ip}:${port}</prop>
</props>
</property>
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jmsJndiTemplate"/>
<property name="jndiName" value="jms/cdrPreMO-connfact-jndi"/>
</bean>
<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
<camel:endpoint id="jmsQueue" uri="weblogic:queue:jms/cdrPreMO-queue-jndi"/>
<route>
<from ref="jmsQueue"/>
<bean ref="test" method="writeFile"/>
<to uri="log:errors?level=ERROR"/>
</route>
</camelContext>
But it gives the exception :
Caused by: javax.naming.NameNotFoundException: Unable to resolve 'weblogic.jms.backend.jms'. Resolved 'weblogic.jms.backend'; remaining name 'jms'
at weblogic.jndi.internal.BasicNamingNode.newNameNotFoundException(BasicNamingNode.java:1139)
at weblogic.jndi.internal.BasicNamingNode.lookupHere(BasicNamingNode.java:252)
at weblogic.jndi.internal.ServerNamingNode.lookupHere(ServerNamingNode.java:182)
at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:206)
at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:214)
at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:214)
at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:214)
at weblogic.jndi.internal.WLEventContextImpl.lookup(WLEventContextImpl.java:254)
at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:393)
at weblogic.jms.frontend.FEManager.destinationCreate(FEManager.java:287)
... 8 more
JMS Conf is true(ip port and jndi names). It is getting the connection, and the session but gives the exception
Could someone tell me what are my mistakes?
Thanx
EDIT: fix applied according to the comment of Claus.
The Camel endpoints should refer to "weblogic" as the component name.
<camel:endpoint id="jmsQueue" uri="jms:queue:jms/cdrPreMO-queue-jndi"/>
Should be
<camel:endpoint id="jmsQueue" uri="weblogic:queue:jms/cdrPreMO-queue-jndi"/>
As that is the name you gave the JMS component in the id attribute of the < bean > tag, eg
<bean id="weblogic" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
Solved but with a workaround. I still do not know what the problem really is but, instead of weblogic create its own destination by itself, I gave the responsibility to spring like:
<bean id="weblogic" class="org.apache.camel.component.jms.JmsComponent">
<property name="configuration" ref="jmsConfiguration" />
</bean>
<bean id="jmsJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">${ip}:${port}</prop>
</props>
</property>
</bean>
<bean id="jndiDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="jmsJndiTemplate"/>
</bean>
<bean id="jmsConfiguration" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destinationResolver" ref="jndiDestinationResolver"/>
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jmsJndiTemplate"/>
<property name="jndiName" value="jms/cdrPreMO-connfact-jndi"/>
</bean>
It is working now.
Although question is pretty old, posting this solution for other users if they get this error. I ran into the this issue on Camel 2.19 version while trying to look up weblogic queue in weblogic 12c version. The lookup that happens here is most likely not a typical JNDI lookup when resolving queue destination in Weblogic.
The end point uri should contain the queue details as follows :
jms_server_name/jms_module_name!queue_name
For example if queue name is TestRequestQueue, created under a module named sample_jms_module and the JMS server is named sample_jms_server in Weblogic, then the uri would need to be as follows :
<camel:endpoint id="jmsQueue" uri="weblogic:queue:sample_jms_server/sample_jms_module!TestRequestQueue"/>
In the prefix portion of the uri weblogic:queue:, the component name can be anything as long as it refers to the created component. It needn't necessarily be weblogic. For example, if the JmsComponent is named as test-jms, the uri will need to be declared with prefix as test-jms:queue: .
Name of the JMS server in weblogic can be obtained from Weblogic console by navigating to the below path :
Services -> Messaging -> JMS Servers
Name of the queue, not the JNDI name, can be obtained from Weblogic console by navigating to the queue and clicking on Monitoring tab. This tab shows the destination name of the queue in the name column.
I've just run apache camel jms component in weblogic 12c with next configuration. The key is the jndi name for the queue.
It must be ./module_name!queueName. './' means local jms server.
<jee:jndi-lookup id="connectionFactoryBean" jndi-name="dpxcomConnectionFactory"/>
<bean id="dpxcomJMSConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="connectionFactoryBean"/>
<property name="sessionCacheSize" value="50"/>
</bean>
Route definition:
from("jms:queue:./DPXCOM!"+config.getMainQueueName()+"?concurrentConsumers="+config.getConcurrentConsumers()
+"&maxConcurrentConsumers="+config.getConcurrentConsumers()+"&jmsMessageType=Text&testConnectionOnStartup=true&connectionFactory=dpxcomJMSConnectionFactory&consumerType=Simple")
.setHeader("jmsMessage").body()
.process(new VerifyJMSMessageProcessor())
.choice()
..
..
end();
I am working with spring 3.0 and within our JBoss application server I perform a JNDI lookup to a remote WebLogic application server. The properties to connect to the WebLogic JNDI server are contained in a properties file called soa.properties. Here is what the spring-config.xml looks like to initialize the JndiTemplate bean
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:app.properties</value>
<value>classpath:soa.properties</value>
</list>
</property>
</bean>
<bean id="soaJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${soa.provider.initial}</prop>
<prop key="java.naming.provider.url">${soa.provider.url}</prop>
<prop key="java.naming.security.principal">${soa.security.principal}</prop>
<prop key="java.naming.security.credentials">${soa.security.credentials}</prop>
</props>
</property>
</bean>
This works fine for pulling my values out of the soa.properties file, but what I would rather do is pull the WebLogic JNDI connection values out of the JBoss JNDI tree.
My problem appears to be with the initialization of the InitialContext object that requires Properties for initialization.
I put all of my JNDI String values for WebLogic JNDI connection into the JBoss JNDI. Below is the code I am using to pull the values out and initialize JndiTemplate bean.
<bean id="soaUrl" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/provider/url" />
</bean>
<bean id="soaFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/provider/connection/factory" />
</bean>
<bean id="soaInitial" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/provider/initial" />
</bean>
<bean id="soaPrincipal" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/security/principal" />
</bean>
<bean id="soaCredential" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="soa/security/credential" />
</bean>
<bean id="testsoaJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<map>
<entry key="java.naming.factory.initial" value-ref="soaUrl" />
<entry key="java.naming.provider.url" value-ref="soaFactory" />
<entry key="java.naming.provider.initial" value-ref="soaInitial" />
<entry key="java.security.principal" value-ref="soaPrincipal" />
<entry key="java.security.credential" value-ref="soaCredential" />
</map>
</property>
</bean>
My application comes up with these beans created, but when I use testsoaJndiTemplate with say soaConnectionFactory like so it boms.
<bean id="soaConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="testsoaJndiTemplate" />
<property name="jndiName" value="${soa.provider.connection.factory.name}" />
</bean>
The error is so cryptic it does make any sense.
Thanks
I am currently working on a project that includes EJB 3.0 (stateless SB), JPA (Hibernate as the provider), JTA as transaction manager. The app server is JBoss AS 7. Spring is used for integrating EJB and JPA.
All seems to be working fine, except if there is any exception that occurs in the EJB, then the persistence unit is closed by Spring. On the subsequent request, the persistence unit is again created, which becomes time consuming and also should not happen in the ideal situation.
Below are the configuration details
persistence.xml
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<class>com.test.User</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>
spring-application-context.xml
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<jee:jndi-lookup id="dataSource" jndi-name="java:/datasources/test" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="database" value="MYSQL" />
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"></entry>
<entry key="hibernate.current_session_context_class" value="jta" />
<entry key="hibernate.connection.release_mode" value="auto" />
</map>
</property>
<property name="persistenceUnitPostProcessors">
<list>
<bean class="com.transaction.processor.JtaPersistenceUnitPostProcessor">
<property name="jtaMode" value="true"/>
<property name="jtaDataSource" ref="dataSource"/>
</bean>
</list>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:/TransactionManager"></property>
<property name="autodetectUserTransaction" value="false"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
The class JtaPersistenceUnitPostProcessor is responsible for setting the transaction-type as JTA and the datasource to jta-datasource.
Could anyone please provide any help on this.
Thanks in advance.
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:jboss/TransactionManager" />
<property name="userTransactionName" value="java:comp/UserTransaction" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
you didn't specify any error message . you can add these lines in your configuration file .
I see you use JTA transaction manager and use that only if you use distributed Transaction and use JNDI. JTA tran. manager listens TX happening through connection acquired from JNDI datasource. If you have datasource created in your code and is not a part of Web container but is limited inside app. container in your web server, JTA wont work.
If you want to implement Tx manager with in a single app. context go for JPA transaction manager which is very reliable.