Mule JMS Topic and ActiveMQ Configuration - mule

I am using Mule ESB to design a process whereby one can post a message to a topic. Subscribers will listen to the topic and receive messages. Each subscriber will act on the messages differently. The goal here is to have the ability to post a test message to the topic from HTTP for testing subscribers.
Here is how I have the JMS connection configured:
<!-- JMS Topic connector -->
<jms:activemq-connector name="jmsTopicConnection" specification="1.1" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ2" durable="true" numberOfConcurrentTransactedReceivers="2"/>
This is the flow:
<flow name="auditJMSServiceFlow">
<http:listener config-ref="HTTP" path="/Audit/Activity" responseStreamingMode="ALWAYS" doc:name="HTTP"/>
<set-variable variableName="#['id']" value="#[message.inboundProperties['id']]" doc:name="set dynamic id"/>
<set-payload value="===TOPIC===" doc:name="Set Payload" />
<request-reply storePrefix="mainFlow">
<jms:inbound-endpoint topic="Audit.Activity" connector-ref="jmsTopicConnection" doc:name="JMS Topic Audit.Activity" exchange-pattern="request-response" durableName="audit_activity">
<jms:transaction action="ALWAYS_BEGIN" />
<!-- Not required to explicitly have this element. Mule will put this in implicitly. -->
<!-- <jms:jmsmessage-to-object-transformer displayName="JmsMsg to Object"/> -->
</jms:inbound-endpoint>
</request-reply>
<json:object-to-json-transformer doc:name="transform JMS message to JSON"/>
<json:validate-schema schemaLocation="resource://AuditMsgSchema.json" doc:name="Validate Json Schema"/>
<component class="com.baml.panther.audit.service.impl.AuditServiceImpl" doc:name="Java"/>
<default-exception-strategy>
<commit-transaction exception-pattern="com.foo.ExpectedExceptionType"/>
<jms:outbound-endpoint queue="dead.letter" connector-ref="jmsConnection">
<jms:transaction action="JOIN_IF_POSSIBLE" />
</jms:outbound-endpoint>
</default-exception-strategy>
<logger message="=== #[message.payload] received #[org.mule.util.DateUtiles.getTimeStamp('dd-MM-yyyy_HH-mm-ss.SSS')]" level="INFO" doc:name="Logger"/>
When I am running through the test I get the following error:
Any suggestions would be greatly appreciated.
Russ

For the error: Your request-reply scope is missing an outbound endpoint. You only have the inbound-endpoint (jms:inbound-endpoint). You need to provide the outbound-endpoint as well.
<request-reply storePrefix="mainFlow">
<jms:inbound-endpoint topic="Audit.Activity" connector-ref="jmsTopicConnection" doc:name="JMS Topic Audit.Activity" exchange-pattern="request-response" durableName="audit_activity">
<jms:transaction action="ALWAYS_BEGIN" />
<!-- Not required to explicitly have this element. Mule will put this in implicitly. -->
<!-- <jms:jmsmessage-to-object-transformer displayName="JmsMsg to Object"/> -->
</jms:inbound-endpoint>
</request-reply>
Not sure what your aim there but if you put just a jms:outbound-enpoint (instead of the whole request-reply block), you can send a message to the JMS topic.

The problem is that you cannot put a message source as the first message processor in a request-reply. The request reply allows you a kind of synchronous call for async protocols like JMS.
If you want to send a message to the message broker at the point where you put the request-reply just put a JMS outbound-endpoint.
If what you want to do is consume a message from the JMS topic you have to put a JMS inbound endpoint as the first message processor in a flow.

Related

How to acknowledge the activemq message in mule using client acknowledge?

