I'm using the wso2 integration studio 7.1.0.
When I'm trying to modify the obtained payload from an external endpoint call, if the endpoint response has a list longer than 4549 elements, than the JsonXMLStreamReader gives a StackOverflowError.
This problem occurs with several mediators: Iterator, PayloadFactory, Script...
I've already checked the JVM memory parameters and I've already tried to change the axis2 JsonFormatter and JsonBuilder.
The simplest example I tried is to call the end point that returns a json holding a list of integers. Then a Script mediator with nashornJS takes the payload add field to the json and reset the payload. If the returned list from the endpoint is smaller than 4549 elements it works correctly, otherwise it gets a StackOverflowError exception.
wso2 code:
<resource methods="GET" uri-template="/cc">
<inSequence>
<call>
<endpoint key="l2-prova"/>
</call>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
<resource methods="GET" uri-template="/dd">
<inSequence>
<call>
<endpoint key="l2-prova"/>
</call>
<script language="nashornJs"><![CDATA[body = mc.getPayloadJSON();
body.len = body.list.length
mc.setPayloadJSON(body)]]></script>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
exception:
[2020-11-04 10:55:53,044] ERROR {org.apache.axis2.transport.base.threads.NativeWorkerPool} - Uncaught exception java.lang.StackOverflowError
at org.apache.synapse.commons.staxon.core.json.stream.impl.JsonScanner.yytext(JsonScanner.java:481)
at org.apache.synapse.commons.staxon.core.json.stream.impl.JsonScanner.yylex(JsonScanner.java:903)
at org.apache.synapse.commons.staxon.core.json.stream.impl.JsonScanner.nextSymbol(JsonScanner.java:310)
at org.apache.synapse.commons.staxon.core.json.stream.impl.JsonStreamSourceImpl.next(JsonStreamSourceImpl.java:156)
at org.apache.synapse.commons.staxon.core.json.stream.impl.JsonStreamSourceImpl.peek(JsonStreamSourceImpl.java:272)
at org.apache.synapse.commons.staxon.core.json.JsonXMLStreamReader.consume(JsonXMLStreamReader.java:151)
at org.apache.synapse.commons.staxon.core.json.JsonXMLStreamReader.consume(JsonXMLStreamReader.java:213)
at org.apache.synapse.commons.staxon.core.json.JsonXMLStreamReader.consume(JsonXMLStreamReader.java:213)
at org.apache.synapse.commons.staxon.core.json.JsonXMLStreamReader.consume(JsonXMLStreamReader.java:213)
...
When JsonXMLStreamReader consuming the json payload, it goes through the following method call.
https://github.com/wso2/wso2-synapse/blob/master/modules/commons/src/main/java/org/apache/synapse/commons/staxon/core/json/JsonXMLStreamReader.java#L149
The above is a recursive method that is consuming the stack until it finishes reading the last element of the array.
Hence, the StackOverflow error is causing by a large number of array elements.
try to increase the stack size from the JVM and check again.
Related
I'm using wso2 esb 4.8.1 version for SOAP to rest conversion with as API. I have a soap request with xsi values. After I generate the proper soap request with script mediator and um getting an expected response. But I have an issue with response. Because I need t convert the soap response into json. When I tried with following out sequence um not getting the proper json response with axis2. How can I convert this soap response into json properly?
This it the soap response.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:easyDownloadResponse xmlns:ns1="http://usermanage.ivas.huawei.com" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<easyDownloadReturn href="#id0"/>
</ns1:easyDownloadResponse>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://response.usermanage.ivas.huawei.com" id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:EasyDownloadResp">
<eventClassName xsi:type="xsd:string" xsi:nil="true"/>
<failedResources xsi:type="soapenc:Array" xsi:nil="true"/>
<operationID xsi:type="xsd:long">0</operationID>
<resultCode xsi:type="xsd:int">0</resultCode>
<resultInfo xsi:type="xsd:string" xsi:nil="true"/>
<returnCode xsi:type="xsd:string">000000</returnCode>
<toneTransactionID xsi:type="soapenc:Array" xsi:nil="true"/>
<transactionID xsi:type="xsd:string" xsi:nil="true"/>
</multiRef>
</soapenv:Body>
</soapenv:Envelope>
This is the response which i'm getting
{"easyDownloadResponse":{"#encodingStyle":"http://schemas.xmlsoap.org/soap/encoding/","easyDownloadReturn":{"#href":"#id0"}}}
This is my out sequence
<outSequence xmlns="http://ws.apache.org/ns/synapse">
<property name="messageType" value="application/json" scope="axis2" type="STRING"></property>
<send></send>
</outSequence>
All your answers are highly welcome.
Finally I found the solution for the issue. In the normal case we use
<property name="messageType" value="application/json" scope="axis2" type="STRING"></property>
But this axis2 property cannot convert the complex soap response into json such as with xsi.
For that need to use the following axis2 property. Then it converts the entire soap response into Json as we expected.
<property name="messageType" value="application/json/badgerfish" scope="axis2" type="STRING"></property>
This is my full outsequence.
<outSequence xmlns="http://ws.apache.org/ns/synapse">
<property name="messageType" value="application/json/badgerfish" scope="axis2" type="STRING"></property>
<send></send>
</outSequence>
You can try payload mediator to get exact json format 1. But still you may have to uncomment the following lines in
$ESB_HOME/repository/conf/axis2/axis2.xml
<!--messageFormatter contentType="application/json"
class="org.apache.axis2.json.JSONStreamFormatter"/-->
<!--messageBuilder contentType="application/json"
class="org.apache.axis2.json.JSONStreamBuilder"/-->
By default, JSON messages are converted to XML when they are received by the PayloadFactor mediator. However, if you enable the JSON stream formatter and builder, incoming JSON messages are left in JSON format.
And also you can use script mediator again (In outsequence) to modify your json response. Refer this sample
I have setup a REST endpoint in WSO2 AM that calls out to another REST endpoint. When the call is made I am receiving a 411 response code. The request contains a JSON body, the content type and accepts header are set to application/json. I can curl the backing service that WSO2 is accessing directly with the same params and it works correctly. It seems that WSO2 AM is stripping or not sending the content-length.
Why is the content length not being sent to the REST endpoint that is being accessed?
Sending content-length is disabled by default because it can cause performance degradation. But you can enable it by adding following to the api's insequence. (see https://docs.wso2.com/display/AM1100/Adding+Mediation+Extensions on adding custom sequence to an api)
<property name="COPY_CONTENT_LENGTH_FROM_INCOMING" value="true" scope="axis2"/>
<property name="FORCE_HTTP_CONTENT_LENGTH" scope="axis2" value="true"></property>
following is a sample sequnce
<sequence xmlns="http://ws.apache.org/ns/synapse" name="contentLengthadd">
<property name="COPY_CONTENT_LENGTH_FROM_INCOMING" value="true" scope="axis2"/>
<property name="FORCE_HTTP_CONTENT_LENGTH" scope="axis2" value="true"></property>
</sequence>
This sequence will get the content length from incoming request request and pass it the request header to the backend.
you can read more about these two properties in https://docs.wso2.com/display/ESB481/HTTP+Transport+Properties#HTTPTransportProperties-FORCE_HTTP_CONTENT_LENGTH
There are numerous examples of using the mailto transport in WSO2 ESB to send emails (based on filter mediator, fault sequence etc.). However, I have attempted this a number of ways all with the same result i.e. that the proxy service never terminates. I am testing this using SOAPUi.
This is my proxy service
<proxy xmlns="http://ws.apache.org/ns/synapse" name="TMCService" transports="https,http" statistics="enable" trace="enable" startOnLoad="true">
<target inSequence="gov:/trunk/sequences/seqGetTMCData">
<outSequence>
<filter xmlns:trac="http://mynamespaceuri" xpath="//trac:SaveIncidentsResponse">
<then>
<log level="full"/>
<property name="Subject" value="CEP Event" scope="transport"/>
<property name="OUT_ONLY" value="true"/>
<send>
<endpoint>
<address uri="mailto:conrad.crampton#gmail.com"/>
</endpoint>
</send>
</then>
<else>
<send/>
</else>
</filter>
</outSequence>
</target>
<description></description>
</proxy>
the email sends no problem with the response from the inSequence - no problem, it just never terminates. I have to manually stop it in SOAPUi to stop.
I've tried putting drop after the send in the then element, that doesn't work either.
I guess I am missing something fundamental in how I am understanding the out sequence to work, but this is pretty much lifted from the many examples out there and no one else appears to be having the same issue as me.
Any suggestions/ pointers??
WSO2 ESB v4.5.1
I have resolved this by cloning the response message, sending one to the mailto transport and sending the other one as a default send (no endpoint) which returns back to the client.
Kind of makes sense as the OUT_ONLY property is explicitly saying there will be no response, so have ensure that the client receives one by cloning the message.
Still welcome any other comments if there is another way of doing this without clone mediator.
So why doesn't the examples show this!
I am using Spring 3.2.5 to create a RESTful web service. To implement it I've used #ResponseBody tag. When I use InternalResourceViewResolver and try to load Html response then it is working fine. But when I call a URL which is marked as #ResponseBody then it gives HTTP 406 error code with error text as
The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.
I have included Jackson jar files in my lib directory as well.
Here is my controller method which handles service request.
#ResponseBody
#RequestMapping (value = "/resp.htm")
public Data jsonResp() {
Data d = new Data();
d.setName("TEst");
d.setAddr("Address....");
return d;
}
There are lots of questions have been asked & answered, I've tried many of them, but it still gives the same result. Then I came across a new kind of answer, which was stating to use ContentNegotiatingViewResolver. By using it I am able to view response in intended format. That is JSON format.
After using ContentNegotiatingViewResolver, servlet dispatcher code looks like this:
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
</map>
</property>
<property name="defaultViews">
<list>
<!-- JSON View -->
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="2" />
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
So, my question is, whenever we require to use Spring's Web Service feature, do we must require to have ContentNegotiatingViewResolver?
Add gson in your class path. as well as jackson
I had a similar issue while calling a spring rest service from angular 8 for uploading a file. I was using ResponseEntity to encapsulate the success or failure message for which I was having the 406 response. all I did was in the UI side this.httpClient.post(url, formData,{responseType: 'text'}) and I was able accept the string as response from the service response.
The annotation #ResponseBody used with custom class types, generally uses MappingJackson2HttpMessageConverter to convert the object to JSON and return it in application/json content.
Since your request doesn't contain an Accept header for application/json, Spring deems the content it's creating as unacceptable and instead returns a 406.
You could simply change your request to add the Accept header. (You can't do this easily in a browser).
In my case the request had .html suffix and received this error. Once removed, it worked fine.
All you need to do is to add jackson libraries to your classpath find them Here
I am creating some services using JAX-RS that need to take in arbitrarily complex objects as arguments, not just primitives like integers and strings. A discussion on the CXF mailing list says to just use a wrapper object as a single parameter in this case.
My concern is how to document the input format to the service? If creating a service that looks something like the following:
#POST
#Produces("application/json")
#Consumes("application/json")
#Path("oneParam")
public ComplexObject2 myServiceMethod(ComplexObject1 obj) {
Foo f = obj.foo
Bar b = obj.bar
...
}
the auto-generated WADL that CXF produces will only produce the following:
<resource path="/oneParam">
<method name="POST">
<request>
<representation mediaType="application/json"/>
</request>
<response>
<representation mediaType="application/json"/>
</response>
</method>
</resource>
This contains no information on what the request or response actually contains. Sergey on the CXF mailing list said it was possible to link a schema to the representation, but how am I supposed to do that? And how do I create the XSD?
(P.S. Using POST for idempotent resources might not be RESTful, but it's not important here as we are in essence doing RPC using Json. This is more or less a 1:1 clone of an existing SOAP based api.)
It is possible to link an XSD file into a WADL file and then to reference an XML element in the representation for requests and responses. However, as it is XML schema it doesn't apply to JSON representations.
To link an XSD into a WADL file, create a grammars element at the top of the file before the main resources element.
<grammars>
<include href="myapp.xsd"/>
</grammars>
Then add a reference to an XML element as follows (using a modified version of your example):
<resource path="/oneParam">
<method name="POST">
<request>
<representation mediaType="application/xml" element="myapp:oneParamRequest" />
</request>
<response>
<representation mediaType="application/xml" element="myapp:oneParamResponse" />
</response>
</method>
</resource>
The prefix myapp is defined in the XSD and can be used in the WADL file as well.
I don't know to to configure CXF to do this automatically. My experience with Jersey is similar and we use the generated WADL as a starting point for hand-editing later.