I have services that takes parameters as given below
> <book category="cooking">
> <title lang="en">Everyday Italian</title>
> <author>Giada De Laurentiis</author> <year>2005</year>
> <price>30.00</price> </book>
Now i want to hide parameters and i want my client should only see
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
</book>
how can is it possible in WSO2 ESB.
Any help would be so helpful.
I assume you want to hide some parameters to the client or consumer so that they will not have to pass them as part of their request. for instance, "price" element in your case.
Well, you can create the proxy as wsdl-based proxy with the appropriate wsdl file such that you don't have the "price" element in the request or in the respective complex type. Now, the clients will not be able see the "price" element in the request because you are describing the WSDL contract without "price" element.
Hope it helps :)
There are several ways to achieve this. You can use payload mediator, transform it via xslt, do it in script mediator etc. I think for your case I'd use payload mediator or xslt. After you've done payload/xslt you can send back the transfomrmed payload to your caller. You can find a lot of examples on the wso2 page.
e.g. here
https://docs.wso2.com/display/ESB481/PayloadFactory+Mediator
Hope that helps.
With a JS Mediator, you can do this:
<payloadFactory media-type="xml">
<format>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
</format>
<args/>
</payloadFactory>
<log level="full"/>
<script language="js"><![CDATA[
var msg = mc.getPayloadXML();
mc.setPayloadXML(
<book category="cooking">
<title lang="en">{msg..*::title}</title>
<author>{msg..*::author}</author>
<year>{msg..*::year}</year>
</book>
);
]]>
</script>
<log level="full"/>
The payloadFactory mediation above is just to define the XML you proposed in your question.
Additionally, you can use the payloadFactory mediator:
<payloadFactory media-type="xml">
<format>
<book category="cooking">
<title lang="en">$1</title>
<author>$2</author>
<year>$3</year>
</book>
</format>
<args>
<arg evaluator="xml" expression="//book/title/text()"/>
<arg evaluator="xml" expression="//book/author/text()"/>
<arg evaluator="xml" expression="//book/year/text()"/>
</args>
</payloadFactory>
Finally, for the XSLT approach, you can define a local-entry file in the synapse-config:
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="xsltToTransform" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="price"/>
</xsl:stylesheet>
</localEntry>
Then, in the mediation sequence, just invoke the defined local entry.
<xslt key="xsltToTransform"/>
Related
I'm newbie about validation on programming. Like Checking string and checking field input empty or not. Maybe anyone in here can share me about simple sample validation rule about string and checking field to me with XSLT. Thanks
First of all, XSLT is for XML transformations and if you want to do schema validations you should be looking at XSD validations. Having said that below is how you can use XSLT to validate a message and generate a payload.
Let's say you have a Payload like the below.
<Request>
<messages>
<message>
<id>123</id>
<name>Not Empty</name>
</message>
<message>
<id>234</id>
<name></name>
</message>
</messages>
</Request>
In the above payload, you want to check each message and check whether the name is empty or not. Inorder to validate this you can use XSLT. First create a XSLT as a LocalEntry in the local-entries directory. You can use the following content. (You can create your XSLT in the registry as well)
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="LOCAL_XSLT_NullCheck" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
<Response>
<!-- Iterating through message elements -->
<xsl:for-each select="//messages/message">
<message>
<messageID><xsl:value-of select="id/text()"/></messageID>
<xsl:choose>
<!-- Check if name is empty -->
<xsl:when test="boolean(name/text())">
<isEmpty>false</isEmpty>
</xsl:when>
<xsl:otherwise>
<isEmpty>true</isEmpty>
</xsl:otherwise>
</xsl:choose>
</message>
</xsl:for-each>
</Response>
</xsl:template>
</xsl:stylesheet>
</localEntry>
Next create a API to consume your request and to validate the payload and then to generate the response.
<?xml version="1.0" encoding="UTF-8"?>
<api context="/xslt" name="TestAPI" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<log level="full">
<property name="Message" value="Incoming Message"/>
</log>
<xslt key="LOCAL_XSLT_NullCheck"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Now once you invoke the API with the aforementioned message. You should see the following response.
<Response xmlns="http://ws.apache.org/ns/synapse">
<message>
<messageID>123</messageID>
<isEmpty>false</isEmpty>
</message>
<message>
<messageID>234</messageID>
<isEmpty>true</isEmpty>
</message>
</Response>
You ca read more on XSLT mediator from here. You can also consider using FastXSLT Mediator as well based on your requirement. Read more on XSLT from here.
How to set property of XML Object payload's to arguments () to call Wso2 ds using CLOB
Below is my payload which calling WSO2 DS :
<property name="messageType" scope="axis2" value="application/xml"/>
<property expression="$body/*" name="acclist" scope="default" type="OM"/>
<payloadFactory media-type="xml">
<format>
<Body>
<p_cif>$1</p_cif>
<p_acclist>$2</p_acclist>
</Body>
</format>
<args>
<arg evaluator="xml" expression="$ctx:cif"/>
<arg evaluator="xml" expression="$ctx:acclist"/>
</args>
</payloadFactory>
Error message of WSO2 DS :
Default Namespace: http://ws.wso2.org/dataservice
Current Request Name: _post_getacclist
Current Params: {p_acclist=, p_cif=00021118}
Nested Exception:-
DS Fault Message: Error in 'createProcessedPreparedStatement'
DS Code: UNKNOWN_ERROR
Nested Exception:-
java.sql.SQLRecoverableException: IO Error: 0 char of CLOB data cannot be read
I think Input Clob parameter(p_acclist) is null or empty,
When i convert $ctx:acclist to JSON, it is set upin arguments, But XML is not working
I can pass whole $body// it prints properly too, But i need inside element of this XML.
Basically i'am calling Data service using Clob(XML object) from Proxy service
Your problem is twofold:
the p_acclist element does not contain any kind of value, but more
xml. This needs to be in a CDATA block
A CDATA block in your payload factory won't work like that because the config is also XML. So the CDATA block in your payloadfactory/proxy will be ignored.
You can solve this by building the message using xslt, within the XSLT you can add the CDATA block as follows:
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:copy-of select="*"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
You could even pass on your property to the xslt like so:
<xslt key="xlsfilereference">
<property expression="$ctx:acclist" name="acclist">
</property>
</xslt>
And then use it in the xslt as follows:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="acclist"></xsl:param>
...
<Body>
<p_cif><xsl:value-of select="[path_to_cif_value]"/></p_cif>
<p_acclist>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:value-of select="$acclist"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</p_acclist>
</Body>
...
</xsl:stylesheet>
You might have to use copy-of instead of value-of in the above example.
Since the content of the acclist is not a valid XML can you try to enclose the elements with the CDATA tags? Please note that we will not be able to use the CDATA tags directly with the payload factory mediator due to its limitations. You can follow the steps below in order to add the CDATA tags.
Create a registry resource with the following elements(conf:/test/format.xml).
<Body>
<p_cif>$1</p_cif>
<p_acclist><![CDATA[$2]]></p_acclist>
</Body>
Modify the payload factory mediator as follows.
<payloadFactory media-type="xml">
<format key="conf:/test/format.xml"/>
<args>
<arg evaluator="xml" expression="$ctx:cif"/>
<arg evaluator="xml" expression="$ctx:acclist"/>
</args>
</payloadFactory>
create a file called XMLInputFactory.properties inside <EI_HOME>
Add the following content into the file
javax.xml.stream.isCoalescing=false
Hi in wso2 ei in payload factory i am getting the response in json
<payloadFactory media-type="json">
<format>{
"Body":$1
}
</format>
<args>
<arg evaluator="json" expression="$."/>
</args>
And the Response is :
{
"Body":{
"result":"done",
"idNumber":"123",
"address":{
"local":"US",
"abroad":"UK"
}
}
}
.... means multiple objects now what i need that all object first letter should be uppercase.
I need the below response
{
"Body":{
"Result":"done",
"IdNumber":"123",
"Address":{
"local":"US",
"abroad":"UK"
}
}
}
Means only the object first letter should be capitalize...Any help!
Replace payload mediator with xslt mediator .
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output method="text" indent="yes" media-type="application/json" encoding="UTF-8"/>
<xsl:template match="/">
{
Body :{
<xsl:for-each select="//*[local-name()='pid']">
Result:<xsl:value-of select="result"/>
IdNumber:<xsl:value-of select="idNumber"/>
</xsl:for-each>
}
}
</xsl:template>
</xsl:stylesheet>
Once this is done then you need to use property mediator so that the payload is still in json.
<property name="messageType" scope="default" type="STRING" value="application/json"/>
<property name="contentType" scope="default" type="STRING" value="application/json"/>
I hope to find help here... Here is the particular case:
I get this XML from my Endpoint:
<Entries>
<Entry>
<Customer>1</Customer>
</Entry>
<Entry>
<Customer>2</Customer>
</Entry>
<Entries>
I can easily convert this XML to JSON by changing the Property messageType, which will result in:
{"Entries":{"Entry":[{"Customer": 1}, {"Customer": 2}]}}
Here is what I want to get, as a JSON result (without wrappers):
[{"Customer": 1}, {"Customer": 2}]
Is there someone who knows how?
Many thanks in advance!
I think you've to first manipulate your xml (maybe with an xslt mediator) to format it this way
<jsonArray>
<Customer>1</Customer>
<Customer>2</Customer>
</jsonArray>
Then I guess you'll get your expected output.
For instance the following xslt could do the job
<xsl:stylesheet exclude-result-prefixes="xsl" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/Entries">
<xsl:element name="jsonArray">
<xsl:copy-of select="./Entry/Customer" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Thank you Anuruddha and Nicolas!
Your answers inspired me and I want to share what I did.
I have created this sequence, which I reuse with a Sequence mediator:
<sequence name="toJSON" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<property name="result" scope="default" type="STRING" expression="json-eval($.Entries.Entry)"/>
<payloadFactory media-type="json">
<format>$1</format>
<args>
<arg evaluator="xml" expression="$ctx:result"/>
</args>
</payloadFactory>
</sequence>
It works so well I even changed the sequence of all my Proxies, even those that returns only 1 result.
Many thanks for your lights!!
Good day!
I only recently began to study the ESB bus. I need to convert the incoming SOAP message in the HTTP request with Content-Type: application/x-www-form-urlencoded.
I have created a Proxy Service, Custom Mediator 1 in Java, transformed message, how do I pass it to the endpoint and get the answer in Custom Mediator 2?
In the picture I have drawn an example of how to transform the message.
You don't need to write custom mediators, you can transform SOAP to rest calls, sample with a rest service waiting for 2 parameters like
param1=value1¶m2=value2
<!-- prepare data for org.apache.axis2.transport.http.XFormURLEncodedFormatter message formatter -->
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<root>
<param1>$1</param1>
<param2>$2</param2>
</root>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg evaluator="xml" expression="$body/node1/node11/text()"/>
<arg evaluator="xml" expression="$body/node1/node12/text()"/>
</args>
</payloadFactory>
<!-- set output format -->
<property name="messageType" value="application/x-www-form-urlencoded" scope="axis2" type="STRING"/>
<property name="DISABLE_CHUNKING" value="true" scope="axis2" type="STRING"/>
<!-- call the REST endpoint with synch call : response is received in this sequence -->
<call>
<endpoint key="conf:endpoints/MyServiceEndpoint.xml"/>
</call>
<!-- the response is here, transform it has needed -->
<xslt key="myxsl"/>
<!-- send this response to the client -->
<property name="messageType" value="application/soap+xml" scope="axis2" type="STRING"/>
<!-- or test/xml and in this case, don't forget to specify a SOAP Action, below, a sample to specify a blank soapAction : -->
<header name="Action" value=""""/>
<send/>
Sample endpoint conf (with this sample, you need to define a property uri.var.ServiceURL in your sequence) :
<endpoint>
<http method="POST" uri-template="{uri.var.ServiceURL}/Path/2011-10-01"/>
</endpoint>
But if you really need your custom mediators, just replace payloadFactory and xslt mediators with them
Thanks for the reply, I still have to write custom mediator, just a very complex transformation messages
I will give an example how should I transform the message
SOAP message in my Proxy Service, send in custrom mediator
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<AddPay xmlns="http://MyTestService">
<!--input dynamic data-->
<fields>
<Items>
<Data>
<Name>Field1</Name>
<Value>11</Value>
</Data>
<Data>
<Name>Field2</Name>
<Value>22</Value>
</Data>
</Items>
</fields>
</AddPay>
</soap:Body>
</soap:Envelope>
The result of the transformation of the mediator
0000035401SM000000970000009700000121
api99 00000990
00000000
BEGIN // <!--input dynamic data-->
FIELD1=11 // Soap data
FIELD2=22 // Soap data
END
BEGIN SIGNATURE
iQBRAwkBAAAD3j2r2NwBAeevAf4nvAG4rGAyAePHkyVKTt7wffzURhOckd3ctgmG
yQkKWkXh3CLpsbrExsllVUBlO6ih8qHozk2uttXApzHXQXoO
=+pch
END SIGNATURE
Request to the HTTP Server
POST /cgi-bin/es/es_pay_check.cgi HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 498
inputmessage=0000035401SM000000970000009700000121%0D%0Aapi99+
+++++++++++00000990%0D%0A++++++++++++++++++++00000000%0ABEGIN%0D%
0FIELD1%11%0FIELD2%220AEND%0D%0ABEGIN+SIGNATURE%0AiQBRAwkBAABCiUs
00dQBATG5AgDHdZ6RYHykL46QBaAvnHYaY4p0pDjgjO4K1Iyj%0D%0AfSBSvCRpS%2
F0EYO9NspuyLeANEQQkkGE%2F37gUxiPqzAgStXjpsAHH%0D%0A%3DvSgb%0AEND+
SIGNATURE
The response from the HTTP Server, pass in custrom mediator to transform into SOAP
0000030301SM000000460000004600000121
0J0005 00064182
00000000
BEGIN
DATE=04.10.2014 12:34:12
ERROR=0
ERRMSG=
FIELD3=33
FIELD4=44
FIELD5=55
END
BEGIN SIGNATURE
iQBRAwkBAAD6tj1BJ10BAYKxAfsHlQsEFnO2k6ry++W8O8AiJuv4gT+ZVCfZHsKk
c0CbZpP/W3vkljG3xNzMLiqjbwkNuIdwR9Dq7gHmH+ZQMhbT
=LOnP
END SIGNATURE
The result in the Proxy service
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<AddPayResponse xmlns="http://MyTestService">
<AddPayResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Data>
<Items>
<!--output dynamic data-->
<Data>
<Name>Field3</Name>
<Value>33</Value>
</Data>
<Data>
<Name>Field4</Name>
<Value>44</Value>
</Data>
<Data>
<Name>Field5</Name>
<Value>55</Value>
</Data>
</Items>
</Data>
<ErrCode>0</ErrCode>
<ErrMsg>Ok</ErrMsg>
</AddPayResult>
</AddPayResponse>
</s:Body>
</s:Envelope>