Creating my own connector - Access Flow Variables within a MessageDispatcher - mule

I want my connector to be robust and accept MEL expressions. Right now though I'm having a problem where I'm doing the MEL Evaluator, but what's in my event is not evaluated. I have <set-variable variableName="key" value="#[payload]" /> and then I do this: <my-connector:outbound location="#[key] />.
When I debug this while stepping through my connector, I look into the MuleEvent and I see under the flowVariables field that key=#[key] instead of key=MyProperty.
I looked at LoggerMessageProcessor to ensure that I'm doing this correctly and my code for evaluation looks the same, but when I debug into the logger, I see that MuleEvent has the expression parsed in the flowVariables, instead of the notation I showed above.
Is there a trick to having the MuleEvent have the expressions of flowVariables already evaluated?

Related

Invalid content error on compression:extract

I am attempting to use the zip-extract method in a foreach loop to unzip several files. When I attempt to deploy the project the following error is returned:
Invalid content was found starting with element 'compression:extract'. One of >'{"http://www.mulesoft.org/schema/mule/core":annotations, >"http://www.mulesoft.org/schema/mule/core":abstract-message-processor, >"http://www.mulesoft.org/schema/mule/core":abstract-mixed-content-message-processor}' is expected.
The actual code is:
<compression:extract doc:name="Extract" doc:id="9119d722-95eb-4aee-a734-50e2a2825449" >
<set-payload value="#[payload]" />
<compression:extractor >
<compression:zip-extractor />
</compression:extractor>
</compression:extract>
I have not been able to find anything online that would point towards a solution.
It look like accidentally a <set-payload> was put inside the <compression:extract> element. Also it doesn't make sense at all because it puts the payload as the payload, which it is already is. Just remove that line.
Maybe the intention was to use <compression-compressed>?
Example:
<compression:extract>
<compression:compressed>#[payload]</compression:compressed>
<compression:extractor>
<compression:zip-extractor/>
</compression:extractor>
</compression:extract>
payload is already the default, so it is not needed.

Recursively invoke a Mule flow

Trying to figure out the proper way to recursively invoke a Mule flow.
We have a flow that builds an array of work to do as it runs, then recursively calls itself using a "Flow Reference" inside a "For Each" block. Problem is, we haven't figured out the correct way to pass parameters to this recursive flow, so we're not getting the results we expect.
We tried passing parameters using flow properties (setInvocationParameter() in Groovy), but it seems that these are shared across multiple instances of the flow.
For an example, we have the ForEach array iterating through an array containing [2. 3. 4], but depending on timing, some of these values are lost (we typically see 2, then 4 twice - skipping 3).
We've tried different Mule processing strategies without any luck. Mule's default queued-asynchronous has the issues described above. Synchronous doesn't seem to work at all (makes sense since our recursive model probably requires two instances to run at minimum).
Here's the relevant part of the configuration XML (the entire flow is quite large). At the end of the flow is this:
<foreach collection="#[sessionVars['actionArray']]"
counterVariableName="actionIndex"
rootMessageVariableName="actionVar" doc:name="For Each">
<scripting:component doc:name="Run Each Action">
<scripting:script engine="Groovy">
<![CDATA[def aa = message.getSessionProperty('actionArray')
def this_item = aa.get(message.getInvocationProperty('actionIndex'))
// Pass the desired action for the recursive call
message.setInvocationProperty('FlowAction', this_item)
log.info "Running $this_item" // <- Shows the correct item
return]]>
</scripting:script>
</scripting:component>
<flow-ref name="DoAction" doc:name="Do Action"/>
</foreach>
At the front of the flow, there's a logger that displays the "FlowAction" flow variable. When we test with my [2, 3, 4] array, this logger statement is driven three times (as expected), but usually with values 2, 4 and 4.
We're getting the same results on Mule 3.7 and an older 3.4 system we have (both are the Community Edition).
Thanks for any suggestions from the Mule mavens out there...
I'm not sure this is 100% correct, but here's what we did...
After spending a lot of time trying to get the "For Each" and "Flow reference" approach to work reliably, we gave up and switched to a different technique. Our alternative was to delete the For Each block and drive the flow recursively from a short Groovy script:
. . .
// Invoke the flow recursively for every item in the array
Flow flow = muleContext.getRegistry().lookupFlowConstruct("flow name")
actions.each // actions is an array of integers built earlier
{ item->
MuleMessage msg = message.createInboundMessage()
DefaultMuleSession sess = new DefaultMuleSession(flow, muleContext)
DefaultMuleEvent event = new DefaultMuleEvent(msg, MessageExchangePattern.ONE_WAY, sess)
// Copy the current inbound properties to the new message
message.getInboundPropertyNames().each
{
event.getMessage().setProperty(it, message.getInboundProperty(it), PropertyScope.INBOUND)
}
// Copy the current session variables to the new message too
message.getSessionPropertyNames().each
{
event.setSessionVariable(it, message.getSessionProperty(it))
}
// Now set the item we want processed as a flow variable
event.setFlowVariable("Action", item.toString())
// Finally, trigger the flow (which runs asynchronously)
flow.process(event).getMessage()
}
This is working properly in our environment now.

