Spring JMS can not connect to WebSphere MQ - authentication fail - spring

I config the WebSphere MQ with following command:
DEFINE QLOCAL(NEW.QL.RQ)
DEFINE QLOCAL(NEW.QL.RS)
DEFINE LISTENER('NEW.LSR') TRPTYPE(TCP) PORT(1420) CONTROL(QMGR)
START LISTENER('NEW.LSR')
DEFINE CHANNEL('NEW.SVR.CONN') CHLTYPE(SVRCONN)
SET CHLAUTH(*) TYPE(BLOCKUSER) USERLIST('nobody','*MQADMIN')
SET CHLAUTH(SYSTEM.ADMIN.*) TYPE(BLOCKUSER) USERLIST('nobody')
SET CHLAUTH(NEW.SVR.CONN) TYPE(ADDRESSMAP) ADDRESS(*) USERSRC(CHANNEL)
SET CHLAUTH(NEW.SVR.CONN) TYPE(BLOCKUSER) USERLIST('nobody')
REFRESH SECURITY
Then I can use MQ Explore connect to it successfully be using mqm username and empty password.
However, when I use spring jms, the authentication fail. The following section is my xml config.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:main.properties" />
<!-- WebSphere MQ Connection Factory -->
<bean id="mqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="hostName">
<value>${queue_hostname}</value>
</property>
<property name="port">
<value>${queue_port}</value>
</property>
<property name="queueManager">
<value>${queue_manager}</value>
</property>
<property name="transportType">
<value>1</value>
</property>
</bean>
<bean id="jmsConnectionFactory"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="mqConnectionFactory" />
<property name="username">
<value>${mq.username}</value>
</property>
<property name="password">
<value>${mq.password}</value>
</property>
</bean>
<!-- JMS Destination Resolver -->
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.DynamicDestinationResolver">
</bean>
<!-- JMS Queue Template -->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate102">
<property name="connectionFactory">
<ref bean="jmsConnectionFactory" />
</property>
<property name="destinationResolver">
<ref bean="jmsDestinationResolver" />
</property>
<property name="pubSubDomain">
<value>false</value>
</property>
<property name="receiveTimeout">
<value>20000</value>
</property>
</bean>
<bean id="messageService" class="com.test.testspringjmsmq.MessageService" />
</beans>
The error messages:
Caused by: com.ibm.msg.client.jms.DetailedJMSSecurityException: JMSWMQ2013: The security authentication was not valid that was supplied for QueueManager 'LOROL' with connection mode 'Client' and host name 'xx.xx.xx.xx'. Please check if the supplied username and password are correct on the QueueManager you are connecting to
at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:531)
at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:219)
at com.ibm.msg.client.wmq.internal.WMQConnection.<init>(WMQConnection.java:410)
at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createV7ProviderConnection(WMQConnectionFactory.java:7855)
at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createProviderConnection(WMQConnectionFactory.java:7331)
at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl.createConnection(JmsConnectionFactoryImpl.java:276)
at com.ibm.mq.jms.MQConnectionFactory.createCommonConnection(MQConnectionFactory.java:6055)
at com.ibm.mq.jms.MQTopicConnectionFactory.createTopicConnection(MQTopicConnectionFactory.java:114)
at com.ibm.mq.jms.MQTopicConnectionFactory.createConnection(MQTopicConnectionFactory.java:197)
at org.springframework.jms.connection.SingleConnectionFactory.doCreateConnection(SingleConnectionFactory.java:343)
at org.springframework.jms.connection.SingleConnectionFactory.initConnection(SingleConnectionFactory.java:290)
at org.springframework.jms.connection.SingleConnectionFactory.createConnection(SingleConnectionFactory.java:227)
at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:184)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:461)
... 25 more
Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2035' ('MQRC_NOT_AUTHORIZED').
at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:206)
... 37 more

