Message enricher and MEL - mule

The message enricher documentation uses a term "variable" for example
<flow name="orderProcessingFlow">
<inbound-endpoint ref="orderEndpoint"/>
<enricher target="#[variable:state]">
<outbound-endpoint ref="stateLookup"/>
</enricher>
<outbound-endpoint ref="orderStep2"/>
</flow>
I did not find any documentation on that keyword, I can figure out it basically adds a flow variable, but is there anything more to it ? (without keyword variable you get a exception)
Also none of the examples in the documentation refer to enriching "message headers" -- My assumption is that message headers implies outbound properties is that correct ?
If the same flow were to add a outbound property how would it look (this works based on my tests)
<flow name="orderProcessingFlow">
<inbound-endpoint ref="orderEndpoint"/>
<enricher target="#[message.outboundProperties.var]">
<outbound-endpoint ref="stateLookup"/>
</enricher>
<outbound-endpoint ref="orderStep2"/>
</flow>

#[variable:state] is the old expression syntax, it's deprecated and replaced by MEL since 3.3. I think the MEL equivalent is #[flowVars.state]
Similarly, message "headers" is obsolete lingo. You have message properties with different scopes (inbound, outbound, flow/invocation and session).
And yes the only properties you can set in a flow are outbound properties (inbound ones are set by endpoints).

Related

Mule:Retrieving object store in an MEL in Mule 3.5

Having a requirement to test a object store whether it contains a key or not in a choice router
<objectstore:config name="storeDownload" doc:name="ObjectStore" persistent="false" partition="test"/>
<choice>
<when expression="#[app.registry.storeDownload.contains('#[flowVars.startKey]').equals('false')]">
Getting an error
1. Expression Evaluator "registry" with expression "ON" returned null but a value was required. (org.mule.api.expression.ExpressionRuntimeException)
org.mule.expression.RegistryExpressionEvaluator:101 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/expression/ExpressionRuntimeException.html)
2. Failed to invoke store. Message payload is of type: byte[] (org.mule.api.MessagingException)
The main issue is that you are embedding MEL into MEL which can't work. Also the boolean-as-string comparison is dodgy.
Replace this:
#[app.registry.storeDownload.contains('#[flowVars.startKey]').equals('false')]
with that:
#[!(app.registry.storeDownload.contains(flowVars.startKey))]
My use case was a bit different to Nazar's I needed to monitor a long running process which can take up to four hours.
In the first flow I generate a key value with a time stamp in it as the payload and then use it to set the ProcessState to the static value 'Started' in an ObjectStore as shown below. After which I fire a Quartz Outbound Endpoint with a four hour delay.
<objectstore:store config-ref="MonitoredProcess" value-ref="Started" key="#[payload]" doc:name="ObjectStore"/>
<quartz:outbound-endpoint jobName="ProcessMonitor" responseTimeout="10000" doc:name="Quartz"
repeatInterval="0" repeatCount="0" startDelay="${process.monitor.event.start.delay}">
<quartz:scheduled-dispatch-job>
<quartz:job-endpoint address="vm://processMonitorQueue"/>
</quartz:scheduled-dispatch-job>
</quartz:outbound-endpoint>
And I got the same exception.
After scratching my head and lots of searches the name of the variable 'value-ref' in combination with David's answer above finally revealed my problem namely the MEL is always invoked for this ref field.
As soon as I changed the field to an expression #['Started'] that MEL could evaluate my problem went away.
<objectstore:store config-ref="MonitoredProcess" value-ref="#['Started']" key="#[payload]" doc:name="ObjectStore"/>
For completeness I've included the code that retrieves the ProcessState from the ObjectStore. Note the defaultValue-ref also needs to use MEL
<vm:inbound-endpoint exchange-pattern="one-way" path="processMonitorQueue" doc:name="VM" />
<objectstore:retrieve config-ref="MonitoredProcess" defaultValue-ref="#['DoesNotExist']" key="#[payload]" targetProperty="processState" doc:name="ObjectStore"/>

How to Extract the Flow Name and MessageProcessor Name using MEL - MULE ESB

