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();
Related
I am developing a Spring web application where I am using JMS as well as some datasource connection.
Now Instead of hardcoding the JNDI names of DataSource/Jms Connection Factory,I want to read them from a external properties file.
I used the following configuration::
<bean id="myProps" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath*:myFile"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
`<jee:jndi-lookup` id="dataSource" jndi-name="${DS_JNDI}" expected-type="javax.sql.DataSource"/>
But during deployment time it is throwing an error in weblogic:::
javax.naming.NameNotFoundException: Unable to resolve '${DS_JNDI}'. Resolved ''; remaining name '${DS_JNDI}'
Is it like that I cannot put a property file entry when using <jee:jndi-lookup>???
you should remove the star after classpath, and add properties of file extension
<bean id="myProps" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:myFile.properties"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
<bean id="myProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:myFile.properties</value>
</list>
</property>
</bean>
This is the correct solution of the problem.I think from Spring5.x onwards it has stopped appending ".properties" extension.
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.
I need a little bit of help in configuring JBoss to work with MQ. I have created initial context in MQ using IBM MQ Explorer and have given a local directory for all bindings like file:/C:/jndi. I have created a connection factory for this initial context. Now JBoss documentation says to bind like this
<connection-definition class-name="com.ibm.mq.connector.outbound.ManagedConnectionFactoryImpl"
jndi-name="java:jboss/MQ.CONNECTIONFACTORY.NAME"
pool-name="MQ.CONNECTIONFACTORY.NAME">
I think I am missing some point here. How do I tell Jboss that my InitialContext bindings are in a directory. I have tried most of the combinations. May be I am not getting the concept right. Any pointers ?
When I try to access this MQ.CONNECTIONFACTORY.NAME from a test servlet I wrote I get javax.naming.NameNotFoundException . If I follow same steps in Java SE environment I am successfully able to establish a connection. I am new to application servers and the question might be naive
Regards
The description of the resources created via MQExplorer suggest that these have been put into JNDI backed by a File System context. This is perfectly fine, but what in theory needs to be done now is get JBOSS to read objects out that JNDI context rather than the usual JNDI provider provided by JBOSS. The settings that are in the connection definition extract are using the standard JBOSS JNDI context.
As an example of using JBOSS with the WebSphere MQ Resoruce Adapter have a look here http://pic.dhe.ibm.com/infocenter/wmqv7/v7r5/topic/com.ibm.mq.dev.doc/q031810_.htm
This links to an example set of definitions that store WMQ JMS administered objects in the JBOSS JNDI context.
This is an important question. I have used Spring for this, like this:
<util:properties id="remoteEnv">
<prop key="java.naming.provider.url">file:${my.config.path}/bindings</prop>
<prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jboss.naming.remote.client</prop>
<prop key="java.naming.factory.initial">com.sun.jndi.fscontext.RefFSContextFactory</prop>
<prop key="java.naming.security.principal">${mdb.user.name}</prop>
<prop key="java.naming.security.credentials">${mdb.user.pass}</prop>
</util:properties>
<bean id="remoteJNDITemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment" ref="remoteEnv" />
</bean>
<bean id="remoteJmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="remoteJNDITemplate" />
<property name="cache" value="true" />
</bean>
<jee:jndi-lookup id="senderQueue" jndi-name="MY_QUEUE_NAME" environment-ref="remoteEnv" />
<bean id="xamqconnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="remoteJNDITemplate"/>
</property>
<property name="jndiName" value="MYCONNECTIONFACTORYJNDINAME"/>
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.XAQueueConnectionFactory" />
</bean>
<bean id="xaMQSenderJMSTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="xamqconnectionFactory" />
</property>
<property name="pubSubDomain">
<value>false</value>
</property>
<property name="defaultDestination">
<ref bean="senderQueue" />
</property>
<property name="destinationResolver" ref="remoteJmsDestinationResolver" />
</bean>
however using the configuration above we bypass the resource adapter. That's no problem otherwise but it prevents transactions from joining the JBoss transaction, so JMS messages are send immediately, not with transaction commit. I haven't found a fix for that yet.
com.sun.jndi.fscontext.RefFSContextFactory, that is used to read .bindings file, can be found at this dependency:
<dependency>
<groupId>com.sun.messaging.mq</groupId>
<artifactId>fscontext</artifactId>
<version>4.6-b01</version>
</dependency>
We have third party applications that make restful calls to camel cxfrs endpoint which is then routed to an external activeMQ. There are applications consuming these JMS messages and provide XML responses. This is all done synchronously using camel InOut exchangePattern. The architecture is very straight forward and simple. We were using activeMQ 5.5.0-fuse, camel-jms 2.8.x and activemq-pool 5.6.
Using this configuration, we see this exception at random times:
javax.jms.InvalidDestinationException: Cannot publish to a deleted Destination: temp- queue://ID:testserver-37266-1366126830205-0:0:1
at org.apache.activemq.ActiveMQSession.send(ActiveMQSession.java:1696)
at org.apache.activemq.ActiveMQMessageProducer.send(ActiveMQMessageProducer.java:231)
at org.apache.activemq.pool.PooledProducer.send(PooledProducer.java:74)
at org.apache.activemq.pool.PooledProducer.send(PooledProducer.java:55)
When this happens the server just stalls and none of our services respond until we restart activeMQ, tomcat and all other services.
camel config:
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<bean id="routeBuilder" class="gov.nasa.arc.tmi.route.TMIServiceRoute"/>
<bean id="jaxbProvider" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
<property name="marshallerProperties" ref="propertiesMap"/>
</bean>
<util:map id="propertiesMap">
<entry key="jaxb.formatted.output">
<value type="java.lang.Boolean">true</value>
</entry>
</util:map>
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="routeBuilder"/>
</camelContext>
<bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://localhost:61616"/>
Camel Router class:
//reroute
from("cxfrs:/rr?resourceClasses=x.y.z.route.RerouteResource")
.setExchangePattern(ExchangePattern.InOut)
.process(new RerouteProcessor())
.to("activemq:queue:x.y.z.tmi.request");
Here is the spring configuration of the application that listens on queue:x.y.z.tmi.request consumes JMS messages:
<context:annotation-config/>
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>tcp://localhost:61616? wireFormat.maxInactivityDurationInitalDelay=30000</value>
</property>
</bean>
<bean id="pooledConnectionFactory"
class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="8" />
<property name="connectionFactory" ref="connectionFactory" />
</bean>
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="gov.nasa.arc.tmi.request"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="defaultDestination" ref="destination" />
</bean>
<jms:listener-container connection-factory="pooledConnectionFactory" concurrency="10">
<jms:listener destination="gov.nasa.arc.tmi.request" ref="tmiQueryListener" />
After googling, I came across these bugs:
https://issues.apache.org/jira/browse/CAMEL-6229
https://issues.apache.org/jira/browse/AMQ-3457
Based on these, we upgraded to camel 2.10.4, activeMq 5.7 and activemq-pool 5.7. Even so, the problem remains.
I am really stuck and don't know how to resolve this issue. Can some one kindly point out what could be wrong?
Thanks.
I wonder if its because the processing the JMS message on the other side takes too long, and then the inactive monitor of ActiveMQ deletes the temp destination as its been inactive for > 30 seconds. http://activemq.apache.org/activemq-inactivitymonitor.html
Maybe try to set the timeout to a higher value, or disable it.
Another option is to use fixed queues for reply queues instead of temp queues.
I do have a working configuration in Spring for JPA with Hibernate provider:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<tx:annotation-driven mode="aspectj"/>
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>
This configuration is working in a small Spring based web-app.
But, when I insert the same configuration into an other existing Spring based web-app, I do get the following exception:
javax.persistence.TransactionRequiredException: no transaction is in progress
I think it has some conflict with Spring JDBC Templates:
<bean id="mysqlTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource" />
</bean>
How can I get this to work side by side?
"no transaction in progress" just means you're trying to use an EntityManager somewhere and you didn't start a transaction first. The stack trace will tell you exactly where that is. Since you're using annotation-driven transactions, just make sure you have an appropriate #Transactional somewhere up the call chain from the location where the exception is happening.