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.
Related
<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.
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.
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>
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¶m2=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
I'm involved in a proxy service development using WSO2.
In my sequence I've saved the initial current message in a property using the following:
<property name="InitialMessage" expression="$body" scope="default" type="STRING"/>
and now I need to rebuild the initial message using the payload factory mediator. Am I right? What are some considerable alternatives?
Could someone show me the right syntax in this case?
yes your method is correct, But I would suggest you to save only the required properties from your incoming message and use them in building the new message. Sample Syntax is given below
<payloadfactory>
<format>
<m:checkpriceresponse xmlns:m="http://services.samples/xsd">
<m:code>$1</m:code>
<m:price>$2</m:price>
</m:checkpriceresponse>
</format>
<args>
<arg expression="//m0:symbol" xmlns:m0="http://services.samples/xsd">
<arg expression="//m0:last" xmlns:m0="http://services.samples/xsd">
</arg></arg></args>
</payloadfactory>
I've solved my problem using the enrich mediator: Here you are how ...
I've saved my initial message in a property InitialMessage in this manner ...
<property name="InitialMessage" expression="$body" scope="default" type="STRING"/>
and after I've used the enrich mediator in this manner
<enrich>
<source type="property" clone="true" property="InitialMessage"/>
<target type="body"/>
</enrich>
It's working ...
I hope this could be useful ...