I have a mule flow which reads messages from a sonic topic and publish to a Websphere MQ Topic.
The flow is synchronous and transacted.
I have set maxRedelivery="10" in the inboud endpoint. but it keeps on trying to redeliver.
Here is the exception I get:
ERROR 2014-03-03 15:13:08,763 [JMS Session Delivery Thread - $TMPAPPID$544239$$SESSION$0:-3441129419112818566] org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : "Message with id "ID:1419c04f:da190005:1448992ACB1" has been redelivered 1,511 times on endpoint "jms://topic:testtopic", which exceeds the maxRedelivery setting of 10 on the connector "sonicMQConnectorSub". Message payload is of type: TextMessage
Code : MULE_ERROR--2
--------------------------------------------------------------------------------
Exception stack is:
1. "Message with id "ID:1419c04f:da190005:1448992ACB1" has been redelivered 1,511 times on endpoint "jms://topic:testtopic", which exceeds the maxRedelivery setting of 10 on the connector "sonicMQConnectorSub". Message payload is of type: TextMessage (org.mule.transport.jms.redelivery.MessageRedeliveredException)
org.mule.transport.jms.redelivery.JmsXRedeliveryHandler:91 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/transport/jms/redelivery/MessageRedeliveredException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
org.mule.transport.jms.redelivery.MessageRedeliveredException: "Message with id "ID:1419c04f:da190005:1448992ACB1" has been redelivered 1,511 times on endpoint "jms://topic:testtopic", which exceeds the maxRedelivery setting of 10 on the connector "sonicMQConnectorSub". Message payload is of type: TextMessage
at org.mule.transport.jms.redelivery.JmsXRedeliveryHandler.handleRedelivery(JmsXRedeliveryHandler.java:91)
at org.mule.transport.jms.MultiConsumerJmsMessageReceiver$JmsWorker.preProcessMessage(MultiConsumerJmsMessageReceiver.java:426)
at org.mule.transport.AbstractReceiverWorker$1$1.process(AbstractReceiverWorker.java:120)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
Here is the flow I use.
<jms:connector name="sonicMQConnectorSub" specification="1.1" validateConnections="true" maxRedelivery="10" connectionFactory-ref="soniqMQConnectionFactorySub" doc:name="JMS" clientId="${topic.sub.clientId}" durable="true"/>
<spring:beans>
<spring:bean id="soniqMQConnectionFactoryBeanSub" name="soniqMQConnectionFactorySub" class="progress.message.jclient.ConnectionFactory">
<spring:property name="connectionURLs" value="${topic.sub.providerUrls}" />
<spring:property name="defaultUser" value="${topic.sub.username}" />
<spring:property name="defaultPassword" value="${topic.sub.password}" />
</spring:bean>
</spring:beans>
<jms:connector name="wsMQConnector" specification="1.1" username="${topic.pub.username}" password="${topic.pub.password}" validateConnections="true" connectionFactory-ref="wsMQConnectionFactory" doc:name="JMS" clientId="${topic.pub.clientId}"/>
<spring:beans>
<spring:bean id="wsMQConnectionFactory" class="com.ibm.mq.jms.MQTopicConnectionFactory">
<spring:property name="transportType" value="1"/>
<spring:property name="hostName" value="${topic.pub.host}"/>
<spring:property name="port" value="${topic.pub.port}"/>
<spring:property name="channel" value="${topic.pub.channel}"/>
<spring:property name="queueManager" value="${topic.pub.queueManager}"/>
</spring:bean>
</spring:beans>
<flow name="Flow1" doc:name="Flow1" processingStrategy="synchronous">
<jms:inbound-endpoint doc:name="JMS" connector-ref="sonicMQConnectorSub" topic="${topic.sub.name}" >
<jms:transaction action="ALWAYS_BEGIN" />
</jms:inbound-endpoint>
<message-properties-transformer doc:name="Message Properties">
<add-message-property key="SENTTIMESTAMP" value="#[server.dateTime]"/>
</message-properties-transformer>
<logger message="Payload: #[message.payload]" level="INFO" doc:name="Logger"/>
<jms:outbound-endpoint doc:name="JMS" connector-ref="wsMQConnector" topic="${topic.pub.name}">
<jms:transaction action="ALWAYS_JOIN" />
</jms:outbound-endpoint>
</flow>
This is expected behavior, the above exception is raised when the maximum redelivery count defined in maxRedelivery has been exceeded by your JMS provider. See the answer by David Dossot here: jms Mule max redelivery exceeded
Related
I need to set Status code and Reason Phrase in mule HTTP using Mule Choice exception strategy under that is Catch exception strategy. Following the Mulesoft documentation https://docs.mulesoft.com/mule-user-guide/v/3.7/http-listener-connector#http-response-status-code-and-reason-phrase
I tried doing something like this :
<choice-exception-strategy name="MyExptn">
<rollback-exception-strategy when="#[exception.causedBy(org.mule.component.ComponentException)]" doc:name="ComponentException Strategy">
<set-variable variableName="errorTableNotPresent" value="400" doc:name="Set status code"/>
<set-variable variableName="errorReasonPhrase" value="Table name does not exist" doc:name="Set reason phrase"/>
<message-properties-transformer doc:name="Message Properties">
<add-message-property key="timestamp" value="#[server.dateTime.format('yyyy-MM-dd hh:mm:ss.SS')]"/>
<add-message-property key="messageID" value="#[message.id]"/>
<add-message-property key="status" value="Error"/>
<add-message-property key="executionPoint" value="Error Handling"/>
<add-message-property key="ip" value="#[server.ip]"/>
<add-message-property key="serverName" value="#[server.host]"/>
<add-message-property key="domainname" value="xyz.com"/>
<add-message-property key="errorCode" value="123"/>
<add-message-property key="errorType" value="Bad request"/>
<add-message-property key="errorText" value="ComponentException"/>
<add-message-property key="integrationName" value="${integrationName}"/>
<add-message-property key="resourceType" value="HTTP Request"/>
<add-message-property key="resourceName" value="Payload"/>
</message-properties-transformer>
<logger level="INFO" message="#[LoggingAppendString] - Failure" doc:name="Logger"/>
</rollback-exception-strategy>
</choice-exception-strategy>
Which is working fine. But when I'm replacing it with Catch Exception Strategy as shown below :
<choice-exception-strategy name="MyExptn">
<catch-exception-strategy when="#[exception.causedBy(org.mule.component.ComponentException)]" doc:name="ComponentException Strategy">
<set-variable variableName="errorTableNotPresent" value="400" doc:name="Set status code"/>
<set-variable variableName="errorReasonPhrase" value="Table name does not exist" doc:name="Set reason phrase"/>
<message-properties-transformer doc:name="Message Properties">
<add-message-property key="timestamp" value="#[server.dateTime.format('yyyy-MM-dd hh:mm:ss.SS')]"/>
<add-message-property key="messageID" value="#[message.id]"/>
<add-message-property key="status" value="Error"/>
<add-message-property key="executionPoint" value="Error Handling"/>
<add-message-property key="ip" value="#[server.ip]"/>
<add-message-property key="serverName" value="#[server.host]"/>
<add-message-property key="domainname" value="xyz.com"/>
<add-message-property key="errorCode" value="123"/>
<add-message-property key="errorType" value="Bad request"/>
<add-message-property key="errorText" value="ComponentException"/>
<add-message-property key="integrationName" value="${integrationName}"/>
<add-message-property key="resourceType" value="HTTP Request"/>
<add-message-property key="resourceName" value="Payload"/>
</message-properties-transformer>
<logger level="INFO" message="#[LoggingAppendString] - Failure" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
Will only log the message but HTTP status always showing 200 OK.
My basic requirement is to send status code based on the error. Say for example if request is not correct then Bad request with code 400.
Define two outbound properties: http.status and http.reason. These will be sent to the client as the actual status. Without setting these values Mule will default to 200 - OK.
I do not see these fields defined in your example.
Example from the documentation link you provided:
<set-property propertyName="http.status" value="500" doc:name="Property"/>
<set-property propertyName="http.reason" value="Request successfully executed!" doc:name="Property"/>
Make sure you scope these as outbound properties.
Keep in mind that on certain versions of the run time there is a bug where http.reason is not mapped into the response correctly resulting in something like Status 400 - OK rather than Status: 400 - Bad Request.
https://www.mulesoft.org/jira/browse/MULE-9045
My flow looks like the below, I expect the message to be redelivered 2 times and then the
Redelivery is exhaused SAD
logger to be printed. But after the component throws the exception the re delivery mechanism does not kick in
<vm:connector name="VM" validateConnections="true" doc:name="VM" />
<flow name="TriggerFlow" >
<http:listener config-ref="Orders_HTTP_Listener_Configuration" path="/rollback" allowedMethods="GET" doc:name="1080/rollback" />
<vm:outbound-endpoint exchange-pattern="request-response" path="txFlow" doc:name="VM" connector-ref="VM" responseTimeout="60000">
</vm:outbound-endpoint>
</flow>
<flow name="TxFlow" >
<vm:inbound-endpoint exchange-pattern="request-response" path="txFlow" doc:name="case1" connector-ref="VM" responseTimeout="60000">
<xa-transaction action="ALWAYS_BEGIN"/>
</vm:inbound-endpoint>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[throw new RuntimeException();]]></scripting:script>
</scripting:component>
<rollback-exception-strategy maxRedeliveryAttempts="3" doc:name="Rollback Exception Strategy">
<logger message="Will rollback #[payload]" level="INFO" doc:name="Logger"/>
<on-redelivery-attempts-exceeded>
<logger message="Redelivery is exhaused SAD " level="INFO" doc:name="Logger"/>
</on-redelivery-attempts-exceeded>
</rollback-exception-strategy>
</flow>
I finally got the answer after speaking with MuleSoft. The updated flow should look like the below, both the VM's should be one-way and the processing strategy of the TxFlow should be synchronous. If the VM is request-reponse then it behaves more like a flow-ref with no queue involved and hence no redelivery ...
Below is a exception strategy part of the flow
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="exception.causedBy(java.sql.BatchUpdateException)" doc:name="SQL deadlock error">
<logger message="SQL EXCEPTION - RETRYING BATCH PROCESS"
level="ERROR" doc:name="Payload Logger" category="asi_user"/>
<set-variable variableName="Exception" value="User" doc:name="Exception Type"/>
<flow-ref name="Reload_Batch" doc:name="Retry Batch Results"/>
</catch-exception-strategy>
<catch-exception-strategy when="exception.causedBy(com.microsoft.sqlserver.jdbc.SQLServerException)" doc:name="SQL error">
<logger message="SQL EXCEPTION - RETRYING BATCH PROCESS"
level="ERROR" category="asi_user" doc:name="Payload Logger" />
<set-variable variableName="Exception" value="User" doc:name="Exception Type"/>
<flow-ref name="Reload_Batch" doc:name="Retry Batch Results"/>
</catch-exception-strategy>
<catch-exception-strategy doc:name="Unexpected errors">
<logger message="UNEXPECTED EXCEPTION - SEND EMAIL NOTIFICATION"
level="ERROR" category="asi_user" doc:name="Payload Logger" />
<set-payload value="#[exception.cause.message]" doc:name="Set Payload"/>
<flow-ref name="Send_Error_Notification" doc:name="Send Email Notification"/>
</catch-exception-strategy>
</choice-exception-strategy>
Even when a java.sql.BatchUpdateException is thrown from the flow, the control goes to the final exception strategy "Unexpected Errors", it doesn't go to SQL deadlock error
Am I missing anything to make it work.
Could any please help me with this to make it work.I'm using is Mule server 3.4.0 EE
Thank you in advance
It is the problem with your expression in the when
Try it the following way.
<catch-exception-strategy when="#[exception.causedBy(java.sql.BatchUpdateException)]" doc:name="SQL deadlock error">
Hope this helps.
I'm trying to build a web service that accepts a number of variables used to build the path for Bing query API. For some reason, if I build the URI my flow recognizes that the new URI is assigned appropriately to the payload, but when I assign the payload to the out-bound HTTP endpoint, it fails.
<flow name="BingQuery" doc:name="BingQuery">
<http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8082" doc:name="HTTP" />
<set-variable variableName="query" doc:name="Variable" value="#[header:INBOUND:query]"/>
<set-variable variableName="numResults" doc:name="Variable" value="#[header:INBOUND:top]"/>
<set-variable variableName="offsetResults" doc:name="Variable" value="#[header:INBOUND:offset]"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy">
<scripting:text><![CDATA[def query = message.getInvocationProperty("query")
def numResults = message.getInvocationProperty("numResults")
def offsetResults = message.getInvocationProperty("offsetResults")
def path = "Data.ashx/Bing/Search/v1/Web?Query=" + "$query" + "&WebFileType=%27PDF%27&\$top=" + "$numResults" + "&\$skip=" + "$offsetResults" + "&\$format=Json"
println "$path"
message.setProperty("pathVar","$path")
return null;]]></scripting:text>
</scripting:script>
</scripting:component>
<logger level="INFO" doc:name="Logger" message="#[header:OUTBOUND:pathVar]"/>
<https:outbound-endpoint exchange-pattern="request-response"
host="api.datamarket.azure.com" port="443" path="#[header:OUTBOUND:pathVar]"
user="*****" password="******"
doc:name="Bing" /> ...
The exception I get is
ERROR 2012-10-25 14:14:26,250 [[poll_directory].BingQuery.stage1.02] org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : Failed to transform from "json" to "java.util.Map"
Code : MULE_ERROR-65110
--------------------------------------------------------------------------------
Exception stack is:
1. Unexpected character ('T' (code 84)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: java.io.InputStreamReader#73b62d67; line: 1, column: 2] (org.codehaus.jackson.JsonParseException)
org.codehaus.jackson.JsonParser:1291 (null)
2. Failed to transform from "json" to "java.util.Map" (org.mule.api.transformer.TransformerException)
org.mule.module.json.transformers.JsonToObject:136 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transformer/TransformerException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
org.codehaus.jackson.JsonParseException: Unexpected character ('T' (code 84)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: java.io.InputStreamReader#73b62d67; line: 1, column: 2]
at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:1291)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportError(JsonParserMinimalBase.java:385)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportUnexpectedChar(JsonParserMinimalBase.java:306)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
There has to be a simple reason it isn't working and I'm sure it's just because I don't know the proper syntax yet in Mule. I also know there is probably a better way to do this using MEL versus Groovy, but I'm not familiar enough with MEL to do it yet.
SOLUTION
Turns out some of the characters of the User property and Password property were being encoded before being sent. Putting that key into a variable before passing to the User & Password property prevents that and led to success.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:json="http://www.mulesoft.org/schema/mule/json"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:https="http://www.mulesoft.org/schema/mule/https" xmlns:file="http://www.mulesoft.org/schema/mule/file"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" xmlns:core="http://www.mulesoft.org/schema/mule/core"
version="CE-3.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/https http://www.mulesoft.org/schema/mule/https/current/mule-https.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
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 ">
<configuration doc:name="Configuration">
<expression-language>
<import class="org.mule.util.StringUtils" />
</expression-language>
</configuration>
<flow name="BingQuery" doc:name="BingQuery">
<http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8082" doc:name="HTTP" />
<set-variable variableName="query" doc:name="Variable" value="#[header:INBOUND:query]"/>
<set-variable variableName="numResults" doc:name="Variable" value="#[header:INBOUND:top]"/>
<set-variable variableName="offsetResults" doc:name="Variable" value="#[header:INBOUND:offset]"/>
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy">
<scripting:text><![CDATA[def query = message.getInvocationProperty("query")
def numResults = message.getInvocationProperty("numResults")
def offsetResults = message.getInvocationProperty("offsetResults")
def path = "Data.ashx/Bing/Search/v1/Web?Query=" + "$query" + "&WebFileType=%27PDF%27&\$top=" + "$numResults" + "&\$skip=" + "$offsetResults" + "&\$format=Json"
println "$path"
message.setProperty("pathVar","$path")
message.setProperty("APIIdentifier","*****")
return null;]]></scripting:text>
</scripting:script>
</scripting:component>
<https:outbound-endpoint exchange-pattern="request-response"
host="api.datamarket.azure.com" port="443" path="#[header:OUTBOUND:pathVar]"
user="#[header:OUTBOUND:APIIdentifier]" password="#[header:OUTBOUND:APIIdentifier]"
doc:name="Bing" />
<json:json-to-object-transformer
returnClass="java.util.Map" doc:name="JSON to Object" />
<expression-transformer expression="#[message.payload.d.results]"
doc:name="Expression" />
<collection-splitter doc:name="Collection Splitter" />
<vm:outbound-endpoint exchange-pattern="one-way"
path="fileWriter" doc:name="VM" />
</flow>
<flow name="RestProcessor" doc:name="RestProcessor">
<vm:inbound-endpoint exchange-pattern="one-way"
path="fileWriter" doc:name="VM" />
<set-variable variableName="fileName" value="#[message.payload.ID].pdf"
doc:name="Variable" />
<http:rest-service-component
serviceUrl="#[joinChar=message.payload.Url.contains('?')?'&':'?' ; StringUtils.join(new String[]{message.payload.Url,(String)joinChar,'followRedirects=true'})]"
httpMethod="GET">
<http:error-filter>
<expression-filter expression="#[Integer.valueOf(message.inboundProperties['http.status']) >= 400]"></expression-filter>
</http:error-filter>
</http:rest-service-component>
<file:outbound-endpoint path="/home/administrator/Documents"
outputPattern="#[flowVars.fileName]" responseTimeout="10000"
mimeType="application/pdf" doc:name="File" />
</flow>
</mule>
Here is the beginning of the flow rewritten with MEL (which works for me, although I tested against a test endpoint not Bing).
Note that I also set the method to GET on the outbound HTTPS endpoint:
<flow name="BingQuery">
<http:inbound-endpoint exchange-pattern="one-way"
host="localhost" port="8082" />
<set-variable variableName="query"
value="#[message.inboundProperties.query]" />
<set-variable variableName="numResults"
value="#[message.inboundProperties.top]" />
<set-variable variableName="offsetResults"
value="#[message.inboundProperties.offset]" />
<expression-component>
flowVars['bingQuery'] =
'Data.ashx/Bing/Search/v1/Web?Query=' + query
+ '&WebFileType=%27PDF%27&$top=' + numResults
+ '&$skip=' + offsetResults
+ '&$format=Json';
payload = null;
</expression-component>
<logger level="ERROR" message="#[bingQuery]" />
<http:outbound-endpoint exchange-pattern="request-response"
method="GET"
host="api.datamarket.azure.com" port="443" path="#[bingQuery]"
user="*****" password="******" />
If the query, numResults and offsetResults variables are not used elsewhere in the flow, I suggest inlining the expressions used to create them right in the expression-component.
I've set up a few proxy services in mule, but still learning. For some reason this flow doesn't work when the namespace and service name should be correct. Anybody see my error?
Thanks for the time
<flow name="UPCFlow1" doc:name="UPCFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="4040" path="upc" doc:name="HTTP"/>
<cxf:proxy-service namespace="http://searchupc.com/" service="GetProduct" payload="envelope" wsdlLocation="http://www.searchupc.com/service/UPCSearch.asmx?WSDL" doc:name="SOAP" port="UPCSearchSoap"/>
<http:outbound-endpoint address="http://www.searchupc.com/supc/service/UPCSearch.asmx"
exchange-pattern="request-response" doc:name="HTTP"/>
</flow>
This is from the stack trace
INFO 2012-10-12 11:06:44,739 [main] org.mule.module.launcher.application.DefaultMuleApplication: App 'upc' never started, nothing to dispose of
Exception in thread "main" org.mule.module.launcher.DeploymentInitException: ServiceConstructionException: Could not find definition for service {http://searchupc.com/}GetProduct.
There is an issue in your configuration: the service name is "UPCSearch" not "GetProduct".
This works:
<flow name="UPCFlow1" doc:name="UPCFlow1">
<http:inbound-endpoint exchange-pattern="request-response"
host="localhost" port="4040" path="upc" doc:name="HTTP" />
<cxf:proxy-service namespace="http://searchupc.com/"
service="UPCSearch" payload="envelope"
wsdlLocation="http://www.searchupc.com/service/UPCSearch.asmx?WSDL"
doc:name="SOAP" port="UPCSearchSoap" />
<http:outbound-endpoint
address="http://www.searchupc.com/supc/service/UPCSearch.asmx"
exchange-pattern="request-response" doc:name="HTTP" />
</flow>