WSO2 Multipart Binary Passthrough and MultipartFormData - wso2

We are currently using WSO EI 6.4 as ESB.
We made the configuration to get the behaviour "Binary Passthrough" in axis2.xml for one carbon application
<messageBuilder contentType="multipart/form-data" class="org.wso2.carbon.relay.BinaryRelayBuilder"/>
<messageFormatter contentType="multipart/form-data" class="org.wso2.carbon.relay.ExpandingMessageFormatter"/>
But now, we need to develop a new carbon application who need to create a multipart message.
and so we need to change the configuration to, as decribed in this article
<messageBuilder contentType="multipart/form-data" class="org.apache.axis2.builder.MultipartFormDataBuilder" />
<messageFormatter contentType="multipart/form-data" class="org.apache.axis2.transport.http.MultipartFormDataFormatter"/>
But if we do that, we will lose the "Binary Passthrough" adn broke the first carbon app.
Is there a possiblitiy to override the messageBuilder and messageFormatter just for one carbon application?
Thank you
Solution
With the help of #tmoasz i was able to solve this issue.
Here the full solution
<inSequence>
<!--Extract value from Json-->
<property name="Data1" expression="json-eval($.Data1)"/>
<property name="Data2" expression="json-eval($.Data2)"/>
<property name="File1" expression="json-eval($.File1)"/>
<!-- remove body and set MessageBuilder
if body not removed, MultipartFormDataFormatter is not call
-->
<script language="js">
mc.getEnvelope().getBody().getFirstElement().detach();
</script>
<builder>
<messageBuilder contentType="multipart/form-data"
class="org.apache.axis2.builder.MultipartFormDataBuilder"
formatterClass="org.apache.axis2.transport.http.MultipartFormDataFormatter"/>
</builder>
<payloadFactory media-type="xml">
<format>
<root xmlns="">
<metadata xmlns="http://org.apache.axis2/xsd/form-data"
filename="key1"
name="key1">$1</metadata>
<!-- content is decode from base64-->
<file xmlns="http://org.apache.axis2/xsd/form-data"
filename="file1.1"
name="file1.1"
content-type="application/xml">$3</file>
<!-- content is not changed-->
<metadata xmlns="http://org.apache.axis2/xsd/form-data"
name="file1.2"
filename="file1.2"
content-type="application/xml">$3</metadata>
</root>
</format>
<args>
<arg expression="get-property('Data1')"/>
<arg expression="get-property('Data2')"/>
<arg expression="get-property('File1')"/>
</args>
</payloadFactory>
<!--set messageType to trigger multiPart Formater -->
<property name="messageType" scope="axis2" type="STRING" value="multipart/form-data"/>
<!--remove ContentType to force generate header content-type with boundary information -->
<property name="ContentType" scope="axis2" action="remove"/>
<send>
<endpoint>
<http method="post" uri-template="http://127.0.0.1:3000/mulitPart/wso2">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</send>
</inSequence>
Curl for test
curl --location --request POST 'http://127.0.0.1:8280/outgoing-mail' \
--header 'Content-Type: application/json' \
--data-raw '{
"Data1": "Value1",
"Data2": "Value2",
"File1" : "PHhtbD4gICAKICAgIDxoZWxsbz5TdGFjazwvaGVsbG8+CjwveG1sPg=="
}'
Multipart Generated
--MIMEBoundary_dfa6d9a4ea9eee573969c1fae03dd6667159a66375689ec7
Content-Disposition: form-data; name="key1"; filename="key1"
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: binary
Value1
--MIMEBoundary_dfa6d9a4ea9eee573969c1fae03dd6667159a66375689ec7
Content-Disposition: form-data; name="file1.1"; filename="file1.1"
Content-Type: application/pdf; charset=ISO-8859-1
Content-Transfer-Encoding: binary
<xml>
<hello>Stack</hello>
</xml>
--MIMEBoundary_dfa6d9a4ea9eee573969c1fae03dd6667159a66375689ec7
Content-Disposition: form-data; name="file1.2"; filename="file1.2"
Content-Type: application/pdf; charset=ISO-8859-1
Content-Transfer-Encoding: binary
PHhtbD4gICAKICAgIDxoZWxsbz5TdGFjazwvaGVsbG8+CjwveG1sPg==
--MIMEBoundary_dfa6d9a4ea9eee573969c1fae03dd6667159a66375689ec7--

