Dynamically add new element to json payload in WSO2 EI by using enrich mediator - json

I need to enrich existing json payload with new elements which is dynamically passed to existing payload instead of static value. Can anyone please help me?
Existing payload:
{
"Type":"CAR",
"Identifier":"2db23c39-9d3f-4e61-b3c5-e8725a2f1b90",
"ListingType":"New",
"SaleStatus":"For Sale"
}
Expected :
{
"Type":"CAR",
"Identifier":"2db23c39-9d3f-4e61-b3c5-e8725a2f1b90",
"ListingType":"New",
"SaleStatus":"For Sale",
"messageId":"urn:uuid:ccdafb72-c4"
}
Here messageId is ESB generated MessageID automatically.
<!-- ************API Request set to incomingRequest property************ -->
<property description="incomingRequest" expression="json-eval($.)" name="incomingRequest"
scope="default" type="STRING"/>
<payloadFactory media-type="json">
<format>$1</format>
<args>
<arg evaluator="xml" expression="get-property('incomingRequest')"/>
</args>
</payloadFactory>
<enrich description="">
<source type="inline" clone="true">
<messageId xmlns="">evaluate(get-property('operation','messageId'))
</messageId>
</source>
<target action="child" xpath="//jsonObject" />
</enrich>
<enrich>
<source clone="true" xpath="//jsonObject" />
<target type="body" />
</enrich>
<log level="full"/>
**Getting Wrong output**
{
"Type":"CAR",
"Identifier":"2db23c39-9d3f-4e61-b3c5-e8725a2f1b90",
"ListingType":"New",
"SaleStatus":"For Sale",
"messageId": "evaluate(get-property('operation','messageId'))"
}
Note:
I have followed this

Inline content on the enrich mediator is not evaluated. (considered as string)
So, we can use the property mediator to evaluate the expression.
<property name="prop1" expression="get-property('operation','messageId')"/>
Then we can use the above property in enrich mediator.
<enrich description="">
<source type="property" property="prop1"></source>
<target action="child" xpath="//jsonObject" />
</enrich>
BTW, In latest product versions, the Enrich mediator has the native JSON support.
More details in Here

I had similar scenario where i wanted to append some elements to a received json response:
First i got the response received into a property:
property expression="json-eval($)" name="RESPONSE" scope="default"
type="STRING"
Then i created a payload and added the new properties:
<payloadFactory media-type="json">
<format>
{"details": $1,
"timestamp":"$2",
"value":"$3"}
</format>
<args>
<arg evaluator="xml"
expression="get-property('RESPONSE')" />
<arg evaluator="xml"
expression="get-property('REQUEST_TIMESTAMP')" />
<arg evaluator="xml"
expression="get-property('VALUE')" />
</args>
</payloadFactory>
Then I returned the response using loopback. Note that REQUEST_TIMESTAMP and VALUE are defined as properties.

Related

Best way to remove JSON field using WSO2 EI Enrich Mediator?

I have a JSON Object that looks like this:
{"firstName":"Todd","lastName":"Jones","age":32}
My question is how can I remove the age field? I was looking in the Enrich Mediator documentation and noticed an example to remove selected parts from a payload:
Sample 7 - Remove selected parts from the payload ( this feature is available from EI 6.6.0 WUM level 1595516738094 )
<target>
<inSequence>
<enrich>
<source clone="true" xpath="json-eval($.store.book[*].author,$.store.book[0])"/>
<target type="body" action="remove"/>
</enrich>
<respond/>
</inSequence>
<outSequence/>
</target>
This would not work for me however because it is available on EI 6.6.0 and I am on EI 6.1.1. How else could I go about achieving the intended result?
As an alternate approach to Enrich Mediator and PayloadFactory Mediator, you can use the Script Mediator to remove the property. Given is a sample, deleting the age property
<property name="JSONPayload" expression="json-eval($.)" />
<script language="js">
<![CDATA[
// var log = mc.getServiceLog();
var response = mc.getProperty("JSONPayload");
var jsonPayload = JSON.parse(response);
delete jsonPayload['age'];
// log.info(JSON.stringify(jsonPayload));
mc.setPayloadJSON(jsonPayload);
]]>
</script>
If your payload is only 3 elements I reckon you could just go with the payloadfactory.
<payloadFactory media-type="json">
<format>
{"firstName":"$1","lastName":"$2"}
</format>
<args>
<arg evaluator="json" expression="$.firstName"/>
<arg evaluator="json" expression="$.lastName"/>
</args>
</payloadFactory>
You might have to enable the JSON stream formatter/builder for this as described here. https://docs.wso2.com/display/EI611/PayloadFactory+Mediator
If the above doesn't work you could also first put the firstName and lastName into separate properties and then reference it as a context property.
I.e. <arg evaluator="xml" expression="$ctx:firstName"/>

