How do you set message properties in Mule using Groovy? - mule

How do you set message properties in Mule using Groovy?
I need to set a message property from within a Groovy Scripting Component. Documentation on the subject does not appear to be easy to find.

You can set individual properties as follows:
message.setInvocationProperty('myFlowVariable', 'value') // sets a flow variable, like <set-variable/>
message.setOutboundProperty('myProperty', 'value') // sets an outbound message property, like <set-property/>
message.setProperty('myInboundProperty', 'value', PropertyScope.INBOUND) // sets an inbound property

In the scripting component you have available the message binding that is an instance of org.mule.api.MuleMessage, thus you can use the method org.mule.api.MuleMessage.addProperties(Map, PropertyScope) to add any property you need.

It depends on which version of Mule EE (and so then Groovy) you are using, but in recent versions of Mule (3.7.x) the easiest way is:
flowVars ['name_of_variable'] = 'value'
flowVars ['name_of_variable'] = 14
This for variables with Invocation scope, if you wan to store variable for Session scope, then:
sessionVars ['name_of_variable'] = 'value'
sessionVars ['name_of_variable'] = 14
Please use this site from Mulesoft for Scripting as reference.
https://docs.mulesoft.com/mule-user-guide/v/3.7/script-component-reference

Here is how I figured it out:
add schema to your flow if missing:
xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting"
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
now let's set session-variable 'account' with a custom Foo object using Groovy:
<scripting:transformer doc:name="Script">
<scripting:script engine="groovy"><![CDATA[
com.test.Foo f = new com.test.Foo();
f.setAccountId('333');
return message.setSessionProperty('account',f);]]>
</scripting:script>
</scripting:transformer>
above script will turn your Payload to NullPayload, because it is a transformer. If that' a concern, try this instead:
<enricher target="#[sessionVars['account']]">
<scripting:transformer doc:name="Script">
<scripting:script engine="groovy"><![CDATA[
com.test.Foo f = new com.test.Foo();
f.setAccountId('333');
return f;]]>
</scripting:script>
</scripting:transformer>
</enricher>
Enjoy. :)

Related

Mule esb 3.8 how to add variable into payload?

let say I have payload:
{ Name=User1, Age=29 }
and variable:
{ Address=Planet Earth}
I want to have a check if that variable not null then add it into payload.
So final result will be:
{ Name=User1, Age=29, Address=Planet Earth }
How? Was try via payload.Put(variable) but that not allow me such.
With DataWeave using a Transform component you can use the expression: payload ++ flowVars.variable
If you don't want or can't use DataWeave then you can use a MEL expression that uses the Java method Map.putAll() of the Map interface. You can not use <set-payload> because it doesn't return a value. Instead you can use the <expression-component> component.
Example:
<expression-component doc:name="Expression"><![CDATA[payload.putAll(flowVars.variable)]]></expression-component>

Retrieve properties value dynamically on run-time for a Mule flow

I have a requirement like an id will be passed through HTTP request and depending on that ID i need to invoke dynamically the properties values.
For one ID I need properties like
dgc.metamodel.CommunityToSync=Community1
dgc.metamodel.DomainToSync=Domain1
For another ID I need like
dgc.metamodel.CommunityToSync=Community2
dgc.metamodel.DomainToSync=Domain2
Is it possible to do this in Mule?
AFAIK, property file will be read at the first time server is run. Although there are many properties only one key (unique) which will be referenced.
However to accommodate this requirement, I think we should utilizing Java code. This code will responsible to read the certain property file based on request (id). Then read the property and set it to variable for further usage:
private Properties prop = new Properties();
private InputStream input = null;
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
String id = ((ParameterMap)message.getInboundProperty("http.query.params")).get("id");
input = getClass().getResourceAsStream("../property" + id + ".properties");
prop.load(input);
message.setInvocationProperty("communityToSync", prop.getProperty("dgc.metamodel.CommunityToSync"));
message.setInvocationProperty("domainToSync", prop.getProperty("dgc.metamodel.DomainToSync"));
I tested it with a simple flow
<flow name="propertyFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/prop" allowedMethods="GET" doc:name="HTTP"/>
<custom-transformer class="example.ReadProperty" doc:name="Java"/>
<logger message="CommunityToSync = #[flowVars.communityToSync], DomainToSync = #[flowVars.domainToSync]" level="INFO" doc:name="Logger"/>
</flow>
Execute it through browser: http://localhost:8081/prop?id=1 or http://localhost:8081/prop?id=2 to get the different result.
You can achieve this by reading the properties into a Map first:
You can load them directly into a map using Spring like so:
<spring:beans>
<spring:bean id="appProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<spring:property name="singleton" value="true"/>
<spring:property name="location" value="classpath:application.properties"/>
</spring:bean>
</spring:beans>
And access it dynamically in your flow using MEL similar to:
<logger message="My prop #[app.registry.appProps[flowVars.someKey]]" level="INFO" />
And you can build the key string however you want.
you can go with groovy to check bsed up on your requirement and send the properties as required.

