My question is about converting xml into json in WSO2 ESB.I'm using salesforce Rest API connector to update sobject in salesforce.
My request is as follows
<body>
<fandV>
<name>Acount Name</name>
<description>Account Description</description>
<fandV>
</body>
I want to convert above response to json object as follows, in order to pass as the fieldandvalue in SalesForce update function.
{ "name":"Acount Name", "description":"Account Description"}
Salesforce Rest API update method sample is follows
<salesforcerest.update>
<sObjectName>Opportunity</sObjectName>
<fieldAndValue>{get-property('fb')}</fieldAndValue>
<Id>0069E000007FmBeQAK</Id>
</salesforcerest.update>
Appreciate if anyone gives suggestion on this
If any conversion is required it always suggested to use xslt, however in your case if the conversion is small then you can go ahead with payload mediator, below is the code which should work for your payload.
<payloadFactory media-type="json">
<format>{ "name":"$1", "description":"$2"}</format>
<args>
<arg evaluator="xml" expression="//body/fandV/name/text()"/>
<arg evaluator="xml" expression="//body/fandV/description/text()"/>
</args>
</payloadFactory>
Related
I'm having a few problems in understanding how to pass a query param to a payload factory that creates a json, and then passing its data to a data service.
What I thought would be the correct config is
<payloadFactory media-type="json">
<format>{"cod_uo" : "$1"}</format>
<args>
<arg evaluator="xml" expression="get-property('query.param.id')"/>
</args>
</payloadFactory>
<log>
<property expression="json-eval($.cod_uo)" name="string"/>
</log>
<dataServiceCall description="GET operation" serviceName="MyService">
<operations type="single">
<operation name="MyOperationName">
---> <param evaluator="xml" expression="json-eval('$.cod_uo')" name="cod_uo"/> <-- This Line
</operation>
</operations>
<source type="inline"/>
<target type="body"/>
</dataServiceCall>
but the system doesn't recognize the json-eval function here.
I tried also a direct json evaluation with
<param evaluator="json" name="id" expression="$.cod_uo"/>
but i get a DataServiceCallMediator
Current Request Name: MyOperationName
Current Params: {cod_uo=}
Nested Exception:-
java.lang.NumberFormatException: For input string: ""
What is the correct method to use the 'cod_uo' property of the payload factory payload in a subsequent data service call?
I'm using the latest Integration Studio (8.0.0.202104161647)
The log ALWAYS returns
{api:MyApi:v1.0.0} To: /my/path?id=123, MessageID: urn:uuid:[uuid], correlation_id: [correlation_id], Direction: request, string = 123
All combinations + errors:
<param evaluator="xml" expression="json-eval('$.cod_uo')" name="cod_uo"/>
[2021-07-30 08:50:41,179] ERROR {SynapseXPath} - Evaluation of the XPath expression json-eval('$.cod_uo') resulted in an error org.jaxen.UnresolvableException: No Such Function json-eval
<param evaluator="xml" expression="json-eval($.cod_uo)" name="cod_uo"/>
(doesn't compile: "Invalid XPath expression for attribute expression : json-eval($.cod_uo)"
<param evaluator="json" expression="json-eval('$.cod_uo')" name="cod_uo"/>
<param evaluator="json" expression="json-eval($.cod_uo)" name="cod_uo"/>
<param evaluator="json" expression="$.cod_uo" name="cod_uo"/>
Current Request Name: MyOperationName
Current Params: {cod_uo=}
Nested Exception:-
org.postgresql.util.PSQLException: ERROR: invalid input syntax for integer: ""
<param evaluator="xml" expression="$.cod_uo" name="cod_uo"/>
(doesn't compile: Invalid XPath expression for attribute expression : $.cod_uo)
Since both Payload Factory mediator and the Data Service Call mediator is in the same sequence, you can make use of the get-property() function to retrieve the value and assign it.
For example,
<param evaluator="json" name="id" expression="get-property('query.param.id')"/>
Furthermore, if you wanted to access the property through json-eval(), I think there has been a typo that is causing the empty value behavior. Please remove the quotes around the key and try the scenario
Update Note: The json-eval() approach didn't solve the problem. But, keeping the following segment as a reference. Look at the Update section to access the payload using XPath expression.
<!-- without single quotes around the $.myId -->
<param evaluator="json" name="id" expression="json-eval($.myId)"/>
Update
You can also try accessing the Payload using XPath expression as following
<param evaluator="xml" name="id" expression="$body//myId"/>
I have an enrich mediator in a sequence which has a value in a plain text. I have verified the value with log and ensured it is a text. But when I do the call after the enrich (see below) the API received the payload as a JSON with key always as "test": and then the plaintext value.
The API below expects any values, it just saves the body to a file. When I try to set a property before the call to state message type=text/plain it just hangs, does not do the call?
QUESTION: Does WSO2 mediator (wso2 framework) by nature expects the body to be either be JSON or XML? NOT Text/Plain allowed. If this is true, then I have to change my API to handle this issue I Think.
If someone can answer that question, I think I will know what to do. Because when I call the same API using a java class mediator with same options it works fine.
<call>
<endpoint>
<http method="POST" uri-template="http://xxxxxxx.38:8280/writefile"/>
</endpoint>
</call>
Thanks for the update. I had tried that before, when I had that the process was hanging and would not call the api. Here is what we did for it to work:
<payloadFactory media-type="xml">
<format>
<text xmlns="http://ws.apache.org/commons/ns/payload">$1</text>
</format>
<args>
<arg evaluator="xml" expression="get-property('fileContent')"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="text/plain"/>
Thanks for the update folks. First time asking a questions and good to see getting response ASAP. Will try to contribute my learning and try to help .
Add this before the call mediator.
<property name="messageType" value="text/plain" scope="axis2"/>
I have a backend service with multiple operations. (for example,echoInt and echoString). I want to replace input value for both of them with predefined variables(in the inSequence) with PayloadFactory mediator.
How can i define payloadfactory for different operations?
when i define two payloadfactory mediator for each of them, only the last mediator works for it's operation. when i call other opertaion, this error occures:
wso2 namespace mismatch
operation1:
<p:echoString xmlns:p="http://echo.services.core.carbon.wso2.org">
<in>$1</in>
</p:echoString>
operation2:
<p:echoInt xmlns:p="http://echo.services.core.carbon.wso2.org">
<in>$1</in>
</p:echoInt>
My inSequense:
<inSequence>
<payloadFactory media-type="xml">
<format>
<p:echoString xmlns:p="http://echo.services.core.carbon.wso2.org">
<in xmlns="">teststr</in>
</p:echoString>
</format>
<args/>
</payloadFactory>
<payloadFactory media-type="xml">
<format>
<p:echoInt xmlns:p="http://echo.services.core.carbon.wso2.org">
<in xmlns="">1111</in>
</p:echoInt>
</format>
<args/>
</payloadFactory>
</inSequence>
with above inSequense, output result for both operations is '1111':
<ns:echoStringResponse xmlns:ns="http://echo.services.core.carbon.wso2.org">
<return>1111</return>
</ns:echoStringResponse>
thanks in advance
The second Payload factory replaces the first.
If you want to use each of them in a different case, you should define them in a Switch mediator.
You can use a property to get the input that defines which case you should use, then use regex to match the property value. Or you could skip the property and enter the expression in the Switch source.
At the end it would look similar to:
<inSequence>
<property expression="/default/expression" name="input_string" scope="default" type="STRING"/>
<switch source="get-property('input_string')">
<case regex="[\w\s]+">
<payloadFactory media-type="xml">
<format>
<p:echoString xmlns:p="http://echo.services.core.carbon.wso2.org">
<in xmlns="">teststr</in>
</p:echoString>
</format>
<args/>
</payloadFactory>
</case>
<default>
<payloadFactory media-type="xml">
<format>
<p:echoInt xmlns:p="http://echo.services.core.carbon.wso2.org">
<in xmlns="">1111</in>
</p:echoInt>
</format>
<args/>
</payloadFactory>
</default>
</switch>
<respond/>
</inSequence>
If you want call two operations in same time, you should use the clone or iterate Mediator, and use the aggregate Mediator in the outsequence.
The reason you use the two payloadFactory, only last one works, is that one request only have one message context, this mean, you only can send one soap message to back end in same time. This mean the last payloadFactory will override the first one.
Clone or iterate Mediator will clone or split one message context to multiple message context, then you can send multiple soap message to back end services. Because of you got multiple message context, then you should use the aggregate Mediator to aggregate these multiple responses into one message context after back end services return the result.
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 ...
My WSO2 ESB Proxy Service receives the following request:
<ReadFormRequest>
<formID>1470</formID>
<name>ConstructionForm</name>
</ReadFormRequest>
I need to change ReadFormRequest to GetFormRequest and send it to the endpoint.
Here is my PayloadFactory code that is supposed to do the job:
<payloadFactory media-type="xml">
<format>
<GetFormRequest>
$1
</GetFormRequest>
</format>
<args>
<arg evaluator="xml" expression="$body/ReadFormRequest/*"/>
</args>
</payloadFactory>
The problem is that my XPath expression "$body/ReadFormRequest/*" returns values of the child elements instead of the actual elements. Thus I am getting the following result:
<GetFormRequest>
1470ConstructionForm
</GetFormRequest>
According to XPath documentation this query should return the elements, but it seems like WSO2 retrieves element values instead.
I've spent a little bit of time trying to do this via xpath and I don't think it's possible. I either get the same as you, or
<GetFormRequest>
<ReadFormRequest>
<formID>1470</formID>
<name>ConstructionForm</name>
</ReadFormRequest>
</GetFormRequest>
Have you considered the XSLT mediator?
You can retrieve the entire xml element if you had a root element wrapping those.
ex:
<ReadFormRequest>
<a>
<formID>1470</formID>
<name>ConstructionForm</name>
</a>
</ReadFormRequest>
So you can either use XSLT mediator or use Payload Factory mediator by setting each child element through arguments.
<payloadFactory>
<format>
<GetFormRequest xmlns="">
<formID>$1</formID>
<name>$2</name>
</GetFormRequest>
</format>
<args>
<arg expression="$body/ReadFormRequest/formID"/>
<arg expression="$body/ReadFormRequest/name"/>
</args>
</payloadFactory>