WSO2 CEP IBM MQ and transport.jms.ConcurrentConsumers - performance

I have a WSO2 CEP configured with Input Event Adaptor set to listen on a IBM WebSphere MQ queue. Below there is a conf in xml:
<inputEventAdaptor name="WEBSPHEREMQ" statistics="disable" trace="disable" type="jms" xmlns="http://wso2.org/carbon/eventadaptormanager">
<property name="java.naming.provider.url">file:/opt/bindings</property>
<property name="transport.jms.SubscriptionDurable">false</property>
<property name="java.naming.factory.initial">com.sun.jndi.fscontext.RefFSContextFactory</property>
<property name="transport.jms.ConnectionFactoryJNDIName">MQ_JMS_MANAGER</property>
<property name="transport.jms.DestinationType">queue</property>
</inputEventAdaptor>
and an event builder with queue set:
<from eventAdaptorName="WEBSPHEREMQ" eventAdaptorType="jms">
<property name="transport.jms.Destination">MSCRM_IN_JMS_QUEUE</property>
</from>
I want to increase transport.jms.ConcurrentConsumers to speed up CEP performance results. Where do I need to put this parameter? I have tried in event adaptor and in event builder but it doesn't work.
Thanks a lot for any help!:)
Peter

Sorry at the moment, there is no any way to pass this property out of the box to jms adaptor. But I strongly believe this is a good addition for jms adaptor. We are doing some improvements related to this by aiming next release.. I have created a jira [1] to track this..
[1] https://wso2.org/jira/browse/CEP-884
you have two option at the moment, improve the current input jms adaptor by fixing in the source or write a custom jms adaptor for you need..
Thanks,Mohan

Related

In Mule 4 using JMS Connector how to remove the RFH Header

I am using JMS Connector to connect to IBM MQ. If I use IBM MQ Connector I have option (targetClient="NO_JMS_COMPLIANT") to disable RFH Header from the message. How can I achieve the same thing using the JMS Connector. My JMS config looks like below
<jms:config name="JMS_Config" doc:name="JMS Config" doc:id="b675becf-06f3-4847-bb95-4f468d5353ea" >
<jms:generic-connection specification="JMS_2_0" connectionFactory="WMQ_ConnectionFactory" />
</jms:config>
Connection Factory looks like this:
<bean id="WMQ_ConnectionFactory" class="com.ibm.mq.jms.MQConnectionFactory" name="WMQ_ConnectionFactory">
<property name="transportType" value="1" />
<property name="hostName" value="MQ-SLQ01"/>
<property name="port" value="1414"/>
<property name="queueManager" value="SLQ01"/>
<property name="channel" value="*******"/>
</bean>
JMS Connector config looks like this:
<jms:publish-consume doc:name="Publish consume" doc:id="b1d40cc6-deb0-42f0-aa50-4b230d843794" config-ref="JMS_Config" destination="P2.REQUEST" sendCorrelationId="ALWAYS">
<jms:message >
<jms:reply-to destination="P2.REPLY" />
</jms:message>
</jms:publish-consume>
I have tried adding request queue name with P2.REQUEST?targetClient=1. I could not see any changes.
I doubt the JMS connector allows to select a non-JMS compatible mode that is specific to a broker (IBM MQ). It a generic connector which provides no broker specific features. You should be using the IBM MQ connector for that that already provides that specific feature.
And alternate action you could take would be to disable the RFH2 header by using a setting on the queue.
ALTER QLOCAL(P2.REQUEST) PROPCTL(NONE)
This will strip all properties (RFH2 header) off the message before delivering it to any application that doesn't supply a message handle.

How do I configure an Spring message listener (MDP) to have one instance across a cluster

I have a spring message listener configured with
<bean id="processListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="1"/>
<property name="clientId" value="process-execute"/>
<property name="connectionFactory" ref="topicConnectionFactory"/>
<property name="destination" ref="processExecuteQueue"/>
<property name="messageListener" ref="processExecuteListener"/>
</bean>
This is running on a cluster with 2 nodes. I see that it's creating 1 consumer per node rather than 1 per cluster. They're both configured with the above xml so they have the same clientId. Yet, when 2 notifications are posted to the queue, both of the listeners are running, each gets a notification, and both execute in parallel. This is a problem because the notifications need to be handled sequentially.
I can't seem to find out how to make it have only one message listener per cluster rather than per node.
I solved the problem by having the jms queue block the next consumer until the previous returned. This is a feature in the weblogic server I'm using called Unit of Order. The documentation says you just need to enable it on the queue (I used hash). However, I found that I needed to enable it on the connection factory as well and set a default name. Now I see an MDP per node but 1 waits for 2 to complete before processing and vice versa. Not the solution I intended but it's working nontheless. While oracle specific, it's actually slightly better than a single MDP solution.
Note: I did not set the unit of order name in the spring jmstemplate producer as I do not know if that's possible. I have weblogic setting a default name when none is provided by the producer.