How can I create a JSON payload with text containing XML in it?

I try to create an automatic JIRA problem reporting (in some FAULT sequences.
I make a JSON payload for JIRA APIs what works just fine for text.
I would like to however report to JIRA a SOAP request and response whereby I could investigate on the issue.
my question is how can I create a JSON payload with text containing XML in it?
I get this exception in WSO2 ESB
[2016-09-18 21:46:31,774] ERROR - NativeWorkerPool Uncaught exception
java.lang.Error: Error: could not match input
at org.apache.synapse.commons.staxon.core.json.stream.impl.JsonScanner.zzScanError(JsonScanner.java:530)
at org.apache.synapse.commons.staxon.core.json.stream.impl.JsonScanner.yylex(JsonScanner.java:941)
payload which I want to generate
<payloadFactory description="" media-type="json">
<format>
{
"fields": {
"project":
{
"key": "$1"
},
"summary": "$2",
"description": "$3",
"issuetype": { "name": "$4" }
}
}
</format>
<args>
<arg evaluator="xml" expression="$func:projectKey"/>
<arg evaluator="xml" expression="$func:summary"/>
<arg evaluator="xml" expression="$func:description"/>
<arg evaluator="xml" expression="$func:issueType"/>
</args>
</payloadFactory>
and I want to send some text containing XML into the parameter $func:description. When I sent only poor XML into the $func:description, the payload Factory transferred into into JSON what is not needed in this case, the the XML is supposed to be a text - the message
for the completeness to get the XML message I used
<property expression="$body" name="request"
scope="default" type="STRING"/>
call the end-point
<property expression="$body" name="response"
scope="default" type="STRING"/>
and I need to know bind "request" + "response" into $func:description
If the XML is well-formed you can simply set messageType property to application/json and do the conversion automatically. Refer this for more details.
Or else you can use the payload Factory mediator or Enrich mediator to custom build your Json.
create the payload with the XML structure you like.
use JS script mediator to modify one node as CDATA.
change the content type.
My proxy config, please do the change you need for your requirement:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="XMLinsideJSON"
transports="http https"
startOnLoad="true">
<target>
<inSequence>
<property name="BOK" expression="//*[1]" type="OM" scope="default"/>
<enrich>
<source type="inline" clone="true">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<fields xmlns="">
<summary xmlns=""/>
<project xmlns=""/>
<description xmlns=""/>
<issuetype xmlns="">
<name xmlns=""/>
</issuetype>
</fields>
</soapenv:Body>
</soapenv:Envelope>
</source>
<target type="envelope"/>
</enrich>
<script language="js">
importPackage(Packages.org.apache.axiom.om);
var elem= mc.getEnvelope().getBody().getFirstElement().getFirstElement();
var myText = elem.getOMFactory().createOMText(elem, mc.getProperty("BOK"), OMNode.CDATA_SECTION_NODE);
elem.addChild(myText)
</script>
<property name="messageType" scope="axis2" value="application/json"/>
<respond/>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
</proxy>
My request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<payload>
<response>
<data>AAA</data>
</response>
</payload>
</soapenv:Body>
</soapenv:Envelope>
My response:
{"fields":{"summary":"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Body>\n <payload>\n <response>\n <data>AAA</data>\n </response>\n </payload>\n </soapenv:Body></soapenv:Envelope>","project":null,"description":null,"issuetype":{"name":null}}}

Converting input XML to JSON format in WSO2 ESB

I want to convert the input XML to JSON format in WSO2 ESB.
I have tried using the property mediator but it is not working,
<property name="messageType" value="application/json" scope="axis2" type="STRING"></property>
<property name="Content-Type" value="application/json" scope="transport" type="STRING"></property>
Try this configuration:
<inSequence>
...
</inSequence>
<outSequence>
<property name="messageType" value="application/json" scope="axis2"></property>
<respond/>
</outSequence>
You just need to add formatter (which is define by messageType property) to format out going message.
<property name="messageType" value="application/json" scope="axis2" type="STRING"></property>
Content-Type property is used to build incoming message to the format of the SOAP, which is used inside the ESB. If incoming message is XML you can use the following builder. Adding this property is not compulsory, if the "Content-Type" is sent with the incoming message headers ESB automatically pic it and build the message.
<property name="Content-Type" value="application/xml" scope="transport" type="STRING"></property>
Also make sure you have enable the "application/json" message formatters inside the axis2.xml file. this can be found inside the repository/conf/axis2 folder.
Let's assume your xml input is,
<name>abc</name>
<id>123</id>
Then you need to convert it to Json format as,
{
"name" : "abc",
"id" : "123"
}
You can use PayloadFactory mediator to convert XML to JSON format
<payloadFactory media-type="json">
<format>
{
"name" : "$1",
"id" : "$2"
}
</format>
<args>
<arg evaluator="xml" expression="//name"/>
<arg evaluator="xml" expression="//id"/>
</args>
</payloadFactory>
Hope this helps!!

wso2 API Manager - How to publish an API using a template?

I have been experimenting with wso2 API Manager 1.8.0 to expose a back end(http/post) system as a REST API. I am able to get it working, but I had to edit the API configuration through the Service Bus source view as pasted below. I would like to have the same template used for all of the new APIs that get published using API Publisher to ensure that we don't have to edit the service bus source every time an API get created.
Please suggest any options that you may have used..
<inSequence>
<script language="js" key="transform_script" function="buildQueryString"/>
<property name="uri.query" expression="get-property('queryString')"/>
<filter source="$ctx:AM_KEY_TYPE" regex="PRODUCTION">
<then>
<property name="Authorization"
expression="fn:concat('Basic ', base64Encode('testuser:testuser#1'))"
scope="transport"/>
<send>
<endpoint name="testuser--AddNumbers_APIsandboxEndpoint_0">
<http method="POST"
uri-template="https://testhost:8443/test/http/6731cc67-3850-4b9b-b486-62cf2a664b46?${uri.query}"/>
</endpoint>
</send>
<bam>
<serverProfile name="bam-profile">
<streamConfig name="org_wso2_apimgt_statistics_destination" version="1.0.0"/>
</serverProfile>
</bam>
</then>
<else>
<property name="Authorization"
expression="fn:concat('Basic ', base64Encode('testuser:testuser#1'))"
scope="transport"/>
<send>
<endpoint name="testuser--AddNumbers_APIsandboxEndpoint_0">
<http method="POST"
uri-template="https://testhost:8443/test/http/6731cc67-3850-4b9b-b486-62cf2a664b46?${uri.query}"/>
</endpoint>
</send>
<bam>
<serverProfile name="bam-profile">
<streamConfig name="org_wso2_apimgt_statistics_destination" version="1.0.0"/>
</serverProfile>
</bam>
</else>
</filter>
</inSequence>
<outSequence>
<payloadFactory media-type="json">
<format>
{
"apiName": "$1",
"apiVersion": "$2",
"runResponse":
{
"runId": "$3",
"runStart": "$4",
"runEnd": "$5",
"flowResponse": "$6",
"flowResult": "$7"
}
}
</format>
<args>
<arg evaluator="xml" expression="get-property('apiName')"/>
<arg evaluator="xml" expression="get-property('apiVersion')"/>
<arg evaluator="json" expression="$.runResponse.runReturn.item[0].value"/>
<arg evaluator="json" expression="$.runResponse.runReturn.item[3].value"/>
<arg evaluator="json" expression="$.runResponse.runReturn.item[4].value"/>
<arg evaluator="json" expression="$.runResponse.runReturn.item[5].value"/>
<arg evaluator="json" expression="$.runResponse.runReturn.item[6].value"/>
</args>
</payloadFactory>
<property name="messageType" value="application/json" scope="axis2"/>
<send/>
</outSequence>
There appears to be some documentation for the older versions of API Manager about the API template under <APIM_HOME>/repository/resources/api-templates/default_api_template.xml file.
With API Manager 1.8.0, I can not find the same documentation page but editing the velocity_template.xml works for non-prototype API definitions.
I am still trying to incorporate my requirements into it.
Actually you want to do some do some transformation for your message. APIM 1.8 supports mediation extension. where you can add your own in,out and fault sequence and have your transformation there. this mediation extension support for globally and per api basis. you can find the details here[1]
so if you create a global level sequence it will be applied to all apis.In your case you have to create one global insequnce to add basic oauth related stuff and one global out sequence to add payload factory related stuff
1.https://docs.wso2.com/display/AM180/Adding+Mediation+Extensions

Iterate Mediator over json arrays

I'd like to iterate the results array of a json message
{
"results":[
{
"category":"mdl",
"subcategory":"ip",
"ip":"103.14.120.121",
"subtype":"IP-MDL",
"date":"1405074556",
"longitude":"75.3333",
"latitude":"19.8833",
"country":"India",
"city":"Aurangabad",
"organization":"Good Domain Registry Private Limited",
"isp":"Good Domain Registry Private Limited"
},
{
"category":"mdl",
"subcategory":"ip",
"ip":"108.162.198.96",
"subtype":"IP-MDL",
"date":"1405074556",
"longitude":"-122.3933",
"latitude":"37.7697",
"country":"United States",
"city":"San Francisco",
"organization":"CloudFlare",
"isp":"CloudFlare"
}
]
}
unfortunately iteration mediator doesn't seem to accept non xpath expression
anyone knows how to iterate over the previous message json results the same way i do it in xml ?
I'd like to use ESB json-native support but doesn't seem to be able to break down json messages as with XML (i've tried iterate mediator, json payload factory and script mediator without any success)
<iterate expression="json-eval(results)">
<target>
<sequence>
<property name="messageType" value="application/json" scope="axis2"/>
<payloadFactory media-type="json">
<format>
{
"event":{
"providerName":"$1",
"providerSource":"$2",
"providerClassification":"$3",
"providerVersion":"$4",
"body":{
"results":{$5}
}
}
}
</format>
<args>
<arg value="bdigital"/>
<arg evaluator="json" expression="$.results.category"/>
<arg evaluator="json" expression="$.results.subcategory"/>
<arg value="1.0"/>
<arg evaluator="json" expression="$.results"/>
</args>
</payloadFactory>
<call>
<endpoint>
<http method="post"
uri-template="http://BD-VM-PP-CIC01:8280/services/CICQueue"/>
</endpoint>
</call>
</sequence>
</target>
</iterate>
thanks in advance,
You could do the following?
<property name="messageType" value="application/xml" scope="axis2" type="STRING"></property>
<iterate xmlns:ns="http://org.apache.synapse/xsd" continueParent="true" expression="//jsonObject/results" id="MyIterator">
<target>
<sequence>
<property name="cat" expression="json-eval($.results.category)" type="STRING"></property>
etc.
There is a new version in WSO2 EI in which you can iterate over JSON using JSON Path. You can do something like below.
<iterate id="iterate-over-users" preservePayload="true" attachPath="json-eval($.results)" expression="json-eval($.results)">
<target>
<sequence>
<send>
<endpoint>
<http method="POST" uri-template="http://backend.com"/>
</endpoint>
</send>
</sequence>
</target>
</iterate>
Refer to the following blog for more info. https://medium.com/#arunans23/iterate-over-json-payload-with-wso2-enterprise-integrator-8ccb9cdd2c70