Mule ESB: How to use MEL expression in Message Properties Key? - mule-esb

I'm using the message-properties component in mule. I need to set a dynamic key name as this is used to add custom headers to a http-request.
<message-properties-transformer doc:name="Message Properties" scope="session">
<add-message-property key="#[flowVars.name]" value="#[payload.split(":")[1]]"/>
</message-properties-transformer>
When logging the output, it shows that the key has not evaluated the MEL expression contained inside:
SESSION scoped properties: #[flowVars.name]=Basic pokpogytg788t878
Is there any way of setting a dynamic key name for a property in this component?

I have faced similar situation,where I had to set dynamic message properties.
I tried several things to set it with message-properties-transformer , but to no luck.
There is some bug filed for similar issue,below is the link
Cannot use MEL expression as key in Message Properties transformer
After trying for sometime I got that working with some workaround.
You can try working it around with Expression component.
<expression-component doc:name="Expression">
<![CDATA[message.outboundProperties[flowVars.name]=payload.split(':')1];]]>
</expression-component>
Not only you can read dynamic values from payload/variables.But you can also call your custom java/groovy methods in it.
Try below code snippet,and let us know if that works for you.
<flow name="testFlow">
<http:listener config-ref="HTTP_Listener_Configuration"
path="/test" doc:name="HTTP" allowedMethods="POST" />
<set-variable variableName="name" value="#["test"]"
doc:name="name" />
<expression-component doc:name="Expression">
<![CDATA[message.outboundProperties[flowVars.name]=payload.split(':')1];]]>
</expression-component>
</flow>

Related

how to read variable in assign message policy in APIGee

In Apigee
given a variable in javascript policy, example: var value = 123;
how to get this variable in the assign message policy?
by using {a} in the payload message is not reachable
For the variable to be available for use in any Apigee policy, you first have to make it a flow variable. You can use Apigee's JavaScript Object Model method called context to to this (see ref here). In your JS policy, you have var {some-value} = 123;. To make this available as a flow variable,introduce this line in your JS policy after the variable assignment: context.setVariable("preferred-variable-name", some-value);
You can now access this preferred-variable-name in your AM policy as show below:
<AssignVariable>
<Name>preferred-variable-name</Name>
<Ref>preferred-variable-name</Ref>
</AssignVariable>
Just to mention it is possible to pass the value directly in the policy as well as shown below
<AssignVariable>
<Name>variable_name</Name>
<Value>123</Value>
</AssignVariable>
Read more here.
The <Name> tag can be set to any name.
You have to set the variable in the context object using context.setVariable("variable-name", value);
Refer to this variable in the assign_message policy using {variable-name}.
You can just set the context variable in jsPolicy like this:
context.setVariable("a","123");
You can use it after in any of the policies.
Ex :-
<QueryParams>
<QueryParam name="a">{a}</QueryParam>
</QueryParams>

Add a Query parameter in Mule

Hi I want to add a query parameter Age = 23
I tried adding
message.inboundProperties.'http.query.params'.Age = '23'
In a expression
<expression-component doc:name="Expression"><![CDATA[message.inboundProperties.'http.query.params'.Age= '23';]]></expression-component>
It won't work.
Inbound properties are Immutable hence you must add it in outbound property to add a query param in your outbound http connector you can use the below
<http:request config-ref="HTTP_Request_Configuration" path="outway" method="POST" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="Age" value="23"/>
</http:request-builder>
</http:request>
To add properties to an outgoing message they need to be in the outbound scope:
message.outboundProperties.'http.query.params'.Age= '23'
You are trying to modify inbound properties but you can´t, they are inmutable
Properties have two main scopes: inbound and outbound.
Inbound properties are immutable, are automatically generated by the message source and cannot be set or manipulated by the user. They contain metadata specific to the message source that prevents scrambling of data formats or other processing mishaps later in the message’s lifecycle. A message retains its inbound properties only for the duration of the flow; when a message passes out of a flow, its inbound properties do not follow it (see image below).
https://docs.mulesoft.com/mule-fundamentals/v/3.7/mule-message-structure
You must add it to outbound as Ryan said.

