Dynamic custom mediator parametres in wso2 ESB - wso2

I built custom mediator using articles http://wso2.com/library/2898/ and http://wso2.com/library/2936/ .
It looks like this:
<inSequence>
<property expression="local-name($body/*[1])" name="method" scope="default" type="STRING"/>
<MyMediator>
<header>SomeHeader<header/>
<topic>SomeTopic</topic>
</MyMediator>
</inSequence>
It works well, but one issue I didn't solve, how I can dynamically change value of header and/or topic mediators parameter?
When I tried to put something like get-property('method') instead of SomeHeader. It was delivered into mediator code like string, ebs didn't calculate it.
My question is how to change value of my custom mediators parameter to property value?

You can choose for exemple to use {} braces to say that your string is an XPath request. In your mediator, if you find {} in first and last position, use org.apache.synapse.util.xpath.SynapseXPath : create a new SynapseXPath with your xpath (the string between {}) and use stringValueOf(theMessageContext)

You can't pass any dynamic value to a custom mediator, but you can read any property within custom mediators.
public boolean mediate(MessageContext mc) {
String value = (String) mc.getProperty("SomeHeader");
}

Current implementation doesn't support for expressions as class mediator properties. Please refer Jira for more details.

Related

Store Value returned from Java Class in Class Mediator

In my WSO2 ESB, I have a created Java class, which produces a string value as output. Now I am calling my Java class with "Class Mediator". How can I store the value retured from my Java class in my WSO2 ESB and show that as log in Log mediator?
You can save values in property in class mediator as below,
public boolean mediate(MessageContext context) {
context.setProperty("testKey","Value in class mediator");
return true;
}
and access the stored values as below,
<log>
<property name="test log" expression="$ctx:testKey"/>
</log>
You need to set the property in your java class for example context.setProperty("propertyName","PropertyValue")
Now as the property is set in your java class then you can use it anywhere in your sequence by using the expression $ctx:propertyName or try using get-property(propertyName) both would fetch the value but $ctx is performance is faster when compared to get-property

Wanted to remove property name while printing the log in WSO2

Here I have one doubt
I am creating log mediator in WSO2 and setting one property msg and it gives me output as follows
[2017-08-04 18:13:10,041] [] INFO - LogMediator Msg = Msg Coming************************
Here I just want the output like Msg Coming************************ I dont want to print property name...
How I will able to do it..
Example
<property name="*******************" value="hello" />
or
<property name="*******************" expression="translate('some string to log', 'abcdefg.....z', '****************************')" />
In first case you will get unknown property, in second unkond property with unknown value. Why you need such logging

Dynamic URI based on file name/cfg file/property name

