Concat operation in property mediator of wso2 is invalid - wso2

<property name="Code" expression="json-eval($.Code)" scope="default" type="STRING"/>
<property name="Endpoint" expression="json-eval($.data.InternalConfig.Events.Code.Endpoint)" scope="default"
<property expression="fn:concat(json-eval($.data.InternalConfig.Events'.'get-property('Code')'.'Endpoint)" name="URL" type="STRING" scope="default"/>
one property is fetching from payload and another from respository , i am trying to merge into 1 property

I believe that you are trying to extract the data from the payload using dynamic values during the runtime. If yes, we can make use of Script Mediator in the WSO2 platform to access the JSON payloads.
For example:
Given below is a sample payload, and you are trying to extract the data: 'some value here' from the payload using the code and endpoint values
{
"userId": 10,
"code": 1,
"body": {
"id": 2,
"endpoint": "some-key",
"1": {
"anotherId": 30,
"title": "Lorum ipsum",
"some-key": "some value here"
}
}
}
Given below is a sample mediation sequence with the Script mediator to achieve your requirement
<?xml version="1.0" encoding="UTF-8"?><sequence xmlns="http://ws.apache.org/ns/synapse" name="mediation-sequence">
<script language="js">
<![CDATA[
// read the JSON payload from the message context
var payload = mc.getPayloadJSON();
// read the property values
var code = payload["code"];
var endpoint = payload["body"]["endpoint"];
var extracted_value = payload["body"][code][endpoint];
// set the extracted value as property to message context
mc.setProperty("ExtractedValue", extracted_value);
]]>
</script>
<log level="custom">
<property name="Extracted value" expression="$ctx:ExtractedValue" />
</log>
</sequence>
Hope this helps you to achieve your requirement.

Related

Replace a body parameter based on value that client sent

I created a API in WSO2 integrator studio contain the below body to receive the application requests.
{"count": "2000",
"Name": "22312312"
},
For responding to above request, I have to send the following JSON body toward the endpoint:
{"count": "2000",
"Name": "BANK"
},
As you can see, the difference between to bodies is about "NAME" value. In this scenario, each client send its own unique number in "Name" parameter, and I have to translate it into a String Name (in WSO2 Enterprise integrator) and send it to the endpoint.
How can I manage this in Integrator studio?
Here is how you can do it. You can have the mappings in a LocalEntry and then use a combination of Property mediators and Enrich mediator to select the Name and replace the Code. Check the following.
Local Entry
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="Mappings" xmlns="http://ws.apache.org/ns/synapse">
<Mappings xmlns="">
<bank>
<code>22312312</code>
<name>bank</name>
</bank>
<bank>
<code>22312313</code>
<name>bank2</name>
</bank>
<bank>
<code>22312314</code>
<name>bank3</name>
</bank>
</Mappings>
</localEntry>
API
<?xml version="1.0" encoding="UTF-8"?>
<api context="/bank" name="BankAPI" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST" url-mapping="/code">
<inSequence>
<property expression="get-property('Mappings')" name="localEntry" scope="default" type="OM"/>
<property expression="json-eval($.Name)" name="BankCode" scope="default"/>
<property expression="$ctx:localEntry//bank[code = $ctx:BankCode]/name/text()" name="BankName"/>
<enrich>
<source type="property" clone="true" property="BankName"/>
<target xpath="json-eval($.Name)"/>
</enrich>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Request and Response
{
"count": "2000",
"Name": "22312313"
}
{
"count": "2000",
"Name": "bank2"
}
If your mapping is dynamic, for example, if you need to pass the code to another API and get the Name, you can still use the same logic above with the Enrich mediator. Instead of reading from the LocalEntry you can get the data from the API.

How to get json property when I use the Property Mediator?

