Using JSON In Data Services with WSO2 Enterprice Integrator - json

Product Version: WSO2-EI-6.3
I have created a data service to retrieve data as a JSON like below format.
{
"Employees":{
"Employee":[
{
"EmployeeNumber":"1"
},
{
"EmployeeNumber":"2"
}
]
}
}
Find below the sequence used to create the data service in EI.
<data name="RDBMSDataService" transports="http https local">
<config enableOData="false" id="DataSource">
<property name="driverClassName">com.mysql.jdbc.Driver</property>
<property name="url">jdbc:mysql://localhost:3306/Employees</property>
<property name="username">root</property>
<property name="password">1234</property>
</config>
<query id="SelectAllEmployees" useConfig="DataSource">
<sql>select EmployeeNumber from Employees</sql>
<result outputType="json">{
"Employees":{
"Employee":[
{
"EmployeeNumber":"$EmployeeNumber"
}
]
}
}</result>
</query>
<operation name="AllEmployees">
<call-query href="SelectAllEmployees"/>
</operation>
</data>
But Still, it gives the XML mapped output as below.
<Employees xmlns="http://ws.wso2.org/dataservice/SelectAllEmployees">
<Employee>
<EmployeeNumber>1</EmployeeNumber>
</Employee>
<Employee>
<EmployeeNumber>2</EmployeeNumber>
</Employee>
</Employees>

Have I been working on it days ago?
What I suggest you to do is. In your client side pass the following header:
'Accept':'application/json'
enter image description here
Then:
enter image description here

Related

Appending JSON content to a JSON file in WSO2

I have few JSON Payloads that have to be appended to a JSON file.
This is how my JSON Payload will look:
{"variant": {"940894": {"attributes": {"Size": "XL" } } } }
I will be getting multiple json Payloads of this type.
At the end I need to form a file that looks like this:
[
{"variant": {"940894": {"attributes": {"Size": "XL" } } } },
{"variant": {"940895": {"attributes": {"Size": "Med" } } } },
{"variant": {"940895": {"attributes": {"Size": "Small" } } } }
]
These are the properties I have set for the requirement:
<property expression="fn:concat('Test',get-property('File_Name'),'.txt')" name="FILE_NAME" scope="default"
<propertyGroup description="File and OutputPayload properties">
<property name="messageType" scope="axis2" type="STRING" value="text/plain"/>
<property name="ContentType" scope="axis2" type="STRING" value="text/plain"/>
<property expression="$ctx:FILE_NAME" name="transport.vfs.ReplyFileName" scope="transport" type="STRING"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
</propertyGroup>
<call>
<endpoint>
<address uri="vfs:sftp://username:password/home/user/test/out/json?transport.vfs.Append=true">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
</call>
But I get an error saying "The file type does not support append mode". What else can I try here.
I had a look at the code, and as you already noticed SFTP protocol doesn't allow you to do file appending. The supported operations for SFTP are here in the code.
Capability.CREATE, Capability.DELETE, Capability.RENAME, Capability.GET_TYPE,
Capability.LIST_CHILDREN, Capability.READ_CONTENT, Capability.URI, Capability.WRITE_CONTENT,
Capability.GET_LAST_MODIFIED, Capability.SET_LAST_MODIFIED_FILE, Capability.RANDOM_ACCESS_READ
But if you use FTP protocol instead you should be able to do File Appending as it's supported here.
Capability.CREATE, Capability.DELETE, Capability.RENAME,
Capability.GET_TYPE, Capability.LIST_CHILDREN,
Capability.READ_CONTENT, Capability.GET_LAST_MODIFIED,
Capability.URI, Capability.WRITE_CONTENT,
Capability.APPEND_CONTENT, Capability.RANDOM_ACCESS_READ
Appending works with the Local file system too.
If you want to append the file and still use SFTP you will have to READ -> APPEND -> WRITE the file. Or can consider writing a Custom Class mediator.

Could not initialize Start up controller. TaskManager not found

i have written a scheduled task which call an Api in sequence in wso2 ei 6.4.0. my task is :
<task xmlns="http://ws.apache.org/ns/synapse"
name="GetMunicipalityAPIToken"
class="org.apache.synapse.startup.tasks.MessageInjector"
group="synapse.simple.quartz">
<trigger interval="60"/>
<property xmlns:task="http://www.wso2.org/products/wso2commons/tasks" name="message">
<test xmlns=""/>
</property>
<property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
name="sequenceName"
value="GetTokenFromMunicipalityService"/>
<property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
name="injectTo"
value="sequence"/>
</task>
and my sequence is :
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="GetTokenFromMunicipalityService" xmlns="http://ws.apache.org/ns/synapse">
<send>
<endpoint>
<http method="POST" uri-template="http://x.x.x.x/api/MunicipalityBill/connect/token"/>
</endpoint>
</send>
</sequence>
but when i run integrator.bat in wso2eiHome/bin I got this error : "Could not initialize Start up controller. TaskManager not found" and the Api dont be called. Do i forget something ?
The error can be caused when you do not have org.wso2.carbon.mediation.ntask.NTaskTaskManager defined in the server. Could you please check whether the following is added in the synapse.xml file located in the [EI_HOME]/repository/deployment/server/synapse-configs/default/ directory
<definitions xmlns="http://ws.apache.org/ns/synapse">
<taskManager provider="org.wso2.carbon.mediation.ntask.NTaskTaskManager"/>
</definitions>