I'm not sure, how can we extract the flow-name and message-processor Name through MEL. For example I have multiple message processor. For logging, i need to extract the flow Name and Message-processor, so that I can find out transaction has crossed this particular flow and its message processor. Is there any simple way to find out. Please guide me. Please find the screenshot below. Here i need to Extract - set payload and its flowName (flow1)
Thanks in advance.
For mule 3.8+ version onwards #[flow.name] don't work.
Use #[mule:context.serviceName] expression in logger or component to extract the name of the flow
I know this post is old but I have been trying to find a way to do this in MEL for error handling emails.
For the flow name you can use #[exception.event.flowConstruct.name]
for the failing message processor you can use #[exception.failingMessageProcessor].
Both of these work in MEL without the need to use an flowVar.
Please note however, that the failing processor does not always come back with a value but comes back with null, I'm not sure why.
You can extract the flow-name with MEL : #[flow.name]
<flow name="name" doc:name="name">
<http:inbound-endpoint address="http://localhost:8090/resources" doc:name="HTTP" />
<logger message="name of flow: #[flow.name]" level="INFO" doc:name="Logger"/>
<set-payload value="name" doc:name="Set Payload"/>
</flow>
or
flowConstruct.getName() in a Message Processor
Two ways to acthive this (from current flow name)
First one is -
<logger message="Current flowName: #[flow.name]" level="INFO" doc:name="Logger"/>
and the second one is -
<logger message="Current flowName: #[context:serviceName]" level="INFO" doc:name="Logger"/>

SMTP subject expression evaluation fails

I have a flow where I want to evealuate an expression on the smtp subject attribute but always get mvel parse expression though the logger give me the right values.
<json:object-to-json-transformer doc:name="Object to JSON"/>
<logger message="MYRequestPayloadID #[json:RequestPayloadID] #[json:ResponseStatusCd]" level="DEBUG" doc:name="Logger"/>
<smtp:outbound-endpoint host="${mail.host}" to="${mail.to}" from="${mail.from}" subject="Error Response for PayloadID #[json:RequestPayloadID], Status #[json:ResponseStatusCd]" responseTimeout="10000" doc:name="SMTP />
I am not sure why in the subject #[json:RequestPayloadID] and #[json:ResponseStatusCd] evaluation fail though I get the data back in the logger . Thanks.
Expressions are not supported everywhere in Mule (alas): this is one place where it isn't.
You have to use message properties to set the subject dynamically:
<set-property propertyName="subject"
value="Error Response for PayloadID #[json:RequestPayloadID], Status #[json:ResponseStatusCd]" />
FTR json: is the old expression style, nowadays you should be using MEL instead: http://www.mulesoft.org/documentation/display/current/Mule+Expression+Language+Tips#MuleExpressionLanguageTips-JSONProcessing

How to parse inbound e-mail when using Mule's IMAP transport?