Google Calendar Connector - Mule - Apikit

Well im trying to use the GCalendar connector in MuleStudio, the conector recibes an instance of org.mule.module.google.calendar.model.Event (See Doc)
How can i create an instance of the Event and pass it to the connector for it to create the event in GCalendar?
Here an image of the case
See Image
You can use MEL(Mule Expression Language) using standard Java syntax or expressions to create an instance of the Event class or you can use Spring etc. Here's a rough example that builds a list with an event and sets it as the payload:
<expression-component>
event = new org.mule.module.google.calendar.model.Event();
event.location = "America";
eventTime = org.mule.module.google.calendar.model.EventDateTime();
eventTime.date = "2015-12-16"'
event.start = eventTime;
event.end = eventTime;
message.payload = [event]
</expression-component>
You can then pass it by reference tot the connector using #[payload]
<google-calendars:batch-insert-event calendarId="bla#gmail.com" calendarEvents="#[payload]" />

Passing An Array Payload to Mule Salesforce Connector generates error

I have a expression component that creates a object of type string array for processing a delete request to salesforce. But the flow fails every time it goes beyond the expression.
The error I see on console is:
Could not find a transformer to transform "SimpleDataType{type=[Ljava.lang.String;, mimeType='/'}" to "CollectionDataType{type=java.util.List, itemType=java.lang.Object, mimeType='/'}".
<sub-flow name="DeleteAspenOrderInfo" doc:name="DeleteAspenOrderInfo">
<expression-component doc:name="Expression"> ArrayList queryresponse =flowVars['DeleteOidList'];
int size=queryresponse.size();
String[] idArray=new String[size];
int i=0;
for(HashMap map : queryresponse)
{
String aValue = map.get("Id");
idArray[i]=aValue;
i++;
}
payload= idArray;</expression-component>
<sfdc:delete config-ref="SalesforceConnector" doc:name="Salesforce">
<sfdc:ids ref="#[payload]"/>
</sfdc:delete>
<custom-transformer class="com.aspen.transformer.AOIDeleteTransformer" doc:name="Java"/>
</sub-flow>
Kindly advise if there is an alternate way to undertake this.
According to the connector's JavaDoc, the delete method has this signature:
public List<DeleteResult> delete (List<String> ids)
Therefore, change your expression component to output a List<String> instead of a String[].

How copy selected property (not all) from camel to activiti

Camel scenario:
read file
do something e.g store content in database
run activiti process and pass variable from previous step
RouteBuilder:
from("file:/home/work/Inbox")
.to("bean:sourceFileService?method=storeFile")
.to("activiti:Receive?copyVariablesFromProperties=true")
During call bean sourceFileService property 'sourceFileId' is set.
This variable should be transferred to the process Receive as variable.
If I don't use copyVariablesFromProperties any variable is not set in process.
One the other side when copyVariablesFromProperties=true then camel try pass all properties and exception occurs:
ActivitiException: couldn't find a variable type that is able to serialize GenericFile
(because one of property is object represents read file, there are 7 other unwanted property )
How pass only selected property to activiti endpoint or in camel any next 'to' ?
change sourceFileService's storeFile method signature as follows;
public String storeFile(... your other params, #OutHeaders Map headers) {
...
headers.put("sourceFileId", "32132132");
....
}
and you can access the set sourceFileId in your activiti endpoint
I have found that the use of copyVariablesFromProperties is not necessary.
The same is achieved by
.setBody().properties()
.to("activiti:Receive")
When in body is Map camel set variables for activiti process using that map.
But I still get exception for the same reason (pass unwanted, not serializable object).
The only solution I have found is
from("file:/home/work/Inbox")
.to("bean:sourceFileService?method=storeFile")
.setBody(method(Helper.class))
.to("activiti:Receive")
where
public class Helper {
#Handler
public Map getProcessVariables(Exchange exchange) {
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("sourceFileId, exchange.getProperty("sourceFileId"));
return variables;
}
}