I have been struggling with this for a long time now. I have an IBM Websphere MQ, which uses EJB and MDB
The following is where the ejb mdb is configured.
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://websphere.ibm.com/xml/ns/javaee"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd" version="1.0">
<message-driven name="Queue1MDB">
<jca-adapter activation-spec-binding-name="jms/Queue1MQActivationSpec" destination-binding-name="jms/Queue1RequestQueue"/>
<resource-ref binding-name="jms/QueueConnectionFactory" name="jms/QueueConnectionFactory"/>
<message-destination-ref binding-name="jms/SuccessfulResponseQueue" name="jms/SuccessfulResponseQueue"/>
<message-destination-ref binding-name="jms/FailedResponseQueue" name="jms/FailedResponseQueue"/>
</message-driven>
<message-driven name="Queue2MDB">
<jca-adapter activation-spec-binding-name="jms/Queue2MQActivationSpec" destination-binding-name="jms/Queue2RequestQueue"/>
<resource-ref binding-name="jms/QueueConnectionFactory" name="jms/QueueConnectionFactory"/>
<message-destination-ref binding-name="jms/SuccessfulResponseQueue" name="jms/SuccessfulResponseQueue"/>
<message-destination-ref binding-name="jms/FailedResponseQueue" name="jms/FailedResponseQueue"/>
</message-driven>
<message-driven name="Queue3MDB">
<jca-adapter activation-spec-binding-name="jms/Queue3MQActivationSpec" destination-binding-name="jms/Queue3RequestQueue"/>
<resource-ref binding-name="jms/QueueConnectionFactory" name="jms/QueueConnectionFactory"/>
<message-destination-ref binding-name="jms/SuccessfulResponseQueue" name="jms/SuccessfulResponseQueue"/>
<message-destination-ref binding-name="jms/FailedResponseQueue" name="jms/FailedResponseQueue"/>
</message-driven>
<message-driven name="Queue4MDB">
<jca-adapter activation-spec-binding-name="jms/Queue4MQActivationSpec" destination-binding-name="jms/Queue4RequestQueue"/>
<resource-ref binding-name="jms/QueueConnectionFactory" name="jms/QueueConnectionFactory"/>
<message-destination-ref binding-name="jms/SuccessfulResponseQueue" name="jms/SuccessfulResponseQueue"/>
<message-destination-ref binding-name="jms/FailedResponseQueue" name="jms/FailedResponseQueue"/>
</message-driven>
</ejb-jar-bnd>
This is configured in ear, which is deployed in IBM WAS. The destination-binding-name will pick the corresponding queue details from the IBM WAS.
And later, my configuring the MDB in my java class like below, the listening is achieved on all the queues simultaneously and the messages are picked up:
#Resource(name = "jms/QueueContractConnectionFactory")
private ConnectionFactory connectionFactory;
#Resource(name = "jms/FailedResponseQueue")
private Queue errorQueue;
#Resource(name = "jms/SuccessfulResponseQueue")
private Queue responseQueue;
I now have to remove the ejb and modify the mdb configurations to make it deploy-able in tomcat.
The xml is something, which I literally have no idea on how to map it without the ejb parameters.
Can someone help or share a document on how to achieve this? I would like to have a example of IBM MQ to Spring JMS with Activation Spec.
Thanks in advance.
As has been commented, it's not simply a matter of replacing WAS with Tomcat, as they are not the same kind of container. So you can not directly deploy your WAS artifacts (the MDBs, notably) directly in to Tomcat. In order to get these in to Tomcat, they will have to be rewritten.
By being an MDB, the container manages for you: connecting to the JMS server, routing of messages from the queue/topic to your logic, multi-threaded message processing (handling more than one queued message at once) and, most notably, transaction management.
Now, message processing against JMS is pretty straightforward. You can make a connection to JMS readily. You can copy an example off the net and get that working. Running processing in the background is straightforward, there are examples of that as well. JMS 2.0 is easier to use than JMS 1.x. No reason not to port to that (unless MQ doesn't support JMS 2.0).
Running multiple instances of the logic, transactionally, is not so straightforward, but maybe that's not a keen aspect of your processing.
However, even if you were able to get all of that working, there's no guarantee at this juncture that your logic will work directly. We don't know if you logic calls other EJBs or leverages any of the other Java EE infrastructure. Were it to do so, them you have to port that aspect of your logic as well, not just the MDB connectivity.
So, this is a deeper problem. It's easy to say "just deploy it in Tomcat", but there could be details that derail that and need to be accounted for.
Another take is to convert the logic to Spring, as that can deploy in Tomcat readily. But that's not necessarily simpler than anything else -- all of the caveats remain.
Finally, "deploying in Tomcat" is almost a non-sequitur in this case because MDBs are not Web Apps, and Tomcat deploys Web Apps. You can create a shell of a Web App that does nothing but house your message driven logic. It's easy to do, I and many others have abused the Web App life cycles to our own nefarious ends for things like this.
So, in the end, I think you need more clarity as to what "deploy in Tomcat" really means, what the expectations are in the end, and whether your message logic relies on other Java EE infrastructure etc. Is the goal to run in Tomcat or to not run in WAS (in that case, as noted in the comments, there are other app servers you could possibly use that would be much easier to transition to).
Mike my other post that you linked to this question outlines the steps assuming you are good with setting up the springframework, MQ and server administration. But if you are struggling to get a start, here's some pointers.
Before you begin, you need to understand that this can be technically challenging. Sometimes, instead of changing what exists, breaking down what exists into multiple modules and implementing them from scratch makes more sense. Should you choose to change what exists, here's how to approach it:
Get the spring framework working in your application that you built in RAD. Did you do this successfully? Just inject any bean from the application context and see if you can get this to work on WAS. If you can do this successfully, it means you got a head start, the rest of it can be done. Let me know when you get to this - paste your application context or configuration here. I can tell you what to do next. Remember, you don't have to switch to tomcat right away - your aim should be to replace an MDB with a spring bean that can listen to messages - and this can run on WAS.
There is one thing you should be aware of with respect of Websphere MQ. The connection pooling with MQ classes for JMS is supported only through Websphere application server. When you migrate to Tomcat you may experience performance penalty and you may have to implement your self some amount of pooling. I think spring can help in this regards. I will quote it from IBM documentation
public void setUseConnectionPooling(boolean usePooling)
Deprecated. JMS does not use connection pooling anymore. Any
connection pooling should be done using the facilities provided by the
App Server. Set the use of ConnectionPooling in earlier versions of
the IBM MQ classes for JMS. This method is retained for compatibility
with older MQJMS applications, but, because this Connection Pooling
functionality has been removed from version 7, setting this property
will have no effect.
https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.0.0/com.ibm.mq.javadoc.doc/WMQJMSClasses/com/ibm/mq/jms/MQConnectionFactory.html#setUseConnectionPooling-boolean-
I think your best shot is to spring-ify(move to spring) your WAS application and then switch to Tomcat. Once you move to spring it should be a piece of cake to switch. It is supposed to be container independent. There are plenty of recipies online on how to migrate Java EE to spring applications. This excersise has been done for years(since spring exists:).
In the process you can also apply divide and conquere and end up with more then one app instead of monolith.
I have an application deployed in Websphere which should push a message in a queue implemented in JBoss using HornetQ. That message will then be consumed by an MDB within another application (on JBoss). Is that even possible?
In summary:
WAS (producer) -> JBoss (consumer)
I think yes because the protocol JMS is shared, but what are the details? should I load JBoss with MQ libraries or is it all in the way I refer to the JBoss queue from WAS?
Thank you so much.
If the MDB deployed on JBoss EAP is receiving a message from a local queue in HornetQ, then you do not need to deploy any MQ jars.
All you will need to do is write a MDB application and read the messages in your onMessage(Message msg) method. It should be really as simple as that.
You can see an example of a MDB in the jboss eap quick start . The HelloWorldQueueMDB.java class is the one you might be interested in. Follow the code in that class and modify the destination annotation value for your particular HornetQ queue name (from standalone-full.xml or standalone-full-ha.xml or the full or full-ha profile in your domain.xml file).
On a side note, JBoss EAP 6.1 is quite old. I would highly recommend upgrading to JBoss EAP 6.4.13 or later.
I am facing a strange issue after migrating my application from OC4J to WebLogic 10.3.6 server.
My application produces JMS TextMessage into OracleAQ queue. It was working fine.
But after deploying the application to WebLogic, produced text messages are getting stored in USER_DATA_TEXT_LOB (clob) column instead of USER_DATA_TEXT_VC (varchar2) column in underlying queue, whereas the USER_DATA_TEXT_LEN is very less (less than 1k chars).
As a consequence, consumer application is failing to dequeue the message and throwing the error: Payload is NULL.
Appreciate any help in this regard.
Update:
I have tried with jms BytesMessage and it is working as expected.
I suspect this is caused by the version of the aqapi.jar and the ojdbc.jar being not the same on your OC4J and weblogic servers.
Try replacing these jar files from your OC4J to your weblogic.
Some version will change type at 500 chars while other will switch at 4000.. I'm not sure which versions it is tho, but if the first one was working you can try switching the jar files.
Are there any good examples of using AMQP client in CMT/JTA environment? I know that AMQP supports transactional messaging, but I don't know how it aligns with JTA.
So far I have managed to setup Apache Qpid java broker and connect to it from a Java application using latest JBossTS (Narayana 5.0.0.M1) as standalone JTA. Basic tests showed that messages successfully appear in a queue when I commit TX and are properly ignored when I rollback. But I'm not sure whether this proves that I can safely use Qpid client in CMT.
There is a linkedin AMQP Group where it's said:
"There started a sub spec of AMQP 1.0 concerning distributed tx which was heavily influenced by Microsoft. Totally incompatible with JTA."
That might be reason why you (and me too) haven't found any example.
source: https://www.linkedin.com/groups/AMQP-JTA-1369617.S.5995685814774882304?trk=groups_most_popular-0-b-ttl&goback=%2Egmp_1369617
It's simple: I have an MDB and an EJB that sends messages to a topic (or queue). JBoss complains that the topic is not bound to the JNDI context.
I want to have the topic/queue to be automatically created at best, or at least to have a standard way to define it, per application (say, in ejb-jar/META-INF)
this question and this blogpost show us how to do it in an application server specific way. This surely works, but:
I want to use the #MessageDriven annotation
I want the setting not to be global for the application server
I want the setting to be portable
It seems impossible to do this, with JavaEE 5 at least.