I want to read from an xml file in my esb home directory called test.xml whose content is:
<a>Helloo
<b>World</b>
</a>
I have written a proxy to access content of node b as:
<proxy xmlns="http://ws.apache.org/ns/synapse" name="ReadFileProxy" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<property name="test" expression="get-property('registry','conf:/test.xml')" scope="default" type="OM"/>
<log level="custom">
<property name="test.b" expression="$ctx:test//b"/>
</log>
<header name="To" action="remove"/>
<property name="RESPONSE" value="true" scope="default" type="STRING"/>
<property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
<payloadFactory>
<format>
<getCombinedResponse>Succefully read</getCombinedResponse>
</format>
</payloadFactory>
<send/>
</inSequence>
</target>
<description></description>
</proxy>
But it is giving me error as:
[2013-06-18 16:29:09,524] ERROR - NativeWorkerPool Uncaught exception
org.apache.axiom.om.OMException: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
at [row,col {unknown-source}]: [1,0]
at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:296)
at org.apache.axiom.om.impl.llom.OMDocumentImpl.getOMDocumentElement(OMDocumentImpl.java:109)
at org.apache.axiom.om.impl.builder.StAXOMBuilder.getDocumentElement(StAXOMBuilder.java:570)
at org.apache.axiom.om.impl.builder.StAXOMBuilder.getDocumentElement(StAXOMBuilder.java:566)
at org.apache.axiom.om.util.AXIOMUtil.stringToOM(AXIOMUtil.java:54)
at org.apache.axiom.om.util.AXIOMUtil.stringToOM(AXIOMUtil.java:39)
at org.apache.synapse.config.SynapseConfigUtils.stringToOM(SynapseConfigUtils.java:766)
at org.apache.synapse.mediators.builtin.PropertyMediator.convertValue(PropertyMediator.java:317)
at org.apache.synapse.mediators.builtin.PropertyMediator.getResultValue(PropertyMediator.java:299)
at org.apache.synapse.mediators.builtin.PropertyMediator.mediate(PropertyMediator.java:95)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:71)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:114)
at org.apache.synapse.core.axis2.ProxyServiceMessageReceiver.receive(ProxyServiceMessageReceiver.java:154)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:434)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:219)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
What am i doing wrong in this. Is there any other method to read from any file(pdf,txt and xml only).
As you have specified in the configuration
<property name="test" expression="get-property('registry','conf:/test.xml')" scope="default" type="OM"/>
you are referring a file which is saved in the registry. This is why you need to save that in the registry.
You can use VFS transport to read from a file. Please reffer the sample [1]. From this sample you can get to know how to read from a file. This sample directly sends the content to an endpoint. For your case you can use an xpath expression to retrieve the element b.
<property name="test.b" expression="//a/b"/>
[1]http://docs.wso2.org/wiki/pages/viewpage.action?pageId=16846489
Related
I am writing an iterate mediator, the code is going in the sequence written in that iterate mediator, it is completing too (read through logs) however, it is not going to next step. Please help me with what wrong am I doing.
<iterate expression="//mpesa/prov">
<target>
<sequence>
<sequence key="ProvMapperQueue"/>
</sequence>
</target>
</iterate>
<log level="custom">
<property name="After" value="Sequence"/>
</log>
It is now printing the logs neither is API getting a response, its stuck after sequence last line is logged.
For further information copying the sequence below too:
<sequence name="ProvMapperQueue" onError="ProvMapperQueue_Error" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="ProvMapperQueue Sequence" value="Started"/>
</log>
<property name="messageType" scope="axis2" type="STRING" value="text/xml"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<call>
<endpoint key="OBD_EP"/>
</call>
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="After Calling" value=" ProvMapperQueue EP"/>
<property name="ProvMapperQueue Sequence" value="Ended"/>
</log>
<respond/>
</sequence>
Logs printing are below :
[2023-01-24 00:14:07,883] INFO {LogMediator} - {api:OBD} Msisdn = 110000171, ProvMapperQueue Sequence = Started
[2023-01-24 00:14:07,893] INFO {TimeoutHandler} - This engine will expire all callbacks after GLOBAL_TIMEOUT: 120 seconds, irrespective of the timeout action, after the specified or optional timeout
[2023-01-24 00:14:08,181] INFO {LogMediator} - {api:OBD} Msisdn = 110000171, After Calling = ProvMapperQueue EP, ProvMapperQueue Sequence = Ended
[2023-01-24 00:17:06,839] INFO {SourceHandler} - Writer null when calling informWriterError
[2023-01-24 00:17:06,841] WARN {SourceHandler} - STATE_DESCRIPTION = Socket Timeout occurred after accepting the request headers and the request body, INTERNAL_STATE = REQUEST_DONE, DIRECTION = REQUEST, CAUSE_OF_ERROR = Connection between the client and the EI timeouts, HTTP_URL = /obd/prov/msisdn/110000171, HTTP_METHOD = GET, SOCKET_TIMEOUT = 180000, CLIENT_ADDRESS = /127.0.0.1:59198, CONNECTION http-incoming-4
Any help would mean a lot.
I think the problem is with the <respond/> mediator that you have added towards the end of the ProvMapperQueue sequence. This will stop further processing of a message and send the message back to the client[1]. That means, after it, the rest of the sequence logic will not be executed including the log mediator outside the iterate mediator.
[1] - https://docs.wso2.com/display/EI611/Respond+Mediator
Few issues with your integration. You need to remove the respond mediator from the Iterate sequence, as responding per iteration doesn't make sense. So, I believe what you need is to iterate over the entries and once done, respond back to the client. In order to wait for all the Iterations to finish you need to couple the iterate mediator with an aggregate mediator. Hence update the sequences like below.
<sequence name="ProvMapperQueue" onError="ProvMapperQueue_Error" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="ProvMapperQueue Sequence" value="Started"/>
</log>
<property name="messageType" scope="axis2" type="STRING" value="text/xml"/>
<property name="OUT_ONLY" scope="default" type="STRING" value="true"/>
<call>
<endpoint key="OBD_EP"/>
</call>
<log level="custom">
<property expression="$ctx:uri.var.msisdn" name="Msisdn"/>
<property name="After Calling" value=" ProvMapperQueue EP"/>
<property name="ProvMapperQueue Sequence" value="Ended"/>
</log>
</sequence>
<iterate expression="//mpesa/prov" id="iterateid">
<target>
<sequence>
<sequence key="ProvMapperQueue"/>
</sequence>
</target>
</iterate>
<aggregate id="iterateid">
<completeCondition>
<messageCount max="-1" min="-1"/>
</completeCondition>
<onComplete expression="$body/*[1]">
<payloadFactory media-type="xml">
<format>
<payload xmlns="">
<response>Done</response>
</payload>
</format>
<args/>
</payloadFactory>
<respond/>
</onComplete>
</aggregate>
Update
The issue is you have set the OUT_ONLY property in your sequence hence the aggregate is never completed since callbacks are not registered. Instead of Iterate Mediator use the Foreach Mediator for your usecase. Check the example below.
<foreach expression="//mpesa/prov">
<sequence>
<sequence key="ProvMapperQueue"/>
</sequence>
</foreach>
<log level="custom">
<property name="After" value="Sequence"/>
</log>
<payloadFactory media-type="xml">
<format>
<payload xmlns="">
<response>Done</response>
</payload>
</format>
<args/>
</payloadFactory>
<respond/>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="ctc"
startOnLoad="true"
statistics="enable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<log>
<property name="******" value="---ctc---"/>
</log>
<property xmlns:saop="http://j2ee.netbeans.org/wsdl/EsbJyBpel/src/saopWSDL"
expression="$body//saop:upload/xml"
name="request_msg"/>
<log>
<property expression="json-eval($)" name="request_msg"/>
</log>
<property name="messageType"
scope="axis2"
type="STRING"
value="application/json"/>
<script language="js">mc.setPayloadJSON(
{
"Code" : "10",
"Price" : "11"
});</script>
<property name="HTTP_METHOD" scope="axis2" value="POST"/>
<property name="messageType"
scope="axis2"
type="STRING"
value="application/json"/>
<property name="Content-Type"
value="application/json"
scope="transport"
type="STRING"/>
<send>
<endpoint>
<address format="pox" uri="http://192.16.110.142:8081/dqcsweb/ES/test"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<log>
<property expression="json-eval($)" name="res_msg"/>
</log>
<send/>
</outSequence>
</target>
</proxy>
The XML structure that the restful service log prints;
How do You convert an XML structure to JSON?
I used script and payloadFactory, output the JSON string in the ESB, and the print log in the invoked service is still XML
input:
enter image description here
The message received by the service(http://192.16.110.142:8081/dqcsweb/ES/test):
<jsonObject><Code>10</Code><Price>11</Price></jsonObject>
expectations:
{
"code":"10",
"Price":"11"
}
Can you change the format of the endpoint invoked to rest. Please refer to the follwoing sample configuration.
<send>
<endpoint>
<address format="rest" uri="http://192.16.110.142:8081/dqcsweb/ES/test"/>
</endpoint>
</send>
The used pox format results in the message transformed into plain old XML format. Please refer to the documentation [1] to further clarify this.
[1]-https://docs.wso2.com/display/EI611/Address+Endpoint
Update
Can you enable wire logs by uncommenting the following [2] in log4j.properties file. You need to perform a server restart to enable this. This allows you to see the request sent out of the EI server. Please check if the request going out of the EI contains the necessary payload.
log4j.logger.org.apache.synapse.transport.http.wire=DEBUG
[2]-https://docs.wso2.com/display/ESB500/Debugging+Mediation#DebuggingMediation-Viewingwirelogs
i'm facing some problems with this process.. let me explain:
i want to call two services and join the responses in this order:
i have the first service's response:
<locations xmlns="http://ssocial.com/traceit/services/location">
<location>
<latitude>-33.45209980</latitude>
<longitude>-70.66241990</longitude>
<altitude>0.0</altitude>
<creation>2016-09-04T14:59:48.000-03:00</creation>
<updated>2016-09-04T14:59:48.000-03:00</updated>
<deviceId>25</deviceId>
</location>
<location>
<latitude>-33.45149521</latitude>
<longitude>-70.66146224</longitude>
<altitude>817.0</altitude>
<creation>2016-09-04T13:18:43.000-03:00</creation>
<updated>2016-09-04T13:18:43.000-03:00</updated>
<deviceId>25</deviceId>
</location>
</locations>
then i have the secon service's response :
<device xmlns="http://ssocial.com/traceit/services/device">
<id>25</id>
<code>mobile_02</code>
<type>
<id>1</id>
<name>MOBILE</name>
</type>
And then, the final response that i would like to have is :
<locations xmlns="http://ssocial.com/traceit/services/location">
<location>
<latitude>-33.45209980</latitude>
<longitude>-70.66241990</longitude>
<altitude>0.0</altitude>
<creation>2016-09-04T14:59:48.000-03:00</creation>
<updated>2016-09-04T14:59:48.000-03:00</updated>
<deviceId>25</deviceId>
<device xmlns="http://ssocial.com/traceit/services/device">
<id>25</id>
<code>mobile_02</code>
<type>
<id>1</id>
<name>MOBILE</name>
</type>
</device>
</location>
<location>
<latitude>-33.45149521</latitude>
<longitude>-70.66146224</longitude>
<altitude>817.0</altitude>
<creation>2016-09-04T13:18:43.000-03:00</creation>
<updated>2016-09-04T13:18:43.000-03:00</updated>
<deviceId>25</deviceId>
<device xmlns="http://ssocial.com/traceit/services/device">
<id>25</id>
<code>mobile_02</code>
<type>
<id>1</id>
<name>MOBILE</name>
</type>
</device>
</location>
</locations>
i'm really having lot of troubles trying to join both responses like that, and this is my sequence in wso2:
<sequence name="getDeviceInfoByLocationProcess" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property expression="count(//ns1:locations/ns1:location)" name="LOCATIONS_COUNT" scope="default" type="STRING" xmlns:ns1="http://ssocial.com/traceit/services/location"/>
<iterate description="" expression="//ns1:locations/ns1:location/ns1:deviceId" id="LOCATIONS_ITERATOR" xmlns:ns1="http://ssocial.com/traceit/services/location">
<target>
<sequence>
<property description="device_id" expression="//ns1:deviceId" name="device_id" scope="default" type="STRING"/>
<sequence key="getDeviceInfoProcess"/>
</sequence>
</target>
</iterate>
<log level="custom">
<property expression="//ns1:locations" name="LOCATIONS" xmlns:ns1="http://ssocial.com/traceit/services/location"/>
<property expression="//ns2:device" name="DEVICE_INFO" xmlns:ns2="http://ssocial.com/traceit/services/device"/>
</log>
<property name="ECNCLOSING_ELEMENT" scope="default">
<wrapper xmlns=""/>
</property>
<aggregate id="AGG_01">
<completeCondition>
<messageCount max="-1" min="{get-property('LOCATIONS_COUNT')}"/>
</completeCondition>
<onComplete expression="//ns2:device" xmlns:ns2="http://ssocial.com/traceit/services/device">
<log level="full">
<property expression="$ctx:LOCATIONS_COUNT" name="COUNTER"/>
<property expression="$ctx:ECNCLOSING_ELEMENT" name="ENCLOSING"/>
</log>
<call/>
</onComplete>
</aggregate>
and actually with this sequence, i'm just getting this:
<device xmlns="http://ssocial.com/traceit/services/device">
<id>25</id>
<code>mobile_02</code>
<type>
<id>1</id>
<name>MOBILE</name>
</type>
In advance , thank you very much for the help
I can't see the content of "getDeviceInfoProcess" sequence, but I guess your are using call mediator. So, as a result of those requests (multiple requests because of iterate mediator), you receive some responses and that what you have to deal with in the rest of the initial mediation : aggregate offers you a way to wait for all the responses, but the initial message is lost : you should save it in a property (type OM) and use something like payloadMediator inside aggregate/onComplete to compose the final message.
I have created an API that accepts a .xlsx file as POST input.
Code is mentioned below:
<api xmlns="http://ws.apache.org/ns/synapse" name="classroomcourse" context="/classroomcourse">
<resource methods="POST">
<inSequence>
<log level="full"/>
<property name="messageType" value="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" scope="axis2"/>
<send>
<endpoint>
<http uri-template="http://qa-aaa.ggg.com/xyz/api/importCourses"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full"/>
<property name="messageType" value="application/json" scope="axis2"/>
<send/>
</outSequence>
When I send request via POSTMAN and attach xlsx file then I get the below error:
[2016-03-02 17:32:13,332] ERROR - Error while building Passthrough stream {org.apache.synapse.transport.passthru.util.RelayUtils}
org.apache.axiom.om.OMException: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character '"' (code 34) in DOCTYPE declaration; expected a space be
tween public and system identifiers
at [row,col {unknown-source}]: [1,50]
at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:296)
at org.apache.axiom.om.impl.llom.OMDocumentImpl.getOMDocumentElement(OMDocumentImpl.java:109)
at org.apache.axiom.om.impl.builder.StAXOMBuilder.getDocumentElement(StAXOMBuilder.java:570)
at org.apache.axiom.om.impl.builder.StAXOMBuilder.getDocumentElement(StAXOMBuilder.java:566)
at org.apache.synapse.transport.passthru.util.DeferredMessageBuilder.getDocument(DeferredMessageBuilder.java:149)
at org.apache.synapse.transport.passthru.util.RelayUtils.builldMessage(RelayUtils.java:133)
at org.apache.synapse.transport.passthru.util.RelayUtils.buildMessage(RelayUtils.java:98)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:72)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:48)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:149)
at org.apache.synapse.rest.Resource.process(Resource.java:297)
Kindly guide me how can I solve this issue.
Make sure that the right message builder is enabled in the axis2.xml file, for the Content type of the ESB inbound request.
Also try removing the <log level="full"/> in inSequence.
<resource methods="GET" uri-template="/getTypeCodes" faultSequence="service_error_handler_">
<inSequence>
<log level="custom">
<property name="CommonService" value="*************getTypeCodes called**************"/>
<property name="Request Payload" expression="get-property('JSON_OBJECT')"/>
</log>
<property name="HTTP_METHOD" value="GET" scope="axis2" type="STRING"/>
<property name="messageType" value="application/json" scope="axis2" type="STRING"/>
<sequence key="oauthMediationService"/>
<property name="uri.var.servicename" value="commonservice"/>
<send>
<endpoint>
<address uri="http://localhost:8080/rest/commonservice/getTypeCodes" format="rest"/>
</endpoint>
</send>
<log level="custom">
<property name="getTypeCodeResponse" expression="$body"/>
</log>
</inSequence>
<outSequence>
<send/>
</outSequence>
From the above rest example configuration i am calling the service in endpoint. After calling the endpoint i need to get the response and send that response to the the another endpoint based on condition.
You can use following configuration to call to reset service and get a response. In below sample I'm using HTTP endpoint
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="peoplePutProxy"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<property name="HTTP_METHOD" value="GET" scope="axis2"/>
<property name="messageType"
value="application/x-www-form-urlencoded"
scope="axis2"/>
<send>
<endpoint>
<http method="post"
uri-template="http://localhost:8080/rest/api/people?email={uri.var.email}&firstName={uri.var.fname}&lastName={uri.var.lname}"/>
<property name="uri.var.fname" value="dhar"/>
<property name="uri.var.email" value="kasun#gmail.com"/>
<property name="uri.var.lname" value="kasun"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<log level="full"/>
<property name="messageType" value="text/xml" scope="axis2"/>
<send/>
</outSequence>
</target>
<description/>
</proxy>
Http end point is where users can specify an URI Template which can dynamically populate final URI for the RESTful service invocation. Also, users can manipulate HTTP method of the outgoing request.
Please refer [1] for more information on http endpoint
[1]. http://docs.wso2.org/display/ESB470/HTTP+Endpoint
Your requirement is called 'Service Chaining'. This blog post explains how to achieve service chaining in WSO2 ESB. Go through the other article linked at the start of that blog to get a better understanding. They provide a complete example of service chaining.
Basically you can specify a sequence as the receiver of the response in a send mediator as follows.
<send receive="RespSequence">
<endpoint>
<address uri="http://localhost:8080/rest/commonservice/getTypeCodes" format="rest"/>
</endpoint>
</send>
In this case the response from calling the endpoint will be directed to RespSequence. So in that sequence you can specify the other endpoint.Refer Send Mediator doc for more info. Use Switch Mediator to check for conditions.