I am trying to pass a to URI value dynamically with a property value. That property value will be configured already in the cfg file.
When the file name is extracted using CamelFileNameOnly header, it has to get passed to the to Uri endpoint. So that the same name is referred in the code.
Please find my code below:
I have dropped a file with name KevinFile.txt in my server location= D:\Servers\jboss-fuse-6.2.0.redhat-133\data\myLocalFTP (file://data/myLocalFTP)
Config File
local.folder.url=file://data/myLocalFTP
KevinFile=file://data/KevinFileDirectory
Camel Route
<route id="awsRoute">
<from uri="{{local.folder.url}}"/>
<bean ref="processorClass" method="process"/>
<log message="myProperty value is ${exchangeProperty.myProperty}"/> <---Gives the fileName
<to uri="{{${exchangeProperty.myProperty}}}"/> <--This is the spot i am getting error :(
</route>
ProcessorClass.java
public class ProcessorClass implements Processor{
#Override
public void process(Exchange exchange) throws Exception {
String fileName = (String) exchange.getIn().getHeader("CamelFileNameOnly");
exchange.setProperty("myPropertyNew", fileName);
}
}
If I understand correctly, you need to specify "dynamic" vlue for the constant part of the producer. Instead of <to uri="{{${exchangeProperty.myProperty}}}"/> you can use recipientList or routingSlip:
<recipientList>
<simple>${exchangeProperty.myProperty}</simple>
</recipientList>
or
<routingSlip>
<simple>${exchangeProperty.myProperty}</simple>
</routingSlip>
Ah what your looking for is simply setting the header as a property. You can do that like this:
from("direct:start")
.setHeader("CamelFileNameOnly").simple("{{myPropertyName}}")
.to("file://data/myLocalDisk");
You can also simplify this by using the uri syntax available on the file component in this case (Thanks to Sergii for the recommendation). Just make sure you check the camel documentation for each component certain components rely on exchange headers, while others can leverage URI properties.
from("direct:start")
.to("file://data/myLocalDisk?fileName={{myPropertyName}}");
Its also worth noting that if you have logic that you want to use before setting the header you can have the setHeader call a bean.
from("direct:start")
.setHeader("CamelFileNameOnly").bean(MyPropertyLogicBean.class, "someMethod({{myPropertyName}})")
.to("file://data/myLocalDisk");
Use the camel properties component to get this property to resolve.
Reference: http://camel.apache.org/properties.html

PayloadFactory - Enrich with Response

I make a callout that response is like this:
<ns:return>
<ax2446:contract>
<ax2446:array>variable1</ax2446:array>
<ax2446:array>value1</ax2446:array>
</ax2446:contract>
<ax2446:contract>
<ax2446:array>variable2</ax2446:array>
<ax2446:array>value2</ax2446:array>
</ax2446:contract>
<ax2446:contract>
<ax2446:array>variable3</ax2446:array>
<ax2446:array>value3</ax2446:array>
</ax2446:contract>
<ax2446:documents>
<ax2446:array>attachement1</ax2446:array>
<ax2446:array>D:\AUTO\filename-1.txt</ax2446:array>
</ax2446:documents>
<ax2446:documents>
<ax2446:array>attachment2</ax2446:array>
<ax2446:array>D:\AUTO\filename-2.txt</ax2446:array>
</ax2446:documents>
<ax2446:process>TEST_PROCESS</ax2446:modulo>
</ns:return>
i want to create a new payload with contracts values (the number can change)
<p:instantiateProcess xmlns:p="http://carbon.sample">
<xs:process xmlns:xs="http://carbon.sample">TEST_PROCESS</xs:process>
<ns:contract xmlns:ns="http://carbon.sample">
<xs:array xmlns:xs="http://carbon.sample">variable1</xs:array>
<xs:array xmlns:xs="http://carbon.sample">value1</xs:array>
</ns:contract>
<ns:contract xmlns:ns="http://carbon.sample">
<xs:array xmlns:xs="http://carbon.sample">variable2</xs:array>
<xs:array xmlns:xs="http://carbon.sample">value2</xs:array>
</ns:contract>
<ns:contract xmlns:ns="http://carbon.sample">
<xs:array xmlns:xs="http://carbon.sample">variable3</xs:array>
<xs:array xmlns:xs="http://carbon.sample">value3</xs:array>
</ns:contract>
</p:instantiateProcess>ยด
i get all the contract by:
<property
expression="//ns:return/ax2431:contract"
name="contract" scope="default" type="STRING"
xmlns:ax2431="http://vo.carbon.sample/xsd" xmlns:ns="http://carbon.sample"/>
I try with payloadfactory, by i dont know how to enrinch (if it is correct to use this mediator) the message to make a call to a new web service. or if i have to make the payload with an iterator...
can anybody help me? thanks
You appear to have a few options:
Use a Payload factory
Use XSLT
Use Script meditator
I suspect all 3 could get the result you are after. It is a question of which you feel most comfortable with. Personally, I would head down the Script mediator route, mapping between two XML payloads, here is an example: http://nimbleapi.com/2016/05/javascript-mapping-between-xml-payloads/
Once you get the contract list you can use iterate mediator to iterate the list and inside the iterator you can add payloadFactory mediator to create payload, then, same time you can send the modified payload to a new web service.
Please find the following links which explain in detail how you use iterate mediator.
http://sparkletechthoughts.blogspot.com/2012/08/how-to-use-iterator-mediator-to-iterate.html
In addition to XSLT or Script meditators, ForEach mediator is also an option.
https://docs.wso2.com/display/ESB490/ForEach+Mediator

Mule - Pass Parameters to datamapper and access them in xpath conditions

How to pass parameters to datamapper in mule and access them. (In XSLT, I pass them as context parameters, receive them in param and access using $ symbol). I need to do the same thing in datamapper. Any suggestions/links/example are appreciated.
Approach1:
We are using invokeTransformer method in datamapper
output.abc= invokeTransformer("MyTransformer",input.abcdef);
This MyTransformer is a java component which has this default method overridden.
#Override
public String transformMessage(MuleMessage message, String outputEncoding)
throws TransformerException {
System.out.println("Inside transformer" +message.getProperty ("sessionVariable1",PropertyScope.SESSION));
return message.getProperty("sessionVariable1",PropertyScope.SESSION);
But, the problem is I am not calling this transformer from mule flow. But, invoking it from datamapper. Hence the argument 'message' does not get passed. So, Unable to retrive that session variable to return to datamapper. Is there a way to send this argument(MuleMessage from datamapper)?
You can use input arguments with DataMapper and then refer to them in the output:
<set-variable variableName="testvar" value="value of testvar"/>
<data-mapper:transform config-ref="new_mapping_grf"">
<data-mapper:input-arguments>
<data-mapper:input-argument key="testvar">#[flowVars['testvar']]</data-mapper:input-argument>
</data-mapper:input-arguments>
</data-mapper:transform>
and
output.myField = invokeTransformer("MyTransformer",inputArguments.testvar);
or
output.myField = inputArguments.testvar;
Adding input arguments available in the DataMapper GUI through the input side green plus icon.