I use the Property Mediator to get a registry resource, it returns me a json string, but how can I get the property in the json string?
my code example:
test-file.json like so
{
"mappings": {
"mapping": {
"ep_1": "http://localhost:8280/services/ep_1",
"ep_2": "http://localhost:8280/services/ep_2",
"ep_3": "http://localhost:8280/services/ep_3"
}
}
}
I do like this:
<property expression="get-property('registry','conf:customresource/test-file.json')" name="JsonContent" scope="default" type="STRING"/>
<property expression="????" name="endpointUrl" />
how to get the property 'ep_1' in the 'endpointUrl' Or is there any other way to get the property 'ep_1'? thx
Try the following.
expression="json-eval($ctx:JsonContent.mappings.mapping.ep_1)"
If above does not work, try this.
expression="$ctx:JsonContent//mappings/mapping/ep_1"
Saving the input JSON to a property:
<property expression="json-eval($)" name="var_in_JSON" scope="default" type="STRING"/>
!!! Don't use dots (.) in the json property name !!!
...
Using data from a saved json property:
<property expression="json-eval($ctx:var_in_JSON.sub_param)" name="sub_param" scope="default" type="STRING"/>
The answer in your case:
<property expression="json-eval($ctx:JsonContent.ep_1)" name="ep_1" scope="default" type="STRING"/>
You can load json file from registry to payload, and make json-eval on payload. It is dirty solution, but it works ;):
<property expression="base64Decode(get-property('registry','conf:customresource/test-file.json'))" name="JsonContent" scope="default" type="STRING"/>
<payloadFactory description="Build Payload Response" media-type="json">
<format>$1</format>
<args>
<arg evaluator="xml" expression="$ctx:JsonContent" xmlns:payload="http://ws.apache.org/commons/ns/payload"/>
</args>
</payloadFactory>
<property expression="json-eval($.mappings.mapping.ep_1)" name="endpointUrl" scope="default" type="STRING"/>
Best regards
I have done with this question.You have to use XML content instead of JSON, then set content into a Property Mediator which type filed is OM, and you can use xpath expression to get any value you want in your XML content.
code example
XML content:
<mappings>
<mapping>
<ep_1>http://localhost:8280/services/ep_1</ep_1>
<ep_2>http://localhost:8280/services/ep_2</ep_2>
<ep_3>http://localhost:8280/services/ep_3</ep_3>
</mapping>
</mappings>
<property expression="get-property('registry','conf:customresource/test-file.xml')" name="XmlContent" scope="default" type="OM"/>
<property expression="$ctx:XmlContent/mapping/ep_1" name="endpointUrl" />
After that, the value will been set into the property named endpointUrl.
Last, please note the expression of second Property mediator,you get black value if you do like this $ctx:XmlContent/mappings/mapping/ep_1.Hope its helpful for someone.

Enrich Payload in WSO2

I have a JSON array of the following structure.
{"paymentItems": [
{
"amount": "180000",
"code": "28"
},
{
"amount": "396000",
"code": "06"
},
{
"amount": "1460000",
"code": "01"
}
]
}
Am trying to enrich each item in the array list with an additional JSON value.
<foreach expression="//paymentItems" id="1">
<sequence>
<property expression="//paymentItems/amount" name="amount" scope="default" type="STRING"/>
<property expression="//paymentItems" name="body" scope="default" type="STRING"/>
<log>
<property expression="$ctx:amount" name="INIDIVIDUAL_AMOUNT"/>
</log>
<script language="js"><![CDATA[var amount = mc.getProperty('amount'); var naira = amount/100; mc.setProperty("nairaValue", naira);]]></script>
<log>
<property expression="get-property('nairaValue')" name="NAIRA_VAL"/>
</log>
<property expression="get-property('nairaValue')" name="naira" scope="default" type="STRING"/>
<enrich>
<source type="custom" xpath="$ctx:nairaValue"/>
<target action="child" type="body"/>
</enrich>
</sequence>
</foreach>
As you can see I process the value in the foreach and then use the result and try to add to the array item but it throws no errors and does not add the value.
Foreach mediator does the following
first take a clone of the original message
take an iterated element from the original message (using XPath)
Create a new message context by adding the iterated element to the cloned envelope
Do the mediation steps given in the sequence for that new message context
Since for each iteration, we are cloning a new message context (say context2), and the original message context(say context1) is a separate one, we cannot enrich from context2 to context1.
That's the reason for the behaviour you are experiencing.
As a remedy, you can do the iteration itself from the script mediator and alter the message as required.