I am just starting to learn mule so please forgive me if this is a very basic question.
I have successfully configured mule to monitor my mail box so whenever a mail comes in I write the mail to text file (just for testing).
Now I need to parse this mail and get the message / From / To from the mail.
<flow name="testFlow" doc:name="testFlow">
<imap:inbound-endpoint host="ip"
port="143" user="username" password="pwd" doc:name="IMAP"
responseTimeout="10000" transformer-refs="Message_Properties">
</imap:inbound-endpoint>
<file:outbound-endpoint path="C:\"
outputPattern="#[function:datestamp].dat" doc:name="File">
</file:outbound-endpoint>
</flow>
I thought I would be able to get the header information using the below expression (using expression transformer)
#[inboundProperties['email-header-name']]
but this doesn't seem to work. I also tried the below expressions but didn't work,
#[map-payload:HOST]
#[map-payload:MESSAGE]
#[map-payload:TIMESTAMP]
Can someone help? Also does anyone know if there is a document with the list of available expressions?
EDIT:
I included the logger to view the properties and it displayed all the properties but I couldnt find the body.. Also, I tried getting the fromAddress using
#[map-payload:fromAddress] and #[inboundProperties['fromAddress']]
but didn't work, can someone let me know where I am wrong?
The properties are something like below,
inbound.fromAddress=Service <service#xx.com>
inbound.subject=Test Final inbound.toAddresses=Service
Edit 2:
This is what I have tried but doesnt work :(
I am trying to retrieve the email subject and write to file or just show it using logger based on email subject but I am getting the below error.
ERROR 2013-02-07 19:22:45,275 [[test].connector.file.mule.default.dispatcher.01] org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : Could not find a transformer to transform "SimpleDataType{type=javax.mail.internet.MimeMessage, mimeType='*/*'}" to "SimpleDataType{type=java.io.InputStream, mimeType='*/*'}".
Code : MULE_ERROR-236
Can you let me know where I am making mistake?
<flow name="testFlow1" doc:name="testFlow1">
<imap:inbound-endpoint host="ip"
port="143" user="uname" password="pwd" doc:name="IMAP"
responseTimeout="10000" disableTransportTransformer="true">
</imap:inbound-endpoint>
<logger message="#[message.inboundProperties['inbound.fromAddress']]" level="INFO" doc:name="Logger"/>
<choice doc:name="Choice">
<when expression="message.inboundProperties['inbound.subject']=='plain test'">
<processor-chain>
<logger message="#[message.inboundProperties['inbound.fromAddress']]" level="INFO" doc:name="Logger"/>
</processor-chain>
</when>
<otherwise>
<processor-chain>
<file:outbound-endpoint path="C:\mule" outputPattern="#[function:datestamp].dat" responseTimeout="10000" disableTransportTransformer="true" doc:name="File">
</file:outbound-endpoint>
</processor-chain>
</otherwise>
</choice>
</flow>
Unfortunately the IMAP connector documentation doesn't list the message properties created when a new message is received. You can find all the created properties by adding:
<logger level="WARN" />
after the imap:inbound-endpoint. This will log all the message meta information, including properties, at WARN level.
You can also find the property names in the MailProperties JavaDoc. For example inbound.fromAddress is the inbound property that contains the sender's email address.
The message body is the text email content, unless it's a multi-part email. In that case, if the first part is text/plain, it will be set as the message payload, otherwise all parts will be available as inbound message attachments.

How to log or handle original payload message in Mule

<flow>
<jms:inbound-endpoint queue="InputQueue"/>
<component class="MyComponent"/>
<choice>
<when expression="/Response/Status/Success" evaluator="xpath">
<jms:outbound-endpoint queue="LogInputQueue"/>
<jms:outbound-endpoint queue="SuccessQueue"/>
</when>
<when expression="/Response/Status/Error" evaluator="xpath">
<jms:outbound-endpoint queue="LogInputQueue"/>
<jms:outbound-endpoint queue="ErrorQueue"/>
</when>
<otherwise>
<jms:outbound-endpoint queue="LogInputQueue"/>
<jms:outbound-endpoint queue="ExceptionQueue"/>
</otherwise>
</choice>
</flow>
In this flow, MyComponent returns either success message as a response or error response or exception?
I need to log the original message from InputQueue in LogInputQueue in all the cases. How do I achieve this in my flow?
Did you mean to create a log file? In that case, you have to implement log4j using slf4j and use the line
<logger level="log_level" category="your_category" message="#[message:payload]"/>
where log_level is your desired logging level- "error", "debug", "info" etc...
your_category is your category of log defined in the log4j.properties file (it is optional actually)
and message="#[expression:value]" is your message to be logged given as an expression:scope:key combination. Scope is optional here.
Using log4j or slf4j you can log the payload.
[payload],we have logger component using this log payload in console.
Since, you need to send original message from InputQueue to LogInputQueue in all the cases, as you mentioned, what you need to do is :-
1. Remove <jms:outbound-endpoint queue="LogInputQueue"/> from all the cases in choice block
2. Store the original payload from InputQueue in a variable by placing it just after the JMS inbound endpoint
3. At the end of the flow, after the choice router, set the payload in set payload component from variable you stored the original payload
4. Now put <jms:outbound-endpoint queue="LogInputQueue"/> after your set payload component.
In this way you will able to send the original payload to the LogInputQueue as per your requirement.