Publish subscribe implementation with Spring JMS

I have a JMS queue implementation with JmsTemplate. I want to have more than one listener when a message is put in the queue, i.e. I want to use topic instead of queue.
I have configuration without JMS namespacing. What are the changes that need to be made to have multiple listeners listen on a topic when someone sends a message in a topic.
I guess you are probably using DefaultMessageListenerContainer. Just to be sure, you want that several individual components receive the same message (i.e. you don't want to process messages in parallel).
Assuming I got this right and component A and compoent B should receive the same message, you simply create two DefaultMessageListenerContainer instance on the same topic and you set the pubSubDomain property to true. Make sure you haven't set any concurrency on the listener container, or better yet, set the concurrency to 1 to make that explicit.
This would give something like
<bean id="listener1"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="pubSubDomain" value="true"/>
<property name="concurrency" value="1"/>
<property name="destinationName=" value="...."/> <!-- topic name -->
<property name="messageListener" ref="...."/>
</bean>
Then you should create a similar bean for the second component.

wso2esb & WMQ 7.5

I've a problem: I need to send messages (only send) to IBM MQ 7.5. In my case I have a lot of dynamic queues on several managers, so it isn't possible to send messages via jndi (like described in wso2 doc).
IBM MQ has a jms extension where I can send messages directly to queue manager and queue by specifying in q name (for example "queue://QM1/qName1"). But to do this I need to specify Connection Factory like these
<bean id="mqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="port" value="${mq.port}"/>
<property name="transportType" value="${mq.transportType}"/>
<property name="hostName" value="#{props['host']}"/>
<property name="queueManager" value="#{props['mq.manager']}"/>
<property name="channel" value="#{props['mq.chanel']}"/>
</bean>
But I doesn't find how I can specify factory in wso2esb. Can you help me?
The obvious question here is "If you are using dynamic queues, how do you know the name of the queue that you want to send to?"
The obvious answer to that question is "It's in the Reply-To fields."
Assuming that the message just received is in rqstMsg and that you want to send replyMsg, it might look something like this:
MessageProducer replyProducer = session.createProducer((Queue rqstMsg.getJMSReplyTo());
// create replyMsge here
replyProducer.send(replyMsg);
You specified "only send" so there's a possibility you are not replying to request messages. (Although if that is the case, how you are determining the dynamic queue names outside the context of a request message is an interesting question.) If in fact you do not have a message with ReplyTo fields set, you can just specify the fully-qualified name of the destination:
MQQueue destQ = new MQQueue(rQMName, rName);
Destination dest = (Destination) destQ;
You would set the remote QMgr name in rQMName and the remote queue name in rName, then use the destination as normal.

ACTIVEMQ - How can subscriber receive topic messages when started after publisher?

In my program, I have two modules :- Publisher and Subscriber which communicate via Topic.
I understand that in order to receive messages by subscriber, it should be started before publisher. But there may be a scenario where the subscriber goes down for some reason and needs to be restarted. Is there any way, by which if I start the Subscriber after Publisher, then also it should be able to receive message?
Adding a code example by using spring DMLC and durable subscribers. It's harder to achieve this with a plain JMSTemplate (you tagged this, so I guess you are using JMS Templates to receive?), since you have to grab the session from the template and create the durable consumer yourself. This is automatically handled for you if you use the DMLC approach.
<bean id="myDurableConsumer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="myCf" />
<property name="sessionTransacted" value="true" />
<property name="subscriptionDurable" value="true"/>
<property name="durableSubscriberName" value="myDurableNameThatIsUniqueForThisInstance" />
<property name="destinationName" value="someTopic" />
<property name="messageListener" ref="myListener" />
< /bean>
If you are only interested in the disconnect-reconnect scenario, I think a durable subscriber is what you are looking for.
http://activemq.apache.org/how-do-durable-queues-and-topics-work.html
In general if you want to account for a subscriber going offline and returning without missing any messages you would use JMS Durable Subscriptions. This allows your subscriber to receive any messages it missed while offline. Note that the caveat here is that is needs to have subscribed once first before it will start to collect offline messages.
Besides the standard JMS Durable consumer model ActiveMQ also provides the retroactive consumer. Another possibility is Virtual destinations.

Resources