Finally, I do not use Spring JMS to implement the connection between java and WebSphere MQ.
I directly use the simple JMS to implement it, and I think the configuration is more easy than Spring JMS.
The following section is the sample code for simple jms.
try {
MQQueueConnectionFactory cf = new MQQueueConnectionFactory();
// Config
cf.setHostName("localhost");
cf.setPort(1414);
cf.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
cf.setQueueManager("QM_thinkpad");
cf.setChannel("SYSTEM.DEF.SVRCONN");
MQQueueConnection connection = (MQQueueConnection) cf.createQueueConnection();
MQQueueSession session = (MQQueueSession) connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
MQQueue queue = (MQQueue) session.createQueue("queue:///Q1");
MQQueueSender sender = (MQQueueSender) session.createSender(queue);
MQQueueReceiver receiver = (MQQueueReceiver) session.createReceiver(queue);
long uniqueNumber = System.currentTimeMillis() % 1000;
JMSTextMessage message = (JMSTextMessage) session.createTextMessage("SimplePTP "+ uniqueNumber);
// Start the connection
connection.start();
sender.send(message);
System.out.println("Sent message:\\n" + message);
JMSMessage receivedMessage = (JMSMessage) receiver.receive(10000);
System.out.println("\\nReceived message:\\n" + receivedMessage);
sender.close();
receiver.close();
session.close();
connection.close();
System.out.println("\\nSUCCESS\\n");
}
catch (JMSException jmsex) {
System.out.println(jmsex);
System.out.println("\\nFAILURE\\n");
}
catch (Exception ex) {
System.out.println(ex);
System.out.println("\\nFAILURE\\n");
}
}

Related

Spring Integration - JMS

