Mule ESB problems with interceptor-stack - mule

I'm new to Mule and having trouble with using interceptor-stack elements.
The following seems like it is taken right out of their documentation here: http://www.mulesoft.org/documentation/display/33X/Using+Interceptors
<interceptor-stack name="default">
<logging-interceptor/>
<timer-interceptor/>
</interceptor-stack>
<flow name="MyFlowFlow1" doc:name="MyFlowFlow1">
<interceptor-stack ref="default"/> <!--this is line 15 -->
<logger level="INFO" message="Got here"/>
</flow>
but I get an exception saying it's invalid.
Can someone tell me what I'm doing wrong?
org.xml.sax.SAXParseException; lineNumber: 15; columnNumber: 43; cvc-complex-type.2.4.a: Invalid content was found starting with element 'interceptor-stack'. One of '{"http://www.mulesoft.org/schema/mule/core":annotations, "http://www.mulesoft.org/schema/mule/core":description, "http://www.mulesoft.org/schema/mule/core":abstract-message-source, "http://www.mulesoft.org/schema/mule/core":abstract-inbound-endpoint, "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, "http://www.mulesoft.org/schema/mule/core":response}' is expected.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
...etc...
EDIT - This is to address the responses below.
This first private flow works perfectly when invoked from another flow via flow-ref. I see the "got here" message and the timing.
<flow name="test2Flow1" doc:name="test2Flow1">
<timer-interceptor/>
<logger level="INFO" message="got here" doc:name="Logger"/>
</flow>
However, this second private flow does not work when invoked from another flow...in fact, it won't even parse. The only difference is that the explicit use of the timer-interceptor is changed to be a reference to an interceptor-stack containing the timer-interceptor.
<interceptor-stack name="default">
<timer-interceptor/>
</interceptor-stack>
<flow name="test2Flow1" doc:name="test2Flow1">
<interceptor-stack ref="default"/>
<logger level="INFO" message="got here" doc:name="Logger"/>
</flow>

I think your flow is invalid because it doesnt have a message processor.
Take a look on the anatomy of a flow.
http://www.mulesoft.org/documentation/display/current/Using+Flows+for+Service+Orchestration#UsingFlowsforServiceOrchestration-TheAnatomyofaFlow

Your message processor must be the first item in the flow

Interceptors are meant to be used within components.
This configuration should work:
<interceptor-stack name="default">
<logging-interceptor/>
<timer-interceptor/>
</interceptor-stack>
<flow name="test2Flow1" doc:name="test2Flow1">
<pooled-component class="com.MyComponent">
<interceptor-stack ref="default"/> <!--this is line 15 -->
</pooled-component>
<logger level="INFO" message="Got here"/>
</flow>

Related

How to capture an exception using the regex-filter filter in Mule ESB

Currently I have a flow that exposes a REST service with a string as input parameter . I am using a regex -filter to ensure the format parameter as follows :
<http:inbound-endpoint doc:name="HTTP"
connector-ref="ciuServiceHTTPConnector" ref="ciuServiceHTTPEndpoint"
exchange-pattern="request-response" />
<logger level="INFO" doc:name="Logger" message="epale1 #[payload]"/>
<regex-filter pattern="^/api/person/(V|E)[0-9]{8}$"
doc:name="Regex" />
<logger message="epale2 #[payload]" level="INFO" doc:name="Logger"/>
<jersey:resources doc:name="REST" >
<component class="...resource.CiudadanoResource"/>
</jersey:resources>
I need to send the customer a message "Invalid or missing parameter" . For this I use a choice-exception-strategy and catch-exception-strategy and then call a Subflow and perform http:response-builder.
How can I throw an exception(type) when the regex-filter do not match?. It is possible to incorporate this behavior or should I change my flow?
Thanks for your help;
Wrap it in a message-filter, like this:
<message-filter throwOnUnaccepted="true">
<regex-filter pattern="^/api/person/(V|E)[0-9]{8}$"
doc:name="Regex" />
</message-filter>
See the official documentation for further details:
Check the Throw On Unaccepted box to throw an exception if a message
or event is not handled. The default when not checked is to not throw
an exception.