How to find current flow name in mule?

I need to capture current flow name into a variable.
I tried with #[flow.name] but no luck in mule 3.8.0
can anybody please assist me?
Based on the answer in this post: How to get caller flow name in private flow in Mule
There is a simplest way to get the flow name and put it into a variable:
<expression-component doc:name="Expression"><![CDATA[flowVars.flowName = flow.name;]]></expression-component>
Alternately, you can directly use expression #[mule:context.serviceName] in a variable :-
<set-variable variableName="myFlowName" value="#[mule:context.serviceName]" doc:name="Variable"/>
<!-- Print the value of variale in logger -->
<logger message="#[flowVars.myFlowName]" level="INFO" doc:name="Logger"/>
This will set your current flow name directly in variable
In mule 3.8.5 using Groovy script component,
flowVars.currentFlowName = eventContext.getFlowConstruct().getName();
I have been using #[flow.name] in 3.7.3 and just tried in 3.8.0 to make sure it had not been removed and it worked fine for me in logger and setting a flowVars value. I suggest posting up at least a snippet of your flow and maybe we can spot the issue you are having.
PS, not sure why flow.name is not in standard forms or really documented by Mule, and as it is not there continues to be some worries they will remove it. I have seen it stated more than just here that it is not accessible in MEL, but #[flow.name] is a MEL expression and does work. To use if for something like I Parse Template in exception strategies, I use sulthony's form, set a flowVars value in an expression and refer to that flowVars in my template.
You can access flow name in logger by using #[flow.name] but its not accessible in MEL. Use flowconstruct for getting flow name. Refer this answer
Hope this helps.

Mule MEL, how to get a property value?

In the Mule MEL, how to get a property value ?
In the java code, I did this:
eventContext.getMessage().setInvocationProperty("amount", 100);
I have tried these options
#[message.invocationProperty.invocation]
#[message.invocationProperty('invocation')]
#[message.getInvocationProperty().get('invocation')]
I realize that message is an instance of org.mule.el.context.MessageContext, then what is the correct syntax ?
Try #[message.inboundProperties['propertyName']] or #[message.invocationProperties['propertyName']]
If you set a variable with scope INVOCATION (with Message Enricher or Variable), you can get the variable with the syntax below:
#flowVars['your_Variable_Name']
Although the sintaxis is almost the same, it depends on the scope of the property variable, but the most usual way is:
#[flowVars['flow_var_name']]
In my personal opinion I don't recommend to use:
#[flowVars.variable]
Because in some complex environment with many messageContext switches the variable could get lost. I recommend to take a look on the next post from Mulesoft oficial blog that shows how to handle Properties and variables.
This answer for your comment
<set-variable variableName="amount" value="message.invocationProperties['amount']" />
Solution is
<set-variable variableName="amount" value="#[message.invocationProperties['amount']]" />
To get the Invocation properties of a message follow this syntax:
#[flowVars.parameter] or #[flowVars['paramater']]

Mule - Inject flow or session variable into Spring bean

I am trying to pass a variable to a Spring bean like so:
<component doc:name="Java">
<no-arguments-entry-point-resolver />
<prototype-object class="org.test.MyComponent">
<property key="fileName" value="#[sessionVars.filename]" />
</prototype-object>
</component>
But the expression never resolves? Is there a another way to do this?
This is a confusion with the spring configuration and Mule Expression language(MEL).
Point 1:
Even though the component is defined inside the Mule Config file. The elements (tags) <property/> is from the Springs Bean schema definition. So the attribute values of key and value are not interpreted by the MEL.
Point 2: As it is provided as setter injection which is invoked during loading(instantiation) the value of session variable(run time value) will not be available.
One possible solution to this would be to make the component implement Callable interface of Mule. So that you will have access to the MuleMessage which contains the session variable.
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
MuleMessage muleMessage = eventContext.getMessage();
muleMessage.getProperty("propertyName", PropertyScope.SESSION);
Hope this helps.
When the Mule server starts, each of the elements are loaded, and the component and spring-object are created. I don't think you can pass session variable or for that matter any variable other than context-properties to object creation happening at server start-up time.