I am trying to read a message from a JMS Queue (using ActiveMQ). Issue I am facing is, messages are being read from the queue, but not getting displayed in the "service-activator".
Any help is much appreciated.
My code is as below:
(1) Spring Configuration
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd
http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Component scan to find all Spring components -->
<context:component-scan base-package="com.poc.springinteg._3" />
<!-- -->
<bean id="remoteJndiTemplate" class="org.springframework.jndi.JndiTemplate" lazy-init="false">
<property name="environment">
<props>
<prop key="java.naming.provider.url">tcp://localhost:61616</prop>
<prop key="java.naming.factory.url.pkgs">org.apache.activemq.jndi</prop>
<prop key="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</prop>
<prop key="connectionFactoryNames">DefaultActiveMQConnectionFactory,QueueConnectionFactory</prop>
<prop key="queue.SendReceiveQueue">org.apache.geronimo.configs/activemq-ra/JCAAdminObject/SendReceiveQueue</prop>
<prop key="queue.SendQueue">org.apache.geronimo.configs/activemq-ra/JCAAdminObject/MDBTransferBeanOutQueue</prop>
</props>
</property>
</bean>
<bean id="remoteConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="false">
<property name="jndiTemplate" ref="remoteJndiTemplate"/>
<property name="jndiName" value="QueueConnectionFactory"/>
<property name="lookupOnStartup" value="true" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<!-- Reading Queue -->
<bean id="inputQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0">
<value>InputQueue_3</value>
</constructor-arg>
</bean>
<bean id="messageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="remoteConnectionFactory"/>
<property name="destination" ref="inputQueue"/>
<property name="sessionTransacted" value="true"/>
<property name="maxConcurrentConsumers" value="1"/>
<property name="concurrentConsumers" value="1"/>
<property name="autoStartup" value="true"/>
</bean>
<int:channel id="inbound"/>
<int-jms:message-driven-channel-adapter id="jmsIn"
channel="inbound"
container="messageListenerContainer" />
<int:service-activator input-channel="inbound"
ref="messageHandler"
method="onMessage"/>
<bean id="messageHandler" class="com.poc.springinteg._3.HelloServiceImpl"/>
</beans>
(2) Service Activator MDP:
package com.poc.springinteg._3;
import javax.jms.Message;
public class HelloServiceImpl
{
public String onMessage(Message name) {
System.out.println( "getHelloMessage:, " + name );
return "getHelloMessage:, " + name ;
}
}
(3) Application start class:
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main( String[] args )
{
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:3_applicationContext.xml" );
applicationContext.registerShutdownHook();
}
}
Thanks
To make your onMessage(javax.jms.Message name) working you should specify extract-payload="false" on your <int-jms:message-driven-channel-adapter>:
/**
* Specify whether the JMS request Message's body should be extracted prior
* to converting into a Spring Integration Message. This value is set to
* <code>true</code> by default. To send the JMS Message itself as a
* Spring Integration Message payload, set this to <code>false</code>.
* #param extractRequestPayload true if the request payload should be extracted.
*/
public void setExtractRequestPayload(boolean extractRequestPayload) {
And quoting Reference Manual:
If extract-payload is set to true (which is the default), the received JMS Message will be passed through the MessageConverter. When relying on the default SimpleMessageConverter, this means that the resulting Spring Integration Message will have the JMS Message’s body as its payload. A JMS TextMessage will produce a String-based payload, a JMS BytesMessage will produce a byte array payload, and a JMS ObjectMessages Serializable instance will become the Spring Integration Message’s payload. If instead you prefer to have the raw JMS Message as the Spring Integration Message’s payload, then set 'extract-payload to false.
Got the solution to my problem:
Parameter type in method "onMessage" should be String:
import javax.jms.Message;
public class HelloServiceImpl
{
public String onMessage(String name) {
System.out.println( "getHelloMessage:, " + name );
return "getHelloMessage:, " + name ;
}
}

ActiveMQ Messages are not consumed spring boot, camel

I am trying to configure Spring Boot, Apache Camel, ActiveMQ all togheter. This is what I did so far:
I run ActiveMQ using activemq.bat
I log into the console to monitor messages
I start backend service (sources below)
I start frontend service (Backend and Frontend are different spring boot projects)
I sucesfully send message into the que from frontend but after 20s I am getting timeout. The message appears in ActiveMQ console but it's not consumed by backend.
Here's how I configured backend:
build.gradle:
dependencies {
compile("org.apache.camel:camel-spring-boot:2.16.0")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-websocket")
compile("org.springframework:spring-messaging")
compile("org.springframework:spring-jms")
compile("org.springframework.security:spring-security-web")
compile("org.springframework.security:spring-security-config")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile('org.apache.camel:camel-jms:2.16.0')
compile("org.hibernate:hibernate-core:4.0.1.Final")
compile("mysql:mysql-connector-java:5.1.37")
compile("log4j:log4j:1.2.16")
compile("junit:junit:4.12")
compile("org.mockito:mockito-all:1.8.4")
compile('org.apache.activemq:activemq-core:5.7.0')
compile('com.epam.training.auction:auction_common:1.0')
testCompile("junit:junit")
}
Route Config: (I use UsersServiceImpl for testing and both ways of defining it don't work)
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.epam.training.auction_backend.services.UsersServiceImpl;
#Configuration
public class MyRouterConfiguration {
#Bean
public RoutesBuilder myRouter() {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("jms:queue:auctions").to("bean:auctionsServiceImpl");
from("jms:queue:users").bean(UsersServiceImpl.class);
from("jms:queue:bidding").to("bean:biddingServiceImpl");
}
};
}
}
Client side, invoking method
#Override
public void registerUser(String username, String password) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("camel-client-remoting.xml");
UsersService usersService = context.getBean("usersServiceImpl", UsersService.class);
System.out.println("Invoking the logging");
UserTransferObject userTransferObject = new UserTransferObject("user", "pass");
usersService.addUser(userTransferObject);
System.out.println("User is logged");
IOHelper.close(context);
}
Client xml camel config
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camel:camelContext id="camel-client">
<camel:template id="camelTemplate"/>
<camel:proxy
id="auctionsServiceImpl"
serviceInterface="com.epam.training.auction.common.AuctionsService"
serviceUrl="jms:queue:auctions"/>
<camel:proxy
id="usersServiceImpl"
serviceInterface="com.epam.training.auction.common.UsersService"
serviceUrl="jms:queue:users"/>
<camel:proxy
id="biddingServiceImpl"
serviceInterface="com.epam.training.auction.common.BiddingService"
serviceUrl="jms:queue:bidding"/>
</camel:camelContext>
<bean id="jmsConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</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="jmsConnectionFactory"/>
</bean>
<bean id="jmsConfig"
class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="concurrentConsumers" value="10"/>
</bean>
<bean id="jms"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
<property name="transacted" value="true"/>
<property name="cacheLevelName" value="CACHE_CONSUMER"/>
</bean>
</beans>
During sending I also get warning:
2015-11-02 11:56:21.547 WARN 16328 --- [nio-8181-exec-5] o.s.b.f.s.DefaultListableBeanFactory : Bean creation exception on FactoryBean type check: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'usersServiceImpl': Invocation of init method failed; nested exception is org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: jms://queue:users due to: Cannot auto create component: jms
Common interfaces nad transfer objects are defined in 3rd project which is a dependency for both backend and frontend projects.
I feel that there's one missing part of this configuration. Please tell me what could it be.
Thanks in advance.
You need to change
<bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
to
<bean id="jms"
class="org.apache.activemq.camel.component.ActiveMQComponent">
or change your endpoint urls to .to("activemq:queue:users").
The id of your ActiveMQComponent is the name used in the .to() to identify to camel that you want to use that component definition.