URL parameter wso2esb

I have created an API in esb like this snippet:
<api xmlns="http://ws.apache.org/ns/synapse" name="contact_v1"
<resource methods="GET" uri-template="/contact-by-email?email={query.param.email}" inSequence="crm_contact-by-email_v1" outSequence="crm_contact-by-email_v1" faultSequence="crm_contact-by-email-error_v1"/>
</api>
In my sequence I retrieve the request param, email, like that
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="crm_contact-by-email_v1" xmlns="http://ws.apache.org/ns/synapse">
<in>
<script language="js"><![CDATA[try {
var randomnumber1=Math.floor((Math.random() * 10000) + 1);
mc.setProperty("sessionnumber", randomnumber1.toString());
} catch(e) {
}]]></script>
<property expression="$axis2:REST_URL_POSTFIX" name="myURL"
scope="default" type="STRING" xmlns:ns="http://org.apache.synapse/xsd"/>
<script language="js"><![CDATA[try {
var log = mc.getServiceLog();
var email = mc.getProperty('query.param.email');
log.info("emailxxxxxx "+email);
} catch(e) {}]]></script>
</in>
<out>
<send/>
<drop/>
</out>
</sequence>
When I make a request with an encoding email like that
test%40test.com
it works witout problem.
But when I make a request with
test#test.com
it display this error
<tp:fault xmlns:tp="https://xxxxxxx.com/"><tp:code>404</tp:code><tp:type>Status report</tp:type><tp:message>Not Found</tp:message><tp:description>The requested resource (//contact-by-email?email=test#test.com) is not available.</tp:description></tp:fault>
Would you have any idea
Best regards
Characters as # are reserved characters for delimiters in the RFC specification for URI-Templates (I can explain more if you are interested). Therefore, in order to allow # as the value for email parameter, define the uri-template with {+query.param.email} as below.
<api xmlns="http://ws.apache.org/ns/synapse" name="contact_v1"
<resource methods="GET" uri-template="/contact-by-email?email={+query.param.email}" inSequence="crm_contact-by-email_v1" outSequence="crm_contact-by-email_v1" faultSequence="crm_contact-by-email-error_v1"/>
</api>

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}}}

WSO2 - Transforming and aggregating different JSON data from multiple endpoints

I've created an API in WSO2 Carbon (5.0) which I POST a payload to:
{
"IdNumber" : "8008185218088",
"LastName" : null
}
I then call initiate a clone mediator sequence which forwards this payload to two different REST endpoints. The json response from the endpoints is different:
Endpoint 1 response:
{
"Name" : "Daniel",
"Number" : "12345678"
}
Endpoint 2 response:
{
"Name": "Bob",
"Address": "200 Bob Street",
"Code": "123"
}
The API response I'd like to create based on the above:
{
"Endpoint 1 Response" : {
"Name" : "Daniel",
"Number" : "12345678"
},
"Endpoint 2 Response" : {
"Name": "Bob",
"Address": "200 Bob Street",
"Code": "123"
}
}
What mediators on the outSequence do I need to configure to achieve this? How would I query the individual json response fields and combine them into a custom formatted json message for the client?
I've looked at the Aggregate mediator but I don't think it's right for differently formatted messages.
Here is my inSequence for reference:
<resource methods="POST">
<inSequence>
<property name="ROOT" scope="default">
<root:rootelement xmlns:root="www.wso2esb.com"/>
</property>
<log level="full"/>
<clone continueParent="true" id="test" sequential="true">
<target>
<sequence>
<send>
<endpoint>
<address uri="http://192.168.1.1/api/service/person" format="rest"/>
</endpoint>
</send>
</sequence>
</target>
<target>
<sequence>
<send>
<endpoint>
<address uri="http://192.168.1.1/api2/query" format="rest"/>
</endpoint>
</send>
</sequence>
</target>
</clone>
</inSequence>
You will be unable to aggregate messages like this. A solution is to use the 'call' mediator, store the first response (or the values) in a property and call the second service afterwards.
Something like this:
<call>
<endpoint>
<address uri="http://192.168.1.1/api/service/person" format="rest"/>
</endpoint>
</call>
<property name="Name1" expression="//Name" />
<property name="Number1" expression="//Number" />
<send>
<endpoint>
<address uri="http://192.168.1.1/api2/query" format="rest"/>
</endpoint>
</send>
<outSequence>
-- build message using payloadfactory
</outSequence>
You can use a payloadFactory in the outSequence to build the response message.