Below is my mule configuration, i want to acknowledge using client acknoledge , how can i do it?
<mule>
<jms:activemq-connector name="Active_MQ" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ" maxRedelivery="2" persistentDelivery="true"/>
<flow name="activemqFlow">
<file:inbound-endpoint path="D:\mule\input" responseTimeout="10000" doc:name="File"/>
<object-to-string-transformer doc:name="Object to String"/>
<set-property propertyName="fileName" value="#[message.inboundProperties.originalFilename]" doc:name="Property"/>
<jms:outbound-endpoint queue="logfilequeue" connector-ref="Active_MQ" doc:name="JMS">
<jms:transaction action="NONE"/>
</jms:outbound-endpoint>
</flow>
<flow name="JmsInboundFlow">
<jms:inbound-endpoint queue="logfilequeue" connector-ref="Active_MQ" doc:name="JMS">
<jms:client-ack-transaction action="ALWAYS_BEGIN"/>
</jms:inbound-endpoint>
<logger message="#[payload.toString()]" level="INFO" doc:name="Logger"/>
<file:outbound-endpoint path="D:\mule\output" responseTimeout="10000" doc:name="File" outputPattern="#[message.inboundProperties.fileName]"/>
</flow>
</mule>
Note: Be REALLY sure you want to use CLIENT_ACKNOWLEDGE it doesn't work like most people think. It ack's the current message AND all previous within the session. If you have parallel/threaded consumers this setting will inadvertently ack messages that aren't ready to be ack'd yet. ActiveMQ has a INDIVIDUAL_ACKNOWLEDGE which ack's just the single message.
JMS Spec 2.0 has feat requests to make this add'l ack mode a standard.
Try adding acknowledgementMode="CLIENT_ACKNOWLEDGE" in your JMS connector.
You can refer this question for more details
Mule jms with CLIENT_ACKNOWLEDGE mode? Message automatically consumed even though I didn't acknoeledge it

Mule ESB: JMS selector expression not working