Wso2am custom sequence - how to log username

I have created a custom sequence in wso2am, in order to convert a rest web service call, to a soap call.
I would like to have the username of the user that makes the actual call, so as to log it, and use it in the soap body.
I tried by accessing the tenant.id and tenant domain variables but the are not available. I tried the END_USER_NAME var but that was also null
<property name="domain" expression="$ctx:tenant.info.domain" />
<property name="user" expression="substring-before(get-property('END_USER_NAME'), '#')" />
Is something like that possible?
if not, is it possible to deduce the username by means of the authheader?
I think you can use context property api.ut.userId in your sequence.
For example
<property name="user" expression="substring-before(get-property('api.ut.userId'), '#')" />
You can get the username from JWT token. Look here for enabling JWT token. Then extract any user claim youwant. I had explained it at,
http://lahiruwrites.blogspot.com/2016/06/access-jwt-token-in-mediator-extension.html.
Pasting below for your reference(You can see how to get enduser),
<?xml version="1.0" encoding="UTF-8"?>
<sequence
xmlns="http://ws.apache.org/ns/synapse" name="Test:v1.0.0--In">
<log level="custom">
<property name="--TRACE-- " value="API Mediation Extension"/>
</log>
<property name="authheader" expression="get-property('transport','X-JWT-Assertion')"></property>
<script language="js"> var temp_auth = mc.getProperty('authheader').trim();var val = new Array();val= temp_auth.split("\\."); var auth=val[1];var jsonStr = Packages.java.lang.String(Packages.org.apache.axiom.om.util.Base64.decode(auth), "UTF-8"); var tempStr = new Array();tempStr= jsonStr.split('http://wso2.org/claims/enduser\":\"'); var decoded = new Array();decoded = tempStr[1].split("\"");mc.setProperty("enduser",decoded[0]); </script>
<log level="custom">
<property name=" Enduser " expression="get-property('enduser')"/>
</log>
</sequence>

Is it possible to extract and/or pass along a query parameter in ESB REST proxy service

I am building a ReST to ReST proxy service. I need to be able to pass along some query parameters to that service that are incoming with the request. E.g.
myhost.zz/proxyService?foo=1&bar=2
When I define such proxy - and later try to extract the value of 'foo' I get null.
So is it possible to achieve?
You shouls define an API (if you really want a proxy service, look at the end of this answer) :
<api xmlns="http://ws.apache.org/ns/synapse" name="proxyService" context="/proxyService">
<resource methods="POST GET OPTIONS DELETE PUT">
<inSequence>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2" type="STRING"></property>
<log level="custom">
<property name="foo" expression="get-property('query.param.foo')"></property>
<property name="bar" expression="get-property('query.param.bar')"></property>
</log>
</inSequence>
</resource>
</api>
call it with this url : http://host:port/proxyService?foo=12&bar=14
look at wso2-esb-service.log : INFO __SynapseService foo = 12, bar = 14
in the "resource", you can define a uri-template (URL Style = uri-template) with, for exemple, "/{scope}/*" and then when you call your api with http://host:port/proxyService/toto?foo=12&bar=14, you can access the "scope" with get-property('uri.var.scope')
to send a REST request, use a http endpoint with a uri-template using the same logic : uri-template="http://other_host:port/Service/{uri.var.scope}/truc?abc={query.param.foo}&dfc={query.param.bar}"
-->
If you want to use a proxy service, you can access to query parameters like this :
request : http://esb:8280/services/MonService?param1=val1&param2=val2
<property name="PARAM1"
expression="tokenize(substring-after(syn:get-property('To'),'param1='),'&')"
scope="default"
type="STRING"/>
<property name="PARAM2"
expression="tokenize(substring-after(syn:get-property('To'),'param2='),'&')"
scope="default"
type="STRING"/>
you can use synapse xpath variable $url to read the query parameter values.
check this[1] for example.
Reading Dynamic query parameter in WSO2 APIM