How to implement deadLetterQueue for JDBC Connector Using Until Successful

I am trying implement deadLetterQueue on UntilSuccessful for JDBC Connector. I would like to send the payload to a queue(DeadLetterQueue) when UntilSuccessful fails after trying no of times as configured. I referred following links
http://blogs.mulesoft.org/meet-until-successful-store-and-forward-for-mule/
Where in the application would you define the vm:endpoint for a dlqEndpoint-ref defined in an until-successful scope?
Below is my code snippet
<vm:endpoint exchange-pattern="one-way" path="dlqChannel" name="VM" doc:name="VM"/>
Above line is my global element
<flow...> .... <until-successful objectStore-ref="objectStore" deadLetterQueue-ref="dlqChannel" maxRetries="5" secondsBetweenRetries="60" doc:name="Until Successful" failureExpression="exception-type:java.sql.SQLException">
<jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="Insert Query" queryTimeout="-1" connector-ref="Database" doc:name="Database"/>
</until-successful>....</flow>
<flow name="Flow2" doc:name="Flow2">
<endpoint ref="dlqChannel" />
<logger message="DEAD DEAD DEAD LETTER LETTER LETTER #[message]" level="INFO" doc:name="Logger"/>
</flow>
At this line <endpoint ref="dlqChannel" /> I am getting compile error says "Reference to unknown global element:dlqChannel"
Can any one suggest a best way to achieve this scenario.
Thanks,
Kalyan
Your endpoint is called 'VM' not 'dlqChannel'. Change either the name to dlqChannel or point it to VM.
This issue is resolved.
Below is my code snippet.
<vm:endpoint exchange-pattern="one-way" path="dlq" name="dlqChannel" doc:name="VM"/>
Above line is vm global element
<flow...> ... <until-successful objectStore-ref="objectStore" deadLetterQueue-ref="dlqChannel" maxRetries="2" secondsBetweenRetries="10" doc:name="Until Successful" failureExpression="exception-type:java.sql.SQLException">
<jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="Insert Query" queryTimeout="-1" connector-ref="Database" doc:name="Database"/>
</until-successful>
....
</flow>
<flow name="Flow2" doc:name="Flow2">
<vm:inbound-endpoint exchange-pattern="one-way" path="dlq" doc:name="VM"/>
<logger message="DEAD DEAD DEAD LETTER LETTER LETTER #[message.payload]" level="INFO" doc:name="Logger"/>
</flow>
Based on "deadLetterQueue-ref" in UntilSuccessful, payload goes to vm:inbound-endpoint(vm://dlq) as defined in the vm global endpoint.
As Seba correctly points out, your error is due to a wrong name/ref. As for how to implement the deadLetterQueue, you need an inbound endpoint. So in Flow2, change the endpoint to <inbound-endpoint ref="dlqChannel" />.

How to get handle to original file from file:outbound-endpoint in mule

In a flow something like below:
<flow name="fileFlow">
<file:inbound-endpoint path="/inbound/ftp/sbc" pollingFrequency="30000" fileAge="30000" moveToDirectory="/inbound/ftp/sbc/archive">
<file:filename-wildcard-filter pattern="*.xml" caseSensitive="false"/>
</file:inbound-endpoint>
<logger message="Entering #[flow.name] flow" level="INFO"/>
<component class="com.abc.RequestFile"/>
<logger message="Payload after transformation is: #[payload] flow" level="INFO"/>
<vm:outbound-endpoint path="merge" />
<logger message="Exiting #[flow.name] flow" level="INFO"/>
</flow>
I get InputStream from file:inbound-endpoint which is passed to RequestFile component. This component is required to return a list of files of which one of this is the original one read and passed. I am seeking a solution other than manual copying InputStream to File in java component.
As explained in this answer https://stackoverflow.com/a/12397775/387927 you can get the java.io.File object instead of its content with this setting:
<file:connector name="fileConnector" streaming="false" autoDelete="false">
<service-overrides messageFactory="org.mule.transport.file.FileMuleMessageFactory" />
</file:connector>
Note that it is up to you to move / delete the file either before you start or once you've done processing it, otherwise Mule will poll it again and again.

mule's http-proxy cannot be used in flow?

I would like to do a proxy for backend rest service, but before I forward the request to backend, I need to do some checks. I checked the docments, there is a http-proxy can be used to do the proxy, but when I put into the flow, there are exceptions. If I use the http:outbound-endpoint the method cannot be a dynamic MEL expression(rest method could be POST, GET, PUT, DELTE etc).
Could you give me a suggestion? An example will be better, Thanks a lot.
My Configuration:
<flow name="demo.routerFlow1" doc:name="demo.routerFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8080" doc:name="HTTP" />
<logger
message="Method: #[message.inboundProperties['http.method']], URI: #[message.inboundProperties['http.request.path']], Params: #[message.inboundProperties['http.query.params']]"
level="INFO" doc:name="Logger" />
<http:body-to-parameter-map-transformer doc:name="Body to Parameter Map" />
<choice doc:name="Choice">
<when expression="(payload['timestamp'] == null || payload['nonce'] == null)">
<expression-component doc:name="Check Required Params"><![CDATA[payload="{\"code\":\"PA001\", \"message\":\"missing required parameter timestamp and nonce\"}"]]>
</expression-component>
</when>
<otherwise>
<choice doc:name="Choice">
<when expression="!replayAttackCheck.validate(payload)" evaluator="groovy">
<expression-component doc:name="Check Required Params"><![CDATA[payload="{\"code\":\"PA002\", \"message\":\"timestamp or nonce is illegal\"}"]]>
</expression-component>
</when>
<otherwise>
<processor-chain doc:name="Processor Chain">
<pattern:http-proxy name="http-proxy-sample"> <!--line 38-->
<http:inbound-endpoint address="http://localhost:8080/"></http:inbound-endpoint>
<http:outbound-endpoint address="http://localhost:8081/"></http:outbound-endpoint>
</pattern:http-proxy>
</processor-chain>
</otherwise>
</choice>
</otherwise>
</choice>
</flow>
Error:
Caused by: org.xml.sax.SAXParseException; lineNumber: 38; columnNumber: 31; cvc-complex-type.2.4.b: The content of element 'processor-chain' is not complete. One of '{"http://www.mulesoft.org/schema/mule/core":annotations, "http://www.mulesoft.org/schema/mule/core":description, "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.
at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
Configuration patterns are standalone and separate from any flow and cannot be configured within one. They are predefined integration patterns for common scenarios. Flows are for rolling your own. See here: http://www.mulesoft.org/documentation/display/current/Choosing+Between+Flows+and+Patterns
As a side note: Your already listening on localhost:8080, so I think you just want a http:outbound-endpoint to the service your running on 8081
<http:outbound-endpoint address="http://localhost:8081/" />
You just need a http:outbound to the actual rest service in your otherwise block.
Try using the following.
<otherwise>
<http:outbound-endpoint address="http://localhost:8081/"></http:outbound-endpoint>
</otherwise>
Hope this helps.

How can I overwrite the payload in mule

I've a Soap request coming into mule flow. Am tasked with getting information out of payload and depending on outcome, push the original request to different jms queues.
To get the desired information out of payload, I'm using XSLT tranformer (not XPath, because I need to get IDREF attribute from an element, based on IDREF, get the element and then a child element out of the IDREF object).
Based on the outcome of the of XSLT tranformation, I use choice element to push original payload. Am storing original payload in a Session (can do it in Inbound as well). After XSLT tansformation, apply choice router to find out appropriate queue, and then want to push the original payload into queue(original payload in stored in a session variable). I am using <expression-component> element. Below is the snippet of mule-flow:
<flow name="ProcessXML121Order">
<jms:inbound-endpoint queue="mviq.121.order" exchange-pattern="one-way" />
<logger message="121 order payload is #[payload]" level="INFO" />
<message-properties-transformer scope="session">
<add-message-property key="mviPayload" value="#[payload]"/>
</message-properties-transformer>
<xm:xslt-transformer xsl-file="chooseVendor.xslt" />
<logger message="After xsl file payload is #[payload]" level="INFO" />
<choice>
<when expression="'EMSI'">
<logger message="Vendor is EMSI" level="INFO" />
<expression-component>payload=#[header:SESSION:mviPayload]</expression-component>
<jms:outbound-endpoint queue="mviq.121.order.emsi" />
</when>
<when expression="'PRMD'">
<logger message="Vendor is PRMD" level="INFO" />
<jms:outbound-endpoint queue="mviq.121.order.prmd" />
</when>
<when expression="'RSA'">
<logger message="Vendor is RSA" level="INFO" />
<logger message="RSA payload is #[payload]" level="INFO" />
<jms:outbound-endpoint queue="mviq.121.order.rsa" />
</when>
<otherwise>
<logger message="Vendor is Error" level="INFO" />
<logger message="Vendor error payload is #[payload]" level="INFO" />
<jms:outbound-endpoint queue="mviq.error" />
</otherwise>
</choice>
</flow>
Following exception is thrown when evaluating payload=#[header:SESSION:mviPayload]
[ProcessXML121Order.stage1.02] exception.AbstractExceptionListener (AbstractExceptionListener.java:296) -
********************************************************************************
Message : Execution of the expression "payload=#[header:SESSION:mviPayload]" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: byte[]
Code : MULE_ERROR-29999
--------------------------------------------------------------------------------
Exception stack is:
1. [Error: illegal use of operator: +]
[Near : {... Unknown ....}]
^
[Line: 1, Column: 0] (org.mvel2.CompileException)
org.mvel2.ast.OperatorNode:46 (null)
2. Execution of the expression "payload=#[header:SESSION:mviPayload]" failed. (org.mule.api.expression.ExpressionRuntimeException)
org.mule.el.mvel.MVELExpressionLanguage:211 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/expression/ExpressionRuntimeException.html)
3. Execution of the expression "payload=#[header:SESSION:mviPayload]" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: byte[] (org.mule.api.MessagingException)
org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor:35 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
[Error: illegal use of operator: +]
[Near : {... Unknown ....}]
^
[Line: 1, Column: 0]
at org.mvel2.ast.OperatorNode.getReducedValueAccelerated(OperatorNode.java:46)
at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85)
at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:105)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
I've 2 questions:
How can I overwrite the original payload? (Not saying this is the best way to go)
What is the better approach in this scenario? Is it advisable to keep original payload intact (in this case) and store XSLT output in other variable? How can I do that? What is the path (mule component) I can use to achieve that? I'm very new to Mule and seek community advice.
Thanks for your time looking into this.
Before answering your questions, let's rewrite this broken expression:
<expression-component>payload=#[header:SESSION:mviPayload]</expression-component>
as:
<set-payload value="#[sessionVars.mviPayload]" />
The following would work too but would be more complex for no good reason:
<expression-component>payload=sessionVars.mviPayload</expression-component>
Also this:
<message-properties-transformer scope="session">
<add-message-property key="mviPayload" value="#[payload]"/>
</message-properties-transformer>
would be better written:
<set-session-variable variableName="mviPayload" value="#[message.payload]" />
Now to your questions:
Use set-payload
What you are doing is the best: transformers, like XSL-T, applies naturally to the current message payload so saving the original in a property then transforming the main payload is OK. Just one thing: prefer a flow variable instead of a session variable. Indeed, in your case, I don't think you need the original payload outside this flow, so storing in session is overkill.
So I suggest you use:
<set-variable variableName="mviPayload" value="#[message.payload]" />
to store the original payload and the following to re-establish it:
<set-payload value="#[mviPayload]" />
Use Set-Payload and provide the data to be overwritten.
You could do this with lot of ways.
Use set-payload
Use expression, #[payload='']
Use an transformer/component
You can keep the payload intact and store the value of the xslt transformation in a variable using message enricher. Use the variable inside choice to determine which queue to go to. Below is a code snippet
<enricher doc:name="Message Enricher" target="#[flowVars.transformResultVar]">
<!--perform transformation logic here-->
</enricher>
Reference: https://dzone.com/articles/content-enrichment-using-mule-message-enricher-com