6

I have a Java method that will read some flow variables, do some aggregation and append the result to a list that already exists in another flow variable.

For this reason the method expects a MuleMessage. I thought it's obviously possible to pass a MuleMessage to a java method, using the message MEL variable like:

<invoke object-ref="Aggregator" method="aggregateSingle" methodArguments="#[message]" doc:name="Invoke"/>

But it turned out that this passes a MessageContext object instead. But I need to set InvocationVariable so this class is not useful. I know I've set variables in groovy, so perhaps this would work (I thought):

<invoke object-ref="Aggregator" method="aggregateSingle" methodArguments="#[groovy:message]" doc:name="Invoke"/>

But no, this somehow passes the payload instead of the MuleMessage.

So the only way I've found to do this is to actually call it in a Groovy component as below. Which means I have to create a new Aggregator object every time, instead of using the spring:bean as I'd planned.

                <scripting:transformer doc:name="aggregateSingle">
                    <scripting:script engine="Groovy"><![CDATA[
                        new com.example.Aggregator().aggregateSingle(message);
                        message
                    ]]></scripting:script>
                </scripting:transformer> 

Is there no way to pass a MuleMessage object to the Java method using invoke?

rewolf
  • 5,561
  • 4
  • 40
  • 51
  • Why would you want to use invoke component and then couple it with the Mule API ? ... the idea of having 2 ways of creating components is that one way ties you to the Mule API and the other does not. – Sudarshan Jul 07 '15 at 01:32
  • @Sudarshan I want to keep the mule code clean. There are two branches in my flow, one which uses `scatter-gather` and another which is sequential. The latter results in a similar object as which is produced by the AggregationStrategy of the former. I'd thus like to re-use the functionality from the AggregationStrategy. It also allows for more fine-grained testing. Are you asking why I want to pass a `MuleMessage` (ie. Mule API-specific class) to my class? It's because its easier than passing 5 individual flowVariables. – rewolf Jul 07 '15 at 01:37
  • 1
    +1'd your question, however I would consider creating a POJO of the 5 flowVariables and passing the POJO into the component, especially if you are considering test ability and clean code. Looking forward to a answer :) – Sudarshan Jul 07 '15 at 02:12
  • 2
    Note that you can call a POJO from Groovy by looking it up in the registry first, then invoking it. – David Dossot Jul 07 '15 at 14:09

1 Answers1

1

By default mel uses message context to refer to the message variable, this in fact is just for helping out with common expressions such as message.payload != null (in previous versions of mule you would have to check for null payload). I have debugged the invoke element and unfortunately no expressions would cut it, but this is an equivalent method that you can use

<expression-transformer expression="#[groovy: Aggregator.aggregateSingle(message)]" />

This works as expected because groovy has direct access to the bean registry so you can reference the bean name and keep it as a spring bean (as I imagine you want to have)

  • This worked, kinda. It definitely should work. But for some reason it's invoking the method twice. – rewolf Jul 08 '15 at 01:50
  • This was an MUnit bug. I upgrade from 3.6.0-SNAPSHOT to 3.6.0-RC1-SNAPSHOT and this error went away. However, other MUnit bugs have appeared with FlowVariables disappearing. But your answer was good, thanks! :D – rewolf Jul 08 '15 at 06:50