Is there a way to instruct Mule object-to-json-transformer component to not include null properties into the JSON produced?
By default it produces something like this for null object properties:
"value": null
Thank you,
ps. just wanna clarify that I'm looking for a way to configure this in Mule, not by using the classes jackson annotations.
Ok, I've found the answer.
Mule object-to-json transformer is ignoring jackson annotations.
Instead, you need to define a customized object mapper bean like this:
<spring:beans>
<spring:bean id="Bean" name="NonNullMapper" class="org.codehaus.jackson.map.ObjectMapper">
<spring:property name="SerializationInclusion">
<spring:value type="org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion">NON_NULL</spring:value>
</spring:property>
</spring:bean>
</spring:beans>
and then reference the bean in the transformer like this:
<json:object-to-json-transformer doc:name="Object to JSON" mapper-ref="NonNullMapper"/>
Note, that this approach only works with custom java classes.
Goes with this, #JsonSerialize (include = JsonSerialize.Inclusion.NON_NULL), simply place it in its class. The library to import is import org.codehaus.jackson.map.annotate.JsonSerialize.
You can configure the ObjectMapper that the json transformers use like so:
<spring:beans>
<spring:bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
<spring:bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<spring:property name="targetObject" ref="jacksonObjectMapper" />
<spring:property name="targetMethod" value="configure" />
<spring:property name="arguments">
<spring:list>
<spring:value>WRITE_NULL_VALUES</spring:value>
<spring:value>false</spring:value>
</spring:list>
</spring:property>
</spring:bean>
</spring:beans>
<flow name="json" >
...
<json:object-to-json-transformer mapper-ref="jacksonObjectMapper" />
</flow>
Or if you are using a Map:
<spring:beans>
<spring:bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
<spring:bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<spring:property name="targetObject" ref="jacksonObjectMapper" />
<spring:property name="targetMethod" value="configure" />
<spring:property name="arguments">
<spring:list>
<spring:value>WRITE_NULL_MAP_VALUES</spring:value>
<spring:value>false</spring:value>
</spring:list>
</spring:property>
</spring:bean>
</spring:beans>
<flow name="json" >
...
<json:object-to-json-transformer mapper-ref="jacksonObjectMapper" />
</flow>
Related
I m implementing mule ESB 3.9 to consume messages from active mq.
I have around 15 domain components to which it actually orchestrates to reach the final destination
I have configured a connection pool for jms and am using numberofconsumers as 32 and maximum thread in reciever as 500.
But what I see is until 4 messages per second the requests sent by jmeter is fine. But if I increase to 5 msgs per second then I find the request sent by jms averages to around 3 msgs per second slowly..
Any thought on how to configure the number of consumers and reciever thread ?
My target is 10 messages per second and also all my 15 components takes only 30 milli seconds each at max to process .so processing time by those components is good...yet I see the total throughput is around 3 seconds at times and mostly its because messages are not being picked immediately.
Please suggest
Activemq xml
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" >
<!-- The constantPendingMessageLimitStrategy is used to prevent
slow topic consumers to block producers and affect other consumers
by limiting the number of messages that are retained
For more information, see:
http://activemq.apache.org/slow-consumer-handling.html
-->
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="10000"/>
</pendingMessageLimitStrategy>
<slowConsumerStrategy>
<abortSlowConsumerStrategy/>
</slowConsumerStrategy>
</policyEntry>
<!--Mahesh added start-->
<policyEntry queue=">" >
<slowConsumerStrategy>
<abortSlowConsumerStrategy/>
</slowConsumerStrategy>
</policyEntry>
<!--Mahesh added end-->
</policyEntries>
</policyMap>
</destinationPolicy>
<managementContext>
<managementContext createConnector="false"/>
</managementContext>
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage percentOfJvmHeap="90" />
</memoryUsage>
<storeUsage>
<storeUsage limit="5 gb"/>
</storeUsage>
<tempUsage>
<tempUsage limit="5 gb"/>
</tempUsage>
</systemUsage>
</systemUsage>
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
Other information on Mule ESB
I am using a prefetch of 1 message
No of consumers are 32 and receiver threads are 500
mule-config ---->
<spring:beans>
<context:component-scan base-package="com.test.esb.orm.db" />
<spring:import resource="classpath*:applicationContext.xml" />
<spring:import resource="classpath*:test-orm-beans.xml" />
<spring:import resource="mule-domain-spring.xml"/>
</spring:beans>
<db:generic-config name="Generic_Database_Configuration"
dataSource-ref="testDataSource"
doc:name="Generic Database Configuration"/>
<db:generic-config name="Generic_TrackTraceDatabase_Configuration"
dataSource-ref="testTrackTraceDataSource"
doc:name="Generic Database Configuration for Track Trace"/>
<!-- ********************* ESB Gateway Configurations ******************************** -->
<http:listener-config name="test-Shared-http-listener" host="${domain.gateway.host}" port="${domain.gateway.port}" doc:name="HTTP Listener connector for ESB Gateway (From ui)">
<http:worker-threading-profile maxThreadsActive="64"
poolExhaustedAction="WAIT"
threadWaitTimeout="30000" />
</http:listener-config>
<jms:activemq-connector name="com.test.esb.trans.jmsConnector"
username="${domain.amq.user.id}" password="${domain.amq.user.password}"
connectionFactory-ref="pooledConnectionFactory"
numberOfConsumers="16" acknowledgementMode="AUTO_ACKNOWLEDGE"
validateConnections="true"
persistentDelivery="true"
doc:name="AMQ Connector For Domain Routing Services"
specification="1.1">
<receiver-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT"/>
<dispatcher-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT"/>
<reconnect count="15" frequency="5000" blocking="true"/>
</jms:activemq-connector>
<jms:activemq-connector name="com.test.esb.domain.jmsConnector"
username="${domain.amq.user.id}" password="${domain.amq.user.password}"
connectionFactory-ref="pooledConnectionFactory"
numberOfConsumers="16" acknowledgementMode="AUTO_ACKNOWLEDGE"
validateConnections="true"
persistentDelivery="false"
doc:name="AMQ Connector For Domain Routing Services"
specification="1.1">
<receiver-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT"/>
<dispatcher-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT"/>
<reconnect count="15" frequency="5000" blocking="true"/>
</jms:activemq-connector>
<jms:activemq-connector name="com.test.esb.domain.orchestrator.jmsConnector"
username="${domain.amq.user.id}" password="${domain.amq.user.password}"
connectionFactory-ref="pooledConnectionFactory"
numberOfConsumers="16" acknowledgementMode="AUTO_ACKNOWLEDGE"
validateConnections="true"
persistentDelivery="true"
doc:name="AMQ Connector For Domain Routing Services"
specification="1.1">
<receiver-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT"/>
<dispatcher-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT"/>
<reconnect count="15" frequency="5000" blocking="true"/>
</jms:activemq-connector>
<jms:activemq-connector name="com.test.esb.interface2.jmsConnector"
username="${domain.amq.user.id}" password="${domain.amq.user.password}"
connectionFactory-ref="pooledConnectionFactory"
validateConnections="true"
numberOfConcurrentTransactedReceivers="16"
persistentDelivery="false"
doc:name="AMQ Connector for interface2 Interface"
specification="1.1">
<receiver-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT" threadWaitTimeout="30000"/>
<dispatcher-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT"/>
<reconnect count="15" frequency="5000" blocking="true"/>
</jms:activemq-connector>
<jms:activemq-connector name="com.test.esb.destination.router.jmsConnector"
username="${domain.amq.user.id}" password="${domain.amq.user.password}"
connectionFactory-ref="pooledConnectionFactory"
validateConnections="true"
numberOfConcurrentTransactedReceivers="8"
persistentDelivery="false"
doc:name="AMQ Connector for DestinationRouter"
specification="1.1">
<receiver-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT"/>
<dispatcher-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT"/>
<reconnect count="15" frequency="5000" blocking="true"/>
</jms:activemq-connector>
<jms:activemq-connector name="com.test.esb.dlq.jmsConnector"
username="${domain.amq.user.id}" password="${domain.amq.user.password}"
connectionFactory-ref="pooledConnectionFactory"
validateConnections="true"
numberOfConcurrentTransactedReceivers="16"
persistentDelivery="false"
doc:name="AMQ Connector for Dead Letter Queue"
specification="1.1">
<receiver-threading-profile maxThreadsActive="500" poolExhaustedAction="WAIT" threadWaitTimeout="30000"/>
<reconnect count="15" frequency="5000" blocking="true"/>
</jms:activemq-connector>
mule-spring config---->
<spring:bean id="domainRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<spring:property name="maximumRedeliveries" value="5" />
<spring:property name="initialRedeliveryDelay" value="500" />
<spring:property name="maximumRedeliveryDelay" value="10000" />
<spring:property name="useExponentialBackOff" value="false" />
<spring:property name="backOffMultiplier" value="3" />
</spring:bean>
<!-- ActiveMQ Connection factory -->
<spring:bean id="domainConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory" lazy-init="true">
<spring:property name="brokerURL"
value="tcp://192.0.0.0:61616?jms.prefetchPolicy.all=1" />
<spring:property name="redeliveryPolicy" ref="domainRedeliveryPolicy" />
</spring:bean>
<!-- amqExceptionConnectionFactory Connection factory -->
<spring:bean id="amqExceptionConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory" lazy-init="true">
<spring:property name="brokerURL"
value="failover:(${domain.amq.failover.url}?jms.prefetchPolicy.all=50)" />
<spring:property name="redeliveryPolicy" ref="domainRedeliveryPolicy" />
</spring:bean>
<spring:bean id="pooledConnectionFactory" class="org.apache.activemq.jms.pool.PooledConnectionFactory" >
<spring:property name="connectionFactory" ref="domainConnectionFactory"/>
<spring:property name="maxConnections" value="10000" />
<spring:property name="maximumActiveSessionPerConnection" value="10000" />
</spring:bean>
<spring:bean id="trackTraceRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<spring:property name="maximumRedeliveries" value="5" />
<spring:property name="initialRedeliveryDelay" value="500" />
<spring:property name="maximumRedeliveryDelay" value="10000" />
<spring:property name="useExponentialBackOff" value="false" />
<spring:property name="backOffMultiplier" value="3" />
</spring:bean>
<spring:bean id="trackTraceConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory" lazy-init="true">
<spring:property name="brokerURL"
value="failover:(${domain.amq.failover.url})" />
<!-- value="tcp://${domain.amq.host}:${domain.amq.port}" /> -->
<spring:property name="redeliveryPolicy" ref="trackTraceRedeliveryPolicy" />
</spring:bean>
<spring:bean id="interface2ConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory" lazy-init="true">
<spring:property name="brokerURL"
value="tcp://192.0.0.0:61616?jms.prefetchPolicy.all=1" />
<!-- value="tcp://${domain.amq.host}:${domain.amq.port}" /> -->
<spring:property name="redeliveryPolicy" ref="interface2RedeliveryPolicy" />
</spring:bean>
<spring:bean id="interface2RedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<spring:property name="maximumRedeliveries" value="5" />
<spring:property name="initialRedeliveryDelay" value="500" />
<spring:property name="maximumRedeliveryDelay" value="10000" />
<spring:property name="useExponentialBackOff" value="false" />
<spring:property name="backOffMultiplier" value="3" />
</spring:bean>
<!-- ********************* Destination Router Configurations ******************************** -->
<!-- ActiveMQ Connection factory for destination Router -->
<spring:bean id="destinationRouterConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory" lazy-init="true">
<spring:property name="brokerURL"
value="tcp://192.0.0.0:61616?jms.prefetchPolicy.all=1" />
<!-- value="tcp://${domain.amq.host}:${domain.amq.port}" /> -->
<spring:property name="redeliveryPolicy"
ref="destinationRouterRedeliveryPolicy" />
</spring:bean>
<spring:bean id="destinationRouterRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<spring:property name="maximumRedeliveries" value="5" />
<spring:property name="initialRedeliveryDelay" value="500" />
<spring:property name="maximumRedeliveryDelay" value="10000" />
<spring:property name="useExponentialBackOff" value="false" />
<spring:property name="backOffMultiplier" value="3" />
</spring:bean>
<!-- ********************* Dead Letter Queue (DLQ) Configurations ******************************** -->
<!-- ActiveMQ Connection factory for Dead Letter Queue -->
<spring:bean id="dlqConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory" lazy-init="true">
<spring:property name="brokerURL"
value="failover:(${domain.amq.failover.url})" />
<spring:property name="redeliveryPolicy" ref="dlqRedeliveryPolicy" />
</spring:bean>
<spring:bean id="dlqRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<spring:property name="maximumRedeliveries" value="5" />
<spring:property name="initialRedeliveryDelay" value="500" />
<spring:property name="maximumRedeliveryDelay" value="10000" />
<spring:property name="useExponentialBackOff" value="false" />
<spring:property name="backOffMultiplier" value="3" />
</spring:bean>
numberOfConsumers is the atribute that determines the number of client threads if the endpoing is using transactions. If the endpoint is in a transaction then you need to use numberOfConcurrentTransactedReceivers instead.
You should really remove the <dispatcher-threading-profile> and <receiver-threading-profile> configurations. 500 threads per JMS configuration is a lot for your system, it is a lot of resources if they are created, and will not help for this use case at all. You should set these values only because of some real reason.
Try to capture a thread dump when the processing is slow to analyze what are the threads doing. That should point to the root cause.
Reference: https://help.mulesoft.com/s/article/JMS-Usage-of-numberOfConsumers-and-numberOfConcurrentTransactedReceivers
can you inject a value from the config params file in to the splitter group attribute? if so, what is the proper way of doing it? thanks!
I've tried,
<split streaming="true" >
<tokenize token="\n" group="{{noOfLines}}" />
<log message="Split Group Body: ${body}"/>
<to uri="bean:extractHeader" />
<to id="acceptedFileType" ref="pConsumer" />
</split>
<split streaming="true" >
<tokenize token="\n" group={{noOfLines}} />
<log message="Split Group Body: ${body}"/>
<to uri="bean:extractHeader" />
<to id="acceptedFileType" ref="pConsumer" />
</split>
what am I doing wrong?
ERROR: 'Open quote is expected for attribute "group" associated with an element type "tokenize".
<tokenize token="\n" group="<simple>${properties:noOfLines:500}</simple>" />
ERROR: 'The value of attribute "group" associated with an element type "tokenize" must not contain the '<' character.'
<tokenize token="\n" group="${properties:noOfLines:500}" />
Caused by: org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: '${properties:noOfLines:500}' is not a valid value for 'integer'.
my quest for info and answers didn't go deep enough. I found this was already encounted and answered by Claus Ibsen. Please see if you run in to this need.
Validation error with integer property (camel)
http://camel.apache.org/using-propertyplaceholder.html
under section "Using Property Placeholders for Any Kind of Attribute in the XML DSL"
here is what I did following these instructions.
added property prefix namespace
xmlns:prop="http://camel.apache.org/schema/placeholder"
then modified the tokenize attribute
<tokenize token="\n" prop:group="noOfLines" />
I'm using the property placeholder
<cm:property-placeholder persistent-id="com.digital.passthru.core" />
this works like a charm. thank you Claus.
this is what worked for me.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:prop="http://camel.apache.org/schema/placeholder"
xmlns:camel="http://camel.apache.org/schema/blueprint"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint
http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<cm:property-placeholder persistent-id="com.ge.digital.passthru.core" />
<bean id="deadLetterErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder">
<property name="deadLetterUri" value="${deadLetterQueue}"/>
<property name="redeliveryPolicy" ref="redeliveryPolicyConfig"/>
<property name="useOriginalMessage" value="true" />
</bean>
<bean id="redeliveryPolicyConfig" class="org.apache.camel.processor.RedeliveryPolicy">
<property name="maximumRedeliveries" value="3"/>
<property name="redeliveryDelay" value="5000" />
</bean>
...
<camelContext
id="com.ge.digital.passthru.coreCamelContext"
trace="true"
xmlns="http://camel.apache.org/schema/blueprint"
allowUseOriginalMessage="false"
streamCache="true"
errorHandlerRef="deadLetterErrorHandler" >
...
<route
id="core.predix.accept.file.type.route"
autoStartup="true" >
<from uri="{{fileEntranceEndpoint}}" />
<convertBodyTo type="java.lang.String" />
<split streaming="true" strategyRef="csvAggregationStrategy">
<tokenize token="\n" />
<process ref="toCsvFormat" /> <!-- passthru only we do not allow embedded commas in numeric data -->
</split>
<log message="CSV body: ${body}" loggingLevel="INFO"/>
<choice>
<when>
<simple>${header.CamelFileName} regex '^.*\.(csv|CSV|txt|gpg)$'</simple>
<log message="${file:name} accepted for processing..." />
<choice>
<when>
<simple>${header.CamelFileName} regex '^.*\.(CSV|txt|gpg)$'</simple>
<setHeader headerName="CamelFileName">
<!-- <simple>${file:name.noext}.csv</simple> --> <!-- file:name.noext.single -->
<simple>${file:name.noext.single}.csv</simple>
</setHeader>
<log message="${file:name} changed file name." />
</when>
</choice>
<split streaming="true" >
<tokenize token="\n" prop:group="noOfLines" />
<log message="Split Group Body: ${body}"/>
<to uri="bean:extractHeader" />
<to id="acceptedFileType" ref="predixConsumer" />
</split>
<to uri="bean:extractHeader?method=cleanHeader"/>
</when>
<otherwise>
<log message="${file:name} is an unknown file type, sending to unhandled repo." loggingLevel="INFO" />
<to uri="{{unhandledArchive}}" />
</otherwise>
</choice>
</route>
...
and noOfLines is a property
now there is an order to all this as I found out while doing this also.
please go to the link below for the Camel ordering of components in XML DSL
Camel DataFormat Jackson using blueprint XML DSL throws context exception
I have a very simple flow in the Mule, it listens to an ActiveMQ queue and if the message from the queue contains the string "fail" an exception is thrown. Without an XA transaction, everything works ok. The message is redelivered after 5 seconds, the next time after some seconds more. After 5 redeliveries the message is moved to the dead letter queue.
With XA transactions the message is redelivered immediately 5 times and then moved to the dead letter queue. How can I tell Mule or ActiveMQ to wait the RedeliveryDelay?
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting"
xmlns:jbossts="http://www.mulesoft.org/schema/mule/jbossts" xmlns:jms="http://www.mulesoft.org/schema/mule/jms"
xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.6.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd
http://www.mulesoft.org/schema/mule/jbossts http://www.mulesoft.org/schema/mule/jbossts/current/mule-jbossts.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd">
<spring:beans>
<!-- Redelivery Policy -->
<spring:bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<spring:property name="maximumRedeliveries" value="5" />
<spring:property name="initialRedeliveryDelay" value="5000" />
<spring:property name="redeliveryDelay" value="5000" />
<spring:property name="useExponentialBackOff" value="true" />
<spring:property name="backOffMultiplier" value="1.5" />
</spring:bean>
<!-- ActiveMQ Connection factory -->
<spring:bean id="amqXAFactory"
class="org.apache.activemq.ActiveMQXAConnectionFactory" lazy-init="true"
name="amqXAFactory">
<spring:property name="brokerURL"
value="tcp://localhost:61616" />
<spring:property name="redeliveryPolicy" ref="redeliveryPolicy" />
</spring:bean>
</spring:beans>
<jbossts:transaction-manager doc:name="JBoss Transaction Manager">
<property key="com.arjuna.ats.arjuna.coordinator.defaultTimeout"
value="47" /><!-- this is in seconds -->
<property key="com.arjuna.ats.arjuna.coordinator.txReaperTimeout"
value="108000" /><!-- this is in milliseconds -->
</jbossts:transaction-manager>
<jms:activemq-connector name="Active_MQconnectorMessages"
specification="1.1" validateConnections="true" doc:name="Active MQ for XA"
persistentDelivery="true" connectionFactory-ref="amqXAFactory"
numberOfConsumers="1" maxRedelivery="5">
<reconnect-forever frequency="10000" />
</jms:activemq-connector>
<flow name="xatestFlow">
<jms:inbound-endpoint queue="xa.test" doc:name="JMS"
connector-ref="Active_MQconnectorMessages">
<xa-transaction action="ALWAYS_BEGIN" />
</jms:inbound-endpoint>
<logger message="Message from queue: #[payload]" level="INFO"
doc:name="Logger" />
<scripting:component doc:name="fail if payload contains fail">
<scripting:script engine="Groovy"><![CDATA[if (payload.contains("fail")) {
throw new IllegalArgumentException("Failed...")
}
]]></scripting:script>
</scripting:component>
<logger message="Message is ready" level="INFO" doc:name="Logger" />
</flow>
</mule>
It took some time, but I discovered the solution. There are two types of configuration, the server side in ActiveMQ and the client side.
In the client redeliveryPolicy I changed maximumRedeliveries to 0. On the server I created a redeliveryPlugin in the activemq.xml:
<broker ....>
......
<plugins>
<redeliveryPlugin fallbackToDeadLetter="true" sendToDlqIfMaxRetriesExceeded="true">
<redeliveryPolicyMap>
<redeliveryPolicyMap>
<redeliveryPolicyEntries>
<!-- a destination specific policy -->
<redeliveryPolicy
queue="amm.input.to.router" maximumRedeliveries="3"
redeliveryDelay="7000"
initialRedeliveryDelay="5000"
useCollisionAvoidance="true"
/>
</redeliveryPolicyEntries>
<!-- the fallback policy for all other destinations -->
<defaultEntry>
<redeliveryPolicy
maximumRedeliveries="4"
useExponentialBackOff="true"
initialRedeliveryDelay="10000"
redeliveryDelay="5000"
useCollisionAvoidance="true"
backOffMultiplier="1.5"
maximumRedeliveryDelay="93600000" />
</defaultEntry>
</redeliveryPolicyMap>
</redeliveryPolicyMap>
</redeliveryPlugin>
</plugins>
</broker>
Now it is ActiveMQ server that takes care of the redeliveries, not the client.
See http://activemq.apache.org/message-redelivery-and-dlq-handling.html
Here's the my mule app xml config
<mule xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:quartz="http://www.mulesoft.org/schema/mule/quartz"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
xmlns:test="http://www.mulesoft.org/schema/mule/test"
xmlns:file="http://www.mulesoft.org/schema/mule/file"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/quartz http://www.mulesoft.org/schema/mule/quartz/current/mule-quartz.xsd
http://www.mulesoft.org/schema/mule/test http://www.mulesoft.org/schema/mule/test/3.6/mule-test.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.6/mule.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/3.6/mule-vm.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/3.6/mule-http.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/3.6/mule-file.xsd">
<object-to-string-transformer name="httptoobj" />
<file:connector name="input"/>
<http:http-response-to-object-transformer
name="httptostring" />
<configuration>
<expression-language autoResolveVariables="false">
<import class="com.xyz.alertcampaign.appworkflow.CampaignStatus" />
</expression-language>
</configuration>
<flow name="polling" doc:name="polling" processingStrategy="synchronous">
<quartz:inbound-endpoint repeatInterval="3000"
startDelay="3000" jobName="couchbasePoller" doc:name="Quartz">
<quartz:event-generator-job stateful="true" />
</quartz:inbound-endpoint>
<component doc:name="Java">
<singleton-object
class="com.xyz.alertcampaign.appworkflow.CouchbasePoller" />
</component>
<vm:outbound-endpoint exchange-pattern="one-way"
path="oozieQueue" doc:name="Trigger workflow" />
</flow>
<flow name="oozie-workflow-manager" doc:name="oozie-workflow-manager">
<vm:inbound-endpoint exchange-pattern="one-way"
path="oozieQueue" doc:name="VM" />
<foreach collection="#[payload.items()]" counterVariableName="counter">
<choice doc:name="Choice">
<when expression="#[payload.status == CampaignStatus.NOT_STARTED]">
<file:inbound-endpoint address="file://#[payload.fileName]" connector-ref="input"/>
<http:outbound-endpoint exchange-pattern="request-response"
address="http://localhost:8080/oozie/v1/jobs"
responseTransformer-refs="httptoobj" method="POST" doc:name="HTTP"
contentType="application/xml;charset=UTF-8" />
<choice doc:name="Choice">
<when expression="#[message.inboundProperties['http.status'] == 201]">
<component doc:name="Java">
<singleton-object
class="com.xyz.alertcampaign.appworkflow.JobUpdater" />
</component>
</when>
<otherwise>
<logger level="ERROR" message="Error occurred on creating Job in OOzie " />
</otherwise>
</choice>
</when>
<when
expression="#[payload.status == CampaignStatus.UPDATED || payload.status == CampaignStatus.EXPIRED]">
<logger level="ERROR" message="#[payload.status]" />
<http:outbound-endpoint exchange-pattern="request-response"
method="PUT"
address="http://localhost:8080/oozie/v1/job/#[payload.jobId]?action=kill"
responseTransformer-refs="httptoobj" doc:name="HTTP" />
<choice doc:name="Choice">
<when expression="#[message.inboundProperties['http.status'] == 200]">
<component doc:name="Java">
<singleton-object
class="com.xyz.alertcampaign.appworkflow.JobUpdater" />
</component>
</when>
<otherwise>
<logger level="ERROR" message="Error occurred on killing Job in OOzie " />
</otherwise>
</choice>
</when>
</choice>
</foreach>
</flow>
</mule>
Getting following exception (stack):
Exception when loading mule' xml:
Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'file:inbound-endpoint'. One of '{"http://www.mulesoft.org/schema/mule/core":abstract-message-processor, "http://www.mulesoft.org/schema/mule/core":abstract-outbound-endpoint, "http://www.mulesoft.org/schema/mule/core":abstract-mixed-content-message-processor}' is expected.
Why am I not allowed to post a file to http inside choice router?
You can only use a file:inbound-endpoint at the beginning of a flow. If you're trying to retrieve a file mid-flow, then consider using the Mule Requestor module. This allows you to request a resource (i.e. a file) at any point in a flow.
The problem is that it's an inbound endpoint so you are adding a message source in the middle of a flow. What you should do is define another flow that starts with that file inbound endpoint (with all that logic) and use a flow reference element in the choice to it.
For more details check out the doc.
Additionaly I think there is another problem where the inbound endpoint does not allow dynamic inputs. I solved it via MuleRequester
I'm testing my Mule(3.3.1) flow which sends a web service call to external vendor. My aim is to catch java.net.ConnectException and apply appropriate XSLT to original payload and send it to caller.
But the payload received in <catch-exception-strategy> is of type org.apache.commons.httpclient.methods.PostMethod#12b13004 and not original XML. Tried using <objexct-to-string-transformer> but didn't help.
Any suggestions how to retrieve the original payload in catch block?
Part of mule-config.xml is below:
<flow name="orderRequirementsToVendor">
<jms:inbound-endpoint queue="order.vendor" />
<set-property propertyName="SOAPAction" value="http://vendor.com/services/InterfacePoint/Call" />
<cxf:proxy-client payload="body" enableMuleSoapHeaders="false">
<cxf:inInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
</cxf:inInterceptors>
<cxf:outInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
</cxf:outInterceptors>
</cxf:proxy-client>
<outbound-endpoint address="${vendor.ws.url}" mimeType="text/xml" connector-ref="https.connector" />
<byte-array-to-string-transformer />
<choice-exception-strategy>
<catch-exception-strategy when="#[exception.causedBy(java.net.ConnectException)]">
<logger message="#[exception.causeException]" level="ERROR" />
<object-to-string-transformer/>
<transformer ref="vendorConnectExceptionTransformer" />
</catch-exception-strategy>
<catch-exception-strategy>
<logger message="#[exception.causeException]" level="ERROR" />
<transformer ref="generalErrorTransformer" />
</catch-exception-strategy>
</choice-exception-strategy>
</flow>
Store the original payload in a flow variable right after jms:inbound-endpoint with
<set-variable variableName="originalPayload" value="#[message.payload]" />
Access it back in your exception strategy with a MEL expression like: #[flowVars.originalPayload].