Rebuilding the initial message using the payload factory mediator - wso2

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

Related

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.

how to force text/plain in WSO2 call to an endpoint

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"/>

WSO2 ESB- PayloadFactory for different operations

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.

WSO2 API manager prototype API HTTP response status

I am using the inline javascript prototype feature in the WSO2 API manager and I'm trying to set different HTTP response statuses. Is this possible? If so how is it done?
So far I have tried setting the HTTP_SC property but this doesn't seem to have any effect.
mc.setProperty('HTTP_SC', "404");
I had the same requirement and after much exploring under the hood was able to find a workable solution.
The reason why setting the property:
mc.setProperty('HTTP_SC', "404");
didn't work is that the property needs to be set in the axis2 scope (as Abimaran said). mc.setProperty doesn't set it on that scope. Moreover, the MessageContext object doesn't provide a way to set the scope.
The 'Deploy as Prototype' action actually creates the API definition file by merging the specified in-line script into the a velocity template and storing the resulting API definition into a file.
Template: ./repository/resources/api_templates/prototype_template.xml
Output location: repository/deployment/server/synapse-configs/default/api/
The output file will have a name in the format:
provider--API Name-vVERSION.xml
where provider appears to be the username of the API creator.
What I did was add a filter to the template:
<filter source="boolean(get-property('HTTP_SC'))" regex="false">
<then>
<property name="HTTP_SC" value="200" scope="axis2"/>
</then>
<else>
<property name="HTTP_SC" expression="get-property('HTTP_SC')" scope="axis2"/>
</else>
</filter>
I added it immediately after a similar block (for handling CONTENT_TYPE) at the start of the inSequence element.
You need to add following properties before <send/> mediator
<header name="To" action="remove"/>
<property name="RESPONSE" value="true"/>
<property name="HTTP_SC" value="403" scope="axis2"/>

How to set Payload for Recipient List Group Endpoint?

I have a sequence that is invoking multiple endpoints. My sequence is:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="GetAllData">
<switch xmlns:ns="http://org.apache.synapse/xsd" xmlns:cct="http://www.tempuri.org" xmlns:tns="http://www.tempuri.org" source="//tns:IDFilter/cct:ID">
<case regex=".?">
<log level="custom">
<property name="Property2" value="----------------Inside switch 1 ? ---------------"/>
</log>
<filter xpath="//tns:ChildIDFilter/cct:ID='?'">
<then>
<log level="custom">
<property name="prop1" value="------Inside Then------------------"/>
</log>
**<payloadFactory>
<format>
<select_all_ID_operation xmlns:cir="http://tempuri.org"/>
</format>
</payloadFactory>
<payloadFactory>
<format>
<select_all_ChildID_operation xmlns="http://tempuri.org"/>
</format>
</payloadFactory>
<send>
<endpoint key="ID_Service_EPS"/>
</send>**
</then>
<else>
<log level="custom">
<property name="prop2" value="------Inside Else------------------"/>
</log>
<payloadFactory>
<format>
<select_all_ID_operation xmlns="http://tempuri.org"/>
</format>
</payloadFactory>
<send receive="ValidateAllData">
<endpoint key="ID_Endpoint"/>
</send>
</else>
</filter>
</case>
</switch>
</sequence>
Now in my ID_EPS endpoint, i have two wsdl endpoints and for them i have to pass payload to get data from both wsdl's, but this is not happenning. My question is how to invoke recipient endpoint contaning different wsdl Endpoints and setting payload for it and finally get the concatinated result. Looking forward to your answers.Thanks in advance
In the management console-->endpoint menu, you can find the recipient list endpoint, where provide your both endpoints, and refer that recipient endpoint from your sequence
To send messages to two endpoints (in your case two wsdl endpoints) using recipient list endpoint, the message format accepted by both endpoints should be identical.
If so, you can send messages to both endpoints using a recipient list endpoint and then aggregate the response messages and construct the concatenated result.
Refer to following resource to find a sample configuration of Recipient list endpoint.
http://docs.wso2.org/wiki/display/ESB460/Sample+62%3A+Routing+a+Message+to+a+Dynamic+List+of+Recipients+and+Aggregating+Responses
If two endpoint message formats are not identical, you have to implement a service chaining scenario or you can clone the message and create two different branches for two endpoints and construct the payload required by each service endpoint and send to the service endpoint within that branch. Then you can aggregate the responses received from both branches and construct the concatenated result.