I have a Mule integration that implements the pub-sub model. The publisher publishes the message to a topic and the subscriber is configured to receive the messages from this topic. I want to have this subscriber receive the messages only if a custom property named 'ENTITY_TYPE' has values either of the following: 'accounts', 'contacts' or 'cases'. Unfortunately this is not working (I mean the subscriber doesn't receive the message at all). Here is the code snippets:
Publisher:
AccountsFlow:
<set-property propertyName="ENTITY_TYPE" value="accounts" doc:name="Set Entity Type"/>
<jms:outbound-endpoint connector-ref="Active_MQ_Publisher" doc:name="Publish Accounts" topic="${activemq.sfdc.topicname}" tracking:enable-default-events="true"/>
ContactsFlow:
<set-property propertyName="ENTITY_TYPE" value="contacts" doc:name="Set Entity Type"/>
<jms:outbound-endpoint connector-ref="Active_MQ_Publisher" doc:name="Publish Contacts" topic="${activemq.sfdc.topicname}" tracking:enable-default-events="true"/>
CasesFlow:
<set-property propertyName="ENTITY_TYPE" value="cases" doc:name="Set Entity Type"/>
<jms:outbound-endpoint connector-ref="Active_MQ_Publisher" doc:name="Publish Cases" topic="${activemq.sfdc.topicname}" tracking:enable-default-events="true"/>
Subscriber:
<jms:inbound-endpoint connector-ref="Active_MQ_Subscriber" doc:name="JMS" tracking:enable-default-events="true" topic="${activemq.sfdc.topicname}">
<jms:selector expression="ENTITY_TYPE='accounts' OR ENTITY_TYPE='contacts' OR ENTITY_TYPE='cases'" />
</jms:inbound-endpoint>
<logger message="$$$: Entity Type = #[message.inboundProperties['ENTITY_TYPE']]" level="INFO" doc:name="Logger"/>
If I remove the 'jms:selector' element, then I do see the output in the logs:
2015-06-18 15:58:19,574 INFO o.m.a.p.LoggerMessageProcessor [[sfdcjob].AccountsContactsCasesSubscriberFlow.stage1.02] $$$: Entity Type = sfdc.locationheader
Here is the env details:
Mule Standalone: 3.6.2 (Enterprise Edition)
OS: Cent OS 7
Message Broker: Active MQ 5.11.1
JVM for both Mule & Active MQ: 1.7.0.75
I certainly need to set the filter and interested to receive only the messages whose message property is set to one of the values defined previously (accounts, contacts, cases). Any idea why the JMS selector not working?
Edit: I tried another way to set the entity type in the publisher as follows and that also didn't work.
<jms:outbound-endpoint connector-ref="Active_MQ_Publisher" doc:name="Publish Accounts" topic="${activemq.sfdc.topicname}" tracking:enable-default-events="true">
<message-properties-transformer doc:name="Message Properties" scope="outbound">
<add-message-property key="ENTITY_TYPE" value="accounts" />
</message-properties-transformer>
</jms:outbound-endpoint>

How to Intercept incoming call in Mule

Hi I am working with Mule Any Point platform i am using composite source which is listening from HTTP and JMS both. I want to identify the incoming call coming from HTTP or JMS and i want to print using the logger. How to do that ?
Try the following way of using logger inside your endpoints.
<composite-source doc:name="Composite Source">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP">
<logger message="Request coming from HTTP endpoint."></logger>
<set-variable value="HTTP" variableName="myVar"></set-variable>
</http:inbound-endpoint>
<jms:inbound-endpoint doc:name="JMS" queue="in">
<logger message="Request coming from JMS endpoint."></logger>
<set-variable value="JMS" variableName="myVar"></set-variable>
</jms:inbound-endpoint>
</composite-source>
In the flow when you have to chekc a condition, you can use the flow variable "myVar" to check whether the message came from HTTP or JMS endpoint.
Hope this helps.

Mule - mixing exchange patterns

I am trying to understand what is going one when i mix exchange patterns.
If i call a vm request-response inbound endpoint with a ones-way outbound endpoint, there is no error but it appears as though the flow is never run for example:
<flow name="main" doc:name="main" processingStrategy="asynchronous">
<poll frequency="60000">
<set-payload value="main"></set-payload>
</poll>
<set-variable value="xxx" variableName="var1"></set-variable>
<logger level="ERROR" message="MAIN1 #[flowVars.var1]" />
<vm:outbound-endpoint address="vm://vm" />
<logger level="ERROR" message="MAIN2 #[flowVars.var1]" />
</flow>
<flow name="p1">
<vm:inbound-endpoint address="vm://vm" exchange-pattern="request-response" />
<logger level="ERROR" message="PRIVATE #[flowVars.var1]" />
</flow>
</mule>
This configuration logs the following, but never prints 'PRIVATE xxx'.
ERROR 2014-03-26 13:22:35,794 [[test].main.stage1.01] org.mule.api.processor.LoggerMessageProcessor: MAIN1 xxx
ERROR 2014-03-26 13:22:35,812 [[test].main.stage1.01] org.mule.api.processor.LoggerMessageProcessor: MAIN2 xxx
INFO 2014-03-26 13:22:35,816 [[test].connector.VM.mule.default.dispatcher.01] org.mule.lifecycle.AbstractLifecycleManager: Initialising: 'connector.VM.mule.default.dispatcher.784920740'. Object is: VMMessageDispatcher
INFO 2014-03-26 13:22:35,817 [[test].connector.VM.mule.default.dispatcher.01] org.mule.lifecycle.AbstractLifecycleManager: Starting: 'connector.VM.mule.default.dispatcher.784920740'. Object is: VMMessageDispatcher
And if I mix them the other way around MAIN2 xxx never prints. Can someone explain what actually is going on here?
Mule docs state the following:
request-response:
When using request-response endpoints, messages are
delivered directly from an outbound vm endpoint to the inbound vm
endpoint that is listening on the same path. This delivery is blocking
and occurs in the same thread. If there is no inbound request-response
vm endpoint in the same Mule application listening on this path, then
dispatching of the message from the outbound endpoint will fail.
one-way:
When using one-way endpoints, messages are delivered to the
corresponding inbound endpoint via a queue. This delivery is
non-blocking. If there is no inbound one-way endpoint in the same Mule
application listening on this path, then, although dispatching of the
message will succeed, the message will remain in the queue. By
default, this queue is in memory, but it is also possible to configure
a persistent queue that will use the file system as its persistence
mechanism.
http://www.mulesoft.org/documentation/display/current/VM+Transport+Reference
I would guess the case with request-response outbound just remains waiting for a response, as the message gets dispatched and received contrary to the docs.
I don't mean to be rude, but It doesn't make sense to mix echange patterns this way. I believe one should never do something like this. In fact it's better to configure your exchange pattern on the vm endpoint globally, so that you have have consistent endpoints and you can't make mistakes.
<vm:endpoint name="vm-endp" path="vm-endp" exchange-pattern="request-response" />
<flow name="main" doc:name="main" processingStrategy="asynchronous">
<http:inbound-endpoint exchange-pattern="one-way" name="http-endpoint" host="localhost" port="2003" path="mule" doc:name="HTTP"/>
<set-variable variableName="var1" value="xxx" doc:name="XXX" />
<logger level="INFO" message="MAIN1 #[flowVars.var1]" />
<set-payload value="#[flowVars.var1]" />
<vm:outbound-endpoint ref="vm-endp" />
<logger level="INFO" message="MAIN2 #[flowVars.var1]" />
<logger level="INFO" message="PAYLOAD #[message.payloadAs(java.lang.String)]" />
</flow>
<!-- flowVars are FLOW VARIABLES, hence they're not accessible from multiple flows -->
<flow name="flow">
<vm:inbound-endpoint ref="vm-endp" />
<logger level="INFO" message="PRIVATE #[flowVars.var1]" />
<append-string-transformer message=" added to the payload" />
</flow>
It should output:
INFO [[VMtest].main.stage1.01] org.mule.api.processor.LoggerMessageProcessor: MAIN1 xxx
INFO [[VMtest].main.stage1.01] org.mule.lifecycle.AbstractLifecycleManager: Initialising: 'connector.VM.mule.default.dispatcher.1221995064'. Object is: VMMessageDispatcher
INFO [[VMtest].main.stage1.01] org.mule.lifecycle.AbstractLifecycleManager: Starting: 'connector.VM.mule.default.dispatcher.1221995064'. Object is: VMMessageDispatcher
INFO [[VMtest].main.stage1.01] org.mule.api.processor.LoggerMessageProcessor: PRIVATE null
INFO [[VMtest].main.stage1.01] org.mule.api.processor.LoggerMessageProcessor: MAIN2 xxx
INFO [[VMtest].main.stage1.01] org.mule.api.processor.LoggerMessageProcessor: PAYLOAD xxx added to the payload

Mule flow with Jms connector, Threads blocking in dynamic outbound endpoint

I have a jms connector, i am receiving message from a queue processing the message in a flow, calling db to get the data based on some ids in the message and writing response output to files, i am using dynamic outbound endpoints to decide output location.
<jms:connector name="tibco" numberOfConsumers="20" ..... >
.....
</jms:connector>
<flow name="realtime" doc:name="ServiceId-8">
<jms:inbound-endpoint queue="${some.queue}" connector-ref="tibco" doc:name="JMS">
<jms:transaction action="ALWAYS_BEGIN"/>
</jms:inbound-endpoint>
<processor ref="proc1"></processor>
<processor ref="proc2"></processor>
<component doc:name="Java">
<spring-object bean="comp1"/>
</component>
<processor ref="proc3"></processor>
<collection-splitter doc:name="Collection Splitter"/>
<processor ref="endpointprocessor"></processor>
<foreach collection="#[message.payload.consumerEndpoints]" counterVariableName="endpoints" doc:name="Foreach">
<when expression="#[consumerEndpoint.getOutputType().equals('txt') and consumerEndpoint.getChannel().equals('file')]">
<processor-chain>
<file:outbound-endpoint path="#[consumerEndpoint.getPath()]" outputPattern="#[consumerEndpoint.getClientId()]-#[attributes['eventId']]%#[consumerEndpoint.getTicSeedCount()]-#[attributes['dateTime']].tic" responseTimeout="10000" doc:name="File"/>
</processor-chain>
</when>
<when expression="#[consumerEndpoint.getOutputType().equals('txt') and consumerEndpoint.getChannel().equals('ftp')]">
<processor-chain>
<ftp:outbound-endpoint path="#[consumerEndpoint.getPath()]" outputPattern="#[consumerEndpoint.getClientId()]-#[attributes['eventId']]%#[consumerEndpoint.getTicSeedCount()]-#[attributes['dateTime']].tic" host="#[consumerEndpoint.getHost()]" port="#[consumerEndpoint.getPort()]" user="#[consumerEndpoint.getChannelUser()]" password="#[consumerEndpoint.getChannelPass()]" responseTimeout="10000" doc:name="FTP"/>
</processor-chain>
</when>
</choice>
</foreach>
<rollback-exception-strategy doc:name="Rollback Exception Strategy">
<processor ref="catchExceptionCustomHandling"></processor>
</rollback-exception-strategy>
</flow>
Above is not complete flow. i pasted the important parts to understand.
Question 1. As i have not defined any thread strategy at any level, and connector has numberOfConsumers="20", if i drop 20 messages in queue how many threads will start.
prefetch size in the jms queue is set to 20.
Question 2: Do i need to configure threading strategy at receiver end and/or at flow level.
some time when the load is very high(let say 15k msgs in queue in a minute) i see message processing gets slow and thread dump shows some thing like below:
"TIBCO EMS Session Dispatcher (7905958)" prio=10 tid=0x00002aaadd4cf000 nid=0x3714 waiting for monitor entry [0x000000004af1e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at org.mule.endpoint.DynamicOutboundEndpoint.createStaticEndpoint(DynamicOutboundEndpoint.java:153)
- waiting to lock <0x00002aaab711c0e0> (a org.mule.endpoint.DynamicOutboundEndpoint)
Any help and pointers will be appreciated.
Thanks-
Message processing is getting slow because of dynamic endpoint, I see thread congestion when dynamic outbound endpoint is created and used. I was using mule 3.3.x and after looking at mule 3.4.x code i realized that dynamic outbound endpoint creation is handled more appropriately. upgraded to 3.4 and the issue is almost gone.