Spring + tomee JTA transactions

I have been struggling through trying to build a very simple application that deploys to tomee using spring, hibernate and JMS. I believe that all of my configurations are correct (have the mysql xa data source and the xa active mq connection factory) but things aren't working as I would expect. Currently I have a simple service that writes using the injected entity manager then pushes to JMS within one method that is annotated as being transactional (spring annotation) but my message listener is being delivered these messages before the transaction is committed in spring.
I've tried using JMS template and the xa connection factory directly, but neither works properly. The template is configured with the jta transaction manager received from jndi. Any ideas what to look at for hints as to why the JMS sends are not participating in the same transaction as the database writes?
Spring Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:encryption="http://www.jasypt.org/schema/encryption"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd
http://www.jasypt.org/schema/encryption http://www.jasypt.org/schema/encryption/jasypt-spring31-encryption-1.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.1.xsd"
default-autowire="byType" default-lazy-init="false">
<context:component-scan annotation-config="false" base-package="org.superbiz" />
<bean class="org.springframework.orm.jpa.DefaultJpaDialect" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<property name="alwaysUseJndiLookup" value="false" />
<property name="jndiFactory" >
<ref local="jndiFactory"/>
</property>
</bean>
<bean id="jndiFactory" class="org.springframework.jndi.support.SimpleJndiBeanFactory">
<property name="resourceRef" value="true" />
</bean>
<bean id="PrintTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref local="jmsFactory" />
</property>
<property name="defaultDestinationName" value="resources/jms/PrintQueue" />
<property name="deliveryPersistent" value="true"/>
<!-- <property name="sessionTransacted" value="true"/> -->
<!-- <property name="sessionAcknowledgeMode" value="0"/> -->
</bean>
<bean id="PersistTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref local="jmsFactory" />
</property>
<property name="defaultDestinationName" value="resources/jms/PersistQueue" />
<property name="deliveryPersistent" value="true"/>
<!-- <property name="sessionTransacted" value="true"/> -->
<!-- <property name="sessionAcknowledgeMode" value="0"/> -->
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property name="defaultPersistenceUnitName" value="movie-unit" />
<property name="persistenceContexts">
<map>
<entry key="movie-unit" value="persistence/movie-unit" />
</map>
</property>
</bean>
<context:component-scan base-package="org.superbiz.ejb" annotation-config="false">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<jee:jndi-lookup id="jmsFactory" jndi-name="resources/jms/ConnectionFactory" expected-type="javax.jms.ConnectionFactory" />
<tx:jta-transaction-manager />
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="printBean" class="org.superbiz.mdb.PrintBean"/>
<bean id="persistBean" class="org.superbiz.mdb.PersistBean"/>
<jms:listener-container container-type="default" connection-factory="jmsFactory" cache="none" transaction-manager="transactionManager" concurrency="1" receive-timeout="1000" prefetch="-1">
<jms:listener destination="resources/jms/PrintQueue" ref="printBean" />
<jms:listener destination="resources/jms/PersistQueue" ref="persistBean" />
</jms:listener-container>
</beans>
tomee.xml (cobbled together from http://tomee-openejb.979440.n4.nabble.com/MDB-doesn-t-read-messages-td4666169.html)
<Resource id="ActiveMQResourceAdapter" type="ActiveMQResourceAdapter">
BrokerXmlConfig=broker:(vm://localhost)
</Resource>
<Resource id="resources/jms/ConnectionFactory" type="javax.jms.ConnectionFactory">
ResourceAdapter = ActiveMQResourceAdapter
</Resource>
<Resource id="resources/jms/XAConnectionFactory" class-name="org.apache.activemq.ActiveMQXAConnectionFactory">
BrokerURL = vm://localhost
ResourceAdapter = ActiveMQResourceAdapter
</Resource>
<Resource id="resources/jms/PrintQueue" type="javax.jms.Queue"/>
<Resource id="resources/jms/PersistQueue" type="javax.jms.Queue"/>
<Resource id="MySQL Database" type="DataSource">
JdbcDriver com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
JdbcUrl jdbc:mysql://localhost/test
UserName test
</Resource>
I've tried several ways to include not using the XAConnectionFactory with the JMSTemplate configured to be sessionTransacted and not, removing the JMSTemplate and creating the connection/session/producer/message from the connectionFactory, but I've run into an issue each time. With manually creating the connection/session/producer/message from the ConnectionFactory I notice that the 20 items I attempt to write to the database then send to another JMS Queue start being read before the services transaction completes.
As far as I can tell everything is configured correctly (although I could definitely be wrong since this was pulled from lots of places). My goal is to be able to use the JMSTemplate instead of manually creating the connection/session/etc myself, but I'm at a loss for why this is happening at this point so any ideas are greatly appreciated.
I've also bumped the logging of the Spring JtaTransactionManager up and I see the following happening when the #Transactional method is called
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.superbiz.ejb.Movies.send]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit
Then I see the my MDB code trying to retrieve the item from the entityManager (which works/fails intermittently). When it succeeds I see this
printing from MDB: director: director0title: title0year: 0
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.springframework.jms.listener.DefaultMessageListenerContainer#0]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
When it fails I see this
/***************** BROKEN ***************/
/*******************435265*****************/
/***************** BROKEN ***************/
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit
DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.springframework.jms.listener.DefaultMessageListenerContainer#0]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
I've further cranked up the logging
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.springframework.jms.listener.DefaultMessageListenerContainer#1]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
**bold** [org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Creating new transaction with name [org.springframework.jms.listener.DefaultMessageListenerContainer#0]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Initializing transaction synchronization
[org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Initializing transaction synchronization
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [org.springframework.jms.connection.JmsResourceHolder#81032a4] for key [org.apache.activemq.ra.ActiveMQConnectionFactory#5ee0c65d] to thread [org.springframework.jms.listener.DefaultMessageListenerContainer#1-1]
[org.springframework.jms.listener.DefaultMessageListenerContainer#0-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [org.springframework.jms.connection.JmsResourceHolder#eaebd86] for key [org.apache.activemq.ra.ActiveMQConnectionFactory#5ee0c65d] to thread [org.springframework.jms.listener.DefaultMessageListenerContainer#0-1]
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Participating in existing transaction
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.interceptor.TransactionInterceptor - Getting transaction for [org.superbiz.mdb.PersistBean.onMessage]
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.jms.connection.JmsResourceHolder#81032a4] for key [org.apache.activemq.ra.ActiveMQConnectionFactory#5ee0c65d] bound to thread [org.springframework.jms.listener.DefaultMessageListenerContainer#1-1]
Persisted finished, but not yet committed
Leaving persist, should commit
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.interceptor.TransactionInterceptor - Completing transaction for [org.superbiz.mdb.PersistBean.onMessage]
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.jta.JtaTransactionManager - Triggering beforeCommit synchronization
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.jta.JtaTransactionManager - Triggering beforeCompletion synchronization
[org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Removed value [org.springframework.jms.connection.JmsResourceHolder#81032a4] for key [org.apache.activemq.ra.ActiveMQConnectionFactory#5ee0c65d] from thread [org.springframework.jms.listener.DefaultMessageListenerContainer#1-1]
**bold** [org.springframework.jms.listener.DefaultMessageListenerContainer#1-1] DEBUG org.springframework.transaction.jta.JtaTransactionManager - Initiating transaction commit
Entering print
/***************** BROKEN ***************/
/*******************597852*****************/
/***************** BROKEN ***************/
in this case DefaultMessageListenerContainer#1-1 is my Persist bean and 0-1 is a bean that retrieves the entity by id and then prints the content.
I am not 100% sure how to read this, but it's interesting to me that the DMLC#1-1 commits well after a new transaction has begun on DMLC#0-1, but DMLC#0-1 sees the message. I would have thought that DMLC#0-1 would have needed to start a new transaction to see this OR since he received the JMS message the entity should also be persisted to the database.
Contents of my persist bean
#Override
#Transactional
public void onMessage(Message message) {
TextMessage msg = (TextMessage)message;
int x;
try {
x = Integer.parseInt(msg.getText());
Movie movie = new Movie("director" + x, "title" + x, x);
entityManager.persist(movie);
final long id = movie.getId();
template.send(new MessageCreator() {
#Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(Long.toString(id));
}
});
System.out.println("Persisted finished, but not yet committed");
System.out.println("Leaving persist, should commit");
} catch (Exception e) {
e.printStackTrace();
}
}
Contents of my print bean
public void onMessage(Message message) {
System.out.println("Entering print");
final TextMessage textMessage = (TextMessage) message;
try {
long id = Long.parseLong(textMessage.getText());
Movie movie = entityManager.find(Movie.class, id);
if(movie == null){
System.out.println("/***************** BROKEN ***************/");
System.out.println("/*******************" + id + "*****************/");
System.out.println("/***************** BROKEN ***************/");
} else {
System.out.println("updating: "+ movie);
}
} catch (Exception e) {
e.printStackTrace();
}
}
The entire app is available at https://github.com/jej2003/simple-spring, running a vanilla Tomee 1.7.1 with the necessary hibernate jars added to the tomee/lib directory.
I'm really at a loss here, does no one run JTA transactions in Tomee with Spring?
After a ton of debugging it turns out that the failure was not in the JTA implementation, but more so my understanding of JTA in general. While JTA ensures that both transactions will successfully commit, it does not enforce an order apparently of those transactions. The answer was ultimately provided here https://jira.spring.io/browse/SPR-12535, by Stéphane Nicoll.

spring DefaultMessageListenerContainer and websphere MQ - failed to connect Queue Manager

This is my first time to post question on stackoverflow. I tried as much formatting for code/question and try to as much clear as i can do. apologize and explain if there's any err. recorrect in my next question.
I am newbie in try implementing service through soap over jms using websphereMq and spring JMS functionality.
I have make sure below things
binding file generated without any error encounter
Status of queue manager and Queue are up and running.
I encounter below error while try putting message into websphereMQ
com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2058' ('MQRC_Q_MGR_NAME_ERROR')
I have done homework regarding this error. This error may occurs due to unavailability of Queue manager but i see QM is up and running. where i am doing wrong? How can i resolved this error to put message successfully to webspherMQ using spring functionlity?
TestClass
public class JmsTransportWebServiceIntegrationTest {
private static final String expectedResponseContent = "<tns:placeOrderResponse xmlns:tns=\"http://www.packtpub.com/liverestaurant/OrderService/schema\"><tns:refNumber>order-xxxx_yyyy_1234</tns:refNumber></tns:placeOrderResponse>";
#Autowired
private WebServiceTemplate webServiceTemplate;
public void setWebServiceTemplate(WebServiceTemplate webServiceTemplate) {
this.webServiceTemplate = webServiceTemplate;
}
#Test
public void testSendReceive() throws Exception {
InputStream is = new JmsTransportWebServiceIntegrationTest().getClass().getResourceAsStream("placeOrderRequest.xml");
StreamSource source = new StreamSource(is);
StringResult result = new StringResult();
webServiceTemplate.sendSourceAndReceiveToResult(source, result);
XMLAssert.assertXMLEqual("Invalid content received", expectedResponseContent, result.toString());
} }
applicationContext.xml
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<map>
<entry key="java.naming.factory.initial"
value="com.sun.jndi.fscontext.RefFSContextFactory"/>
<entry key="java.naming.provider.url" value="file:C:/JNDI-Directory" />
</map>
</property>
</bean>
<bean id="ibm-mq-jms-qcf" class= "org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>jms/mdpSampleQCF</value>
</property>
</bean>
<!-- Bean for JMS Destination -->
<bean id="ibm-mq-queue" class= "org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName">
<value>jms/mdpSampleQueue</value>
</property>
</bean>
<bean id="listenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="1" />
<property name="connectionFactory" ref="ibm-mq-jms-qcf" />
<property name="destination" ref="ibm-mq-queue" />
<property name="messageListener">
<bean class="org.springframework.ws.transport.jms.WebServiceMessageListener">
<property name="messageFactory" ref="messageFactory"/>
<property name="messageReceiver" ref="messageDispatcher"/>
</bean>
</property>
</bean>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.jms.JmsMessageSender">
<property name="connectionFactory" ref="ibm-mq-jms-qcf"/>
</bean>
</property>
<property name="defaultUri" value="jms:mdpSampleQueue?deliveryMode=NON_PERSISTENT"/>
</bean>
<bean id="messageDispatcher" class="org.springframework.ws.soap.server.SoapMessageDispatcher">
<property name="endpointMappings">
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<property name="defaultEndpoint">
<bean class="com.packtpub.liverestaurant.service.endpoint.SimplePayloadEndpoint">
<property name="orderService">
<bean class="com.packtpub.liverestaurant.service.OrderServiceImpl"/>
</property>
</bean>
</property>
</bean>
</property>
</bean
I know this is quite old question, but maybe my answer will help someone in future.
I'm using WebSphere MQ 7.5 now and in installation there are also some Java classes. One that helped me a lot is called MQIVP.java in my installation in c:\Program Files (x86)\IBM\WebSphere MQ\tools\wmqjava\samples. Very good to test setting with this class first. From source of that class we can find that 2058 stands for:
Reason: 2058 - Queue manager name not valid or not known.
Action: Amend the queue manager name and retry.
Simply pressing enter at the queue manager name prompt will
connect to the default queue manager.

Sending message to Weblogic JMS Queue from a Camel Route

I am trying to put a message on a Queue in Weblogic JMS, via a Camel Route.
My aim is to eventually configure a Route to consume the messages from the jms queue to which I publish the data from the earlier Route.
Here is my config:
<bean id="jndiTemplate" 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://localhost:7001</prop>
<!-- opional ... -->
<prop key="java.naming.security.principal">weblogic</prop>
<prop key="java.naming.security.credentials">weblogic</prop>
</props>
</property>
</bean>
<!-- Gets a Weblogic JMS Connection factory object from JDNI Server by jndiName-->
<bean id="webLogicJmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="jms/TestConnectionFactory" /> <!-- the connection factory object is store under this name -->
</bean>
<!-- Create a new WebLogic Jms Camel Component -->
<bean id="wmq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="webLogicJmsConnectionFactory"/>
</bean>
My Route looks like this:
from("cxfrs:bean:rsServer")
.setBody().body(TestRequest.class)
.process(new Processor(){
#Override
public void process(Exchange exchange) throws Exception {
TestRequest request = exchange.getIn().getBody(TestRequest.class);
TestResponse response = new TestResponse();
response.setAddress(request.getAddress());
response.setName(request.getName());
}
}).to("wmq:queue:TestJMSQueue");
I am getting this exception when I try to execute this Route:
May 27, 2013 6:37:47 PM org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
WARNING: javax.ws.rs.WebApplicationException: org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is weblogic.jms.common.JMSException: [JMSExceptions:045101]The destination name passed to createTopic or createQueue "TestJMSModule!TestJMSQueue" is invalid. If the destination name does not contain a "/" character then it must be the name of a distributed destination that is available in the cluster to which the client is attached. If it does contain a "/" character then the string before the "/" must be the name of a JMSServer or a ".". The string after the "/" is the name of a the desired destination. If the "./" version of the string is used then any destination with the given name on the local WLS server will be returned.
at org.apache.camel.component.cxf.jaxrs.CxfRsInvoker.returnResponse(CxfRsInvoker.java:149)
at org.apache.camel.component.cxf.jaxrs.CxfRsInvoker.asyncInvoke(CxfRsInvoker.java:104)
at org.apache.camel.component.cxf.jaxrs.CxfRsInvoker.performInvocation(CxfRsInvoker.java:57)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:167)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:94)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor
...
Caused by: weblogic.jms.common.JMSException: [JMSExceptions:045101]The destination name passed to createTopic or createQueue "TestJMSModule!TestJMSQueue" is invalid. If the destination name does not contain a "/" character then it must be the name of a distributed destination that is available in the cluster to which the client is attached. If it does contain a "/" character then the string before the "/" must be the name of a JMSServer or a ".". The string after the "/" is the name of a the desired destination. If the "./" version of the string is used then any destination with the given name on the local WLS server will be returned.
at weblogic.jms.frontend.FEManager.destinationCreate(FEManager.java:202)
at weblogic.jms.frontend.FEManager.invoke(FEManager.java:544)
at weblogic.messaging.dispatcher.Request.wrappedFiniteStateMachine(Request.java:961)
at weblogic.messaging.dispatcher.DispatcherImpl.syncRequest(DispatcherImpl.java:184)
at weblogic.messaging.dispatcher.DispatcherImpl.dispatchSyncNoTran(DispatcherImpl.java:287)
at weblogic.jms.dispatcher.DispatcherAdapter.dispatchSyncNoTran(DispatcherAdapter.java:59)
at weblogic.jms.client.JMSSession.createDestination(JMSSession.java:3118)
at weblogic.jms.client.JMSSession.createQueue(JMSSession.java:2514)
I followed the procedure to create a Queue mentioned here: https://blogs.oracle.com/soaproactive/entry/how_to_create_a_simple
I am creating a JMS Module(TestJMSModule) and in that I am creating a Queue(TestJMSQueue) and a connection factory inside it.
I am new to JMS and I know I am doing something wrong with the configurations either on the Camel side or the Weblogic side, but not able to figure out what. Any help would be greatly appreciated.
Thanks in advance.
You need to create a JMS Server. Then you need to create a subdeployment in your JMS Module and then target the subdeployment to the JMS Server.
Then the syntax needs to be
JMSServer/JMSModule!Queue
Unfortunately I'm not an expert in WebLogic configuration.
Client side config looks correct.
The exception says the object name is not right.
In the example you mentioned jndi name of the queue is "jms/TestJMSQueue", not just "TestJMSQueue".
To me it means you should be using .to("wmq:queue:jms/TestJMSQueue"); instead.
I was to integrate Spring (4.1.6) + Apache Camel (2.15.2) and consuming messages from a JMS Queue hosted on Oracle Weblogic (11g).
applicationContext.xml
<bean id="jndiTemplate" 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://localhost:7001</prop>
<prop key="java.naming.security.principal">weblogic</prop>
<prop key="java.naming.security.credentials">welcome1</prop>
</props>
</property>
</bean>
<bean id="webLogicJmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<!-- Connection factory JNDI name -->
<property name="jndiName" value="jms/TestConnectionFactory" />
</bean>
<bean id="weblogicJmsComponent" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="webLogicJmsConnectionFactory" />
</bean>
<camel:camelContext id="camel" xmlns:camel="http://camel.apache.org/schema/spring">
<!-- Route to copy files -->
<camel:route startupOrder="1">
<camel:from uri="file:data/inbox?noop=true" />
<camel:process ref="loggingProcessor" />
<camel:to uri="file:data/outbox" />
</camel:route>
<!-- Route to read from JMS and process them in jmsReaderProcessor -->
<camel:route startupOrder="2">
<camel:from uri="weblogicJmsComponent:queue:TestJMSServer/TestJMSModule!TestJMSQueue" />
<camel:process ref="jmsReaderProcessor" />
</camel:route>
</camel:camelContext>
loggingProcessor and jmsReaderProcessor are two Camel Processor that just log the messages in/out from Exchange object.
public void process(Exchange exchange) throws Exception {
LOG.info("begin process()");
LOG.info("process() -- Got exchange: {}", exchange);
Message messageIn = exchange.getIn();
LOG.info("process() -- Got messageIn: {}", messageIn);
LOG.info("process() -- Got messageIn.getBody(): {}", messageIn.getBody());
Message messageOut = exchange.getOut();
LOG.info("process() -- Got messageOut: {}", messageOut);
LOG.info("end process()");
}
Kind Regards,
Cristian Manoliu

Resources