Maybe the BuilderMediator can do that, what you would to achieve.
Checkout this: Builder+Mediator documentation.

Related

WSO2 EI 6.6.0 Class Mediator not being able to use SOAP call return content

I have the following API in EI 6.6.0:
<?xml version='1.0' encoding='UTF-8'?>
<api xmlns="http://ws.apache.org/ns/synapse" name="sample" context="/sample">
<resource methods="POST">
<inSequence>
<payloadFactory media-type="xml">
<format>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<P xmlns="http://tempuri.org/">
<P1>$1</P1>
<P2>$2</P2>
<P3>$3</P3>
</P>
</soap:Body>
</soap:Envelope>
</format>
<args>
<arg evaluator="json" expression="$.p1" />
<arg evaluator="json" expression="$.p2" />
<arg evaluator="json" expression="$.p3" />
</args>
</payloadFactory>
<log level="full" />
<property name="Content-Type" value="text/xml;charset=UTF-8" scope="axis2"/>
<header name="Accept" scope="transport" value="text/xml"/>
<call>
<endpoint>
<wsdl Action="name_of_the_action" service="name_of_the_service" port="name_of_soap_port" uri="http://<ip>/path?WSDL" />
</endpoint>
</call>
<class name="my_mediator_package"></class>
<log level="full" />
<payloadFactory media-type="xml">
<format>
<retorno xmlns="">
<msg>$1</msg>
</retorno>
</format>
<args>
<arg evaluator="xml" expression="get-property('property_set_on_mediator')" />
</args>
</payloadFactory>
<property name="messageType" value="application/xml" scope="axis2" type="STRING" />
<respond />
</inSequence>
<outSequence>
</outSequence>
<faultSequence>
<property name="text" value="An unexpected error occured"/>
<property name="message" expression="get-property('ERROR_MESSAGE')"/>
<payloadFactory media-type="xml">
<format>
<error xmlns="">
<msg>$1</msg>
</error>
</format>
<args>
<arg evaluator="xml" expression="get-property('ERROR_MESSAGE')"/>
</args>
</payloadFactory>
<property name="messageType" value="application/json" scope="axis2" type="STRING"/>
<respond/>
</faultSequence>
</resource>
</api>
my mediate method content:
public boolean mediate(MessageContext synCtx) {
org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) synCtx)
.getAxis2MessageContext();
try {
// Getting the json payload to string
String jsonPayloadToString = JsonUtil.jsonPayloadToString(((Axis2MessageContext) synCtx)
.getAxis2MessageContext());
System.out.println("original payload : \n" + jsonPayloadToString + "\n");
I'm not being able to use the return from my SOAP call in my mediator so I can work on it.
When I run the API I get the following from my mediator code:
original payload:
{}
Is there a way so I can obtain the SOAP call returned envelope and use it in my mediator?
The JSON payload is coming as empty because you are calling a SOAP backend and getting a SOAP payload. You can use synCtx.getEnvelope() in your mediator to get the SOAPEnvelope from the response.
1- make sure the json payload is there. So, log the json properties inside your inSequence.
2- I'm not being able to use the return from my SOAP call in my mediator so I can work on it. you can see the response payload in your outSequence which currently is doing nothing.
3- According to your scenario which is simply calling a SOAP webservice, you do not need a class mediator. In other words, when you do not need manipulating the initial payload and then pass it to the destination service, logically implementing your own class mediator benefits you nothing.
Also, there are quite number of samples in https://docs.wso2.com/display/EI611 which will help you.
Please let me know if your problem is solved.

wso2 Missing boundary in multipart/form-data POST

I'm trying to implement this scenario:
wso2Proxy sends POST to joao.php
joao.php gets id value and returns it.
if i call joao.php from a browser and a form with a field called id it works. If i do the same in WSO2 Proxy i get the php error Missing boundary in multipart/form-data POST.
I used TCPMon to analyse the calls and WSO2 sends Content-Type: multipart/form-data but no boundary.
Can someone point me in the right direction?
Here are the 2 calls:
From Browser:
POST /joao.php HTTP/1.1
Host: localhost:7590
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarytcskUke6yP5MNOzt
Origin: http://localhost:7590
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8
Referer: http://localhost:7590/joao.php
Upgrade-Insecure-Requests: 1
DNT: 1
Content-Length: 135
Connection: keep-alive
------WebKitFormBoundarytcskUke6yP5MNOzt
Content-Disposition: form-data; name="id"
sd
------WebKitFormBoundarytcskUke6yP5MNOzt--
From WSO2 Proxy:
POST /joao.php HTTP/1.1
Content-Type: multipart/form-data
Content-Length: 264
Host: localhost:7590
Connection: Keep-Alive
User-Agent: Synapse-PT-HttpComponents-NIO
--MIMEBoundary_4e039051f0592881a6551113d958f38436c2e8eef5b85bba
Content-Disposition: form-data; name="id"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit
teste123
--MIMEBoundary_4e039051f0592881a6551113d958f38436c2e8eef5b85bba--
I have the following commented sections on axis2.xml:
<!--messageFormatter contentType="multipart/form-data"
class="org.wso2.carbon.relay.ExpandingMessageFormatter"/-->
<!--messageBuilder contentType="multipart/form-data"
class="org.wso2.carbon.relay.BinaryRelayBuilder"/-->
This is because if I enable them then the content gets posted as XML and not multipart/data.
As a result, these are the builders and formatters that are enabled for multipart/data:
<messageFormatter class="org.apache.axis2.transport.http.MultipartFormDataFormatter" contentType="multipart/form-data"/>
<messageBuilder class="org.apache.axis2.builder.MultipartFormDataBuilder" contentType="multipart/form-data"/>
Here is the proxy configuration I am using:
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="testeSendFile"
transports="http https"
startOnLoad="true">
<description/>
<target>
<inSequence>
<payloadFactory media-type="xml">
<format>
<params xmlns="">
<id>teste123</id>
</params>
</format>
<args/>
</payloadFactory>
<property name="messageType" value="multipart/form-data" scope="axis2"/>
<property name="DISABLE_CHUNKING"
value="true"
scope="axis2"
type="STRING"/>
<log level="full"/>
<send>
<endpoint>
<http method="POST" uri-template="http://localhost:7590/joao.php"/>
</endpoint>
</send>
<log level="full"/>
</inSequence>
</target>
</proxy>
If you're only sending text values as form data, you can use application/x-www-form-urlencoded instead of form-data.
See http://isharapremadasa.blogspot.com/2014/09/sending-form-data-through-wso2-esb-with.html
This is a bug. Will be fixed in next release.
I was able to resolve the issue by changing the proxy service to the following.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="testeSendFile"
startOnLoad="true"
statistics="disable"
trace="disable"
transports="http,https">
<target>
<outSequence>
<property name="OUT_ONLY" value="true"/>
<send/>
</outSequence>
<endpoint>
<address uri="http://localhost:8080/upload"/>
</endpoint>
</target>
<description/>
</proxy>
For more detailed information refer to the following bolg.
Ushani Balasooriya's Blog
Here is the sample request

Invalid UTF-8 start byte 0x8b error calling a SOAP service after receiving result of a REST call - WSO2 ESB 4.8.1

Implementing a service chain in WSO2 ESB 4.8.1 we have a sequence that calls a REST service and in the receiving sequence we call a SOAP service. In doing so, we get the following error,
<?xml version='1.0' encoding='utf-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body><ns2:Fault xmlns:ns3="http://www.w3.org/2003/05/soap-envelope" xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/"><faultcode>ns2:Client</faultcode>
<faultstring>Couldn't create SOAP message due to exception: XML reader error: com.ctc.wstx.exc.WstxIOException: Invalid UTF-8 start byte 0x8b (at char #2, byte #-1)</faultstring>
</ns2:Fault>
</S:Body>
</S:Envelope>[\r][\n]" {org.apache.synapse.transport.http.wire}
This happens irrespective of whether we use the result of the previous call as input or even when actual values are hard-coded in the PayloadFactory. Moreover the SOAP service never receives the request.
When the SOAP service is called on it's own through the ESB or through soapUI, it works fine.
The sequence that calls the SOAP service is as follows,
<template xmlns="http://ws.apache.org/ns/synapse" name="tmpl_get_customer_details">
<sequence>
<payloadFactory media-type="xml">
<format>
<getCustomer xmlns="http://customer.frontend.ws.utilibill.com.au/">
<customer xmlns="">
<custNo>12965</custNo>
</customer>
<login xmlns="">
<password>password</password>
<userName>username</userName>
</login>
</getCustomer>
</format>
<args>
<arg xmlns:ns2="http://org.apache.synapse/xsd" xmlns:ns="http://org.apache.synapse/xsd" expression="$ctx:utilibill_customer_number" evaluator="xml"></arg>
</args>
</payloadFactory>
<log level="full">
<property name="POSITION" value="tmpl_get_customer_details"></property>
</log>
<header name="Action" scope="default" value="http://customer.frontend.ws.utilibill.com.au/UtbCustomer/getCustomerRequest"></header>
<header name="To" scope="transport" value="http://customer.frontend.ws.utilibill.com.au/UtbCustomer/getCustomerRequest"></header>
<property name="POST_TO_URI" value="true" scope="axis2" type="STRING"></property>
<log level="full">
<property name="POSITION" value="CALLING_CUSTOMER_SERVICE"></property>
</log>
<send receive="seq_get_services">
<endpoint key="UtbCustomer"></endpoint>
</send>
</sequence>
</template>
Can anyone please point out what maybe causing this?

Transform response to plain-text using wso2 esb 4.0.6

I'm new to web-service and somehow I have created a simple web-service over http/https using wso2 esb 4.0.6. Now my requirement is to remove the tag from response i.e. i need plain text in response, below code snippets will give u a brief idea of my requirement.
<case regex="POST">
<property name="HTTP_METHOD" value="POST" scope="axis2" type="STRING"/>
<enrich>
<source type="inline" clone="true">
<success xmlns="">Your request for subscription is being processed.</success>
</source>
<target type="body"/>
</enrich>
<header name="To" action="remove"/>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<property name="ContentType" value="text/plain" scope="axis2"/>
</case>
I'm able to get the below response <success>Your request for subscription is being processed.</success>
I just want to remove the <success> </success> tags from the response.
Thanks in advance
May be this is bit late, but I too have came across this recently, and here's how you can make it work.
Make sure in ESB/repository/conf/axis2/axis2.xml plainTextFormatter is enabled.
In your proxy service set 'messageType' property as shown below
Add a payload text element. Please refer to the out sequence of the sample proxy service given below
<outSequence>
<payloadFactory>
<format>
<ms11:text xmlns:ms11="http://ws.apache.org/commons/ns/payload">$1</ms11:text>
</format>
<args>
<arg xmlns:ns="http://www.wso2.org/types" expression="$body/ns:greetResponse/return/text()"/>
</args>
</payloadFactory>
<property name="messageType" value="text/plain" scope="axis2"/>
<log level="full"/>
<send/>
</outSequence>
In this scenario my response from the backend service (HelloService) is as follows.
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns:greetResponse xmlns:ns="http://www.wso2.org/types">
<return>Hello World, Test !!!</return>
</ns:greetResponse>
</soapenv:Body>
</soapenv:Envelope>
See below the request and response for the GET request using curl command
curl -X GET "http://localhost:8280/services/TestProxy/greet?name=Test" -v
* About to connect() to localhost port 8280 (#0)
* Trying 127.0.0.1... connected
> GET /services/TestProxy/greet?name=Test HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: localhost:8280
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
< Server: WSO2 Carbon Server
< Vary: Accept-Encoding
< Date: Wed, 25 Sep 2013 06:08:21 GMT
< Transfer-Encoding: chunked
<
* Connection #0 to host localhost left intact
* Closing connection #0
Hello World, Test !!!
Thanks
Sajith
Simply define the full envelope as inline source.
Eg:
<inSequence>
<enrich>
<source type="inline" clone="true">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body> Your request for subscription is being processed. </soapenv:Body>
</soapenv:Envelope>
</source>
<target type="envelope"/>
</enrich>
<header name="To" action="remove"/>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<property name="Content-Type" value="text/plain" scope="transport" type="STRING"/>
<send/>
</inSequence>

Adding http path parameters dynamically in wso2 esb

We have a proxy service which uses jms transport to receive messages. The messages received need to be sent to a backend REST service using http POST.
The following is done on the messages
xslt transformation to extract specific fields
set message type to application/json
send to the endpoint
The REST service endpoint needs to have a path parameter appended dynamically using one of the values that comes as part of the input message from jms. The url will look like
http://<server-ip>/service/<client>. Here the value for the "client" comes as part of the message.
How can we dynamically add the path param using wso2 esb?
I believe what you are looking for is the REST_URL_POSTFIX property. If you set this property, the value will be appended to the rest endpoint url.
It can be defined as follows with the scope of axis2.
<property name="REST_URL_POSTFIX"
          expression="//client"
          scope="axis2"
         type="STRING"/>
An example on this can be found in this guide, Using REST with a Proxy Service.
EDIT: Following is example using a simple proxy with a POST request using curl. Providing as per the comments. Here, I'm invoking the jaxrs_basic rest service in WSO2 Application Server.
curl -H "Content-Type: application/xml" -H "Accept: application/json" -d "<Customer><name>KasunG</name></Customer>" http://localhost:8281/services/new1/
.
curl -H "Content-Type: application/json" -H "Accept: application/json" -d "{ 'Customer' : { 'name' : 'KasunG' } } " http://localhost:8281/services/new1/
.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="new1"
transports="https http"
startOnLoad="true"
trace="disable">
<description/>
<target>
<inSequence>
<property name="REST_URL_POSTFIX"
value="customers"
scope="axis2"
type="STRING"/>
<property name="ContentType" value="text/xml" scope="axis2" type="STRING"/>
<switch source="$axis2:HTTP_METHOD">
<case regex="GET">
<property name="HTTP_METHOD" value="GET" scope="axis2" type="STRING"/>
</case>
<case regex="POST">
<property name="messageType" value="application/json" scope="axis2"/>
<property name="ContentType"
value="application/JSON"
scope="axis2"
type="STRING"/>
<property name="HTTP_METHOD" value="POST" scope="axis2" type="STRING"/>
</case>
<default/>
</switch>
<send>
<endpoint>
<address uri="http://localhost:8888/jaxrs_basic/services/customers/customerservice"
format="rest"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<property name="messageType" value="application/json" scope="axis2"/>
<send/>
</outSequence>
</target>
</proxy>
I think links [1] & [2] will help you to set jms with WSO2 proxy... To dynamically add path param to the url use the link [3], it is for XML configuration file. similar to this you can assign the part of the message to a property add append that to the url...
[1] http://docs.wso2.org/wiki/display/ESB460/Publish-Subscribe+%28Pub-Sub%29+with+JMS
[2] http://wso2.org/library/articles/2011/11/wso2-esb-example-two-wayrequestresponse-semantic-jms
[3] How to dynamically route message in WSO2 ESB based on XML configuration file
Thanks,
Mohan