HTTPTargetConnection - why proxy.pathsuffix gets appended to URL

I have created multiple target-end points based on my back-end servers. Each target end point has a fixed URL.
URL is configured as -
<HTTPTargetConnection>
<URL>https://example.com/test/</URL>
</HTTPTargetConnection>
I noticed that "proxy.pathsuffix" is automatically getting added to url (https://example.com/test/). How can I avoid this?
A bit outdated in reply - but, Assign Message works for this (to avoid JavaScript):
<AssignVariable>
<Name>target.copy.pathsuffix</Name>
<Value>false</Value>
</AssignVariable>
You'll need to create a new JavaScript callout policy in your proxy request flow. In this JavaScript callout, simply add a single line:
context.setVariable("target.copy.pathsuffix", false);

Working around the wildcard limitation in defining hierarchical APIs

Suppose I want to create the following APIs:
/movies/{movieId}/cast
/movies/{movieId}/crew
/movies/{movieId}/awards
On the recent versions of Apigee, wildcards are no longer allowed in the base URL. To achieve the ones above, we first created an API proxy /movies. We then defined three separate resources under it, each starting with a wildcard:
/*/cast
/*/crew
/*/awards
Here's a couple of questions:
Is this the only way to define wildcards in a hierarchical API structure?
Is there a way to define these into 3 separate API proxies?
Say you created an API with the basepath /movies and then consume /movies/jaws/cast. You can then crate a PreFlow policy to extract the path variable like this:
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-URI">
<DisplayName>Extract URI</DisplayName>
<FaultRules/>
<Properties/>
<URIPath>
<Pattern>/{movieid}/{function}</Pattern>
</URIPath>
</ExtractVariables>
You now have two variables, one for the variable and one for the actual service. Now you can create a Conditional Flow for each function (cast, crew, awards...) on the variable function rather than matching the path:
<Flow name="Cast">
<Description/>
<Request/>
<Response>
<Step>
<FaultRules/>
<Name>Assign-cast</Name>
</Step>
</Response>
<Condition>(function = "cast") and (request.verb = "GET")</Condition>
</Flow>
You may still need to do some magic to rewrite your target path, but your request proxy path will still be /jaws/cast but now you can run specific policies against a request for the cast of Jaws.
See http://apigee.com/docs/api-services/api/conditions-reference and http://apigee.com/docs/gateway-services/content/flow-variables-and-conditions for more info on Conditional Flow configuration.

How to add additional data to a mule payload?

I'm trying to add some additional static data to an inbound http message (received as URL parameters) payload before submitting it to an outbound http form based endpoint. My mule config is as follows :
<flow name="login" doc:name="login">
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8081/login" doc:name="Login"/>
<http:body-to-parameter-map-transformer doc:name="Body to Parameter Map"/>
<http:outbound-endpoint address="http://localhost:8090/mayapp/Main/login.do"
method="POST" contentType="application/x-www-form-urlencoded" exchange-pattern="request-response">
</http:outbound-endpoint>
</flow>
The above transforms the URL parameters to a http form POST (name/values pairs) very nicely. What I need now is the ability to add new name-value pairs to the POST(ed) data ? The form I'm posting to expects some static data (posted as hidden HTML fields) that I would like to handle as part of the transformation process.
I've managed to accomplish this using a custom component. I'm wondering if there's an easier way to handle this using Mule's native transformers / message processors !
First I would use a transformer and not a component for this, as it is really a transformation you're doing on the payload data.
Second I can't think of another transformer than the Groovy one to modify the Map payload created by the body-to-parameter-map-transformer. Something like:
<script:transformer>
<script:script engine="groovy">
<script:text>
payload['newKey'] = 'newValue'
</script:text>
</script:script>
</script:transformer>
You can use an expression-component as well:
<expression-component doc:name="change_payload">
<![CDATA[#[ message.payload = 'foo';]]]>
</expression-component>

Resources