0

I am attempting to make a blocking call that retrieves a PDF file, but an error is thrown whenever I try to use the returned payload (including sending it).

The error is "Attempted read on closed stream", and I think it's happening because the response is being parsed into xml only when it's needed, but by then the call mediator has closed the connection.

Here is an example sequence:

<call blocking="true">
  <endpoint>
    <http uri-template="https://myserver.com/generatePDF?id=1234" method="GET"/>
  </endpoint>
</call>

<log level="custom">
  <property name="msg" value="Complete"/>
</log>

<log level="custom">
  <property name="body" expression="$body"/>
</log>

<log level="full"/>

Watching the logs, the call is made and it waits for the response. Once the response is completed the "Completed" log message is printed. But when it tries to access the $body the following error occurs:

[2016-05-19 13:03:21,582]  INFO - LogMediator msg = Complete
[2016-05-19 13:03:21,584] ERROR - SequenceMediator Error reading data handler
org.apache.axiom.om.OMException: Error reading data handler
    at org.apache.axiom.om.impl.llom.OMTextImpl.internalSerialize(OMTextImpl.java:421)
    at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:555)
    at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:875)
    at org.apache.axiom.om.impl.util.OMSerializerUtil.serializeChildren(OMSerializerUtil.java:555)
    at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:875)
    at org.apache.axiom.om.impl.llom.OMSerializableImpl.serialize(OMSerializableImpl.java:125)
    at org.apache.axiom.om.impl.llom.OMSerializableImpl.serialize(OMSerializableImpl.java:113)
    at org.apache.axiom.om.impl.llom.OMElementImpl.toString(OMElementImpl.java:988)
    at org.apache.synapse.util.xpath.SynapseXPath.stringValueOf(SynapseXPath.java:321)
    at org.apache.synapse.mediators.MediatorProperty.getEvaluatedExpression(MediatorProperty.java:138)
    at org.apache.synapse.mediators.builtin.LogMediator.setCustomProperties(LogMediator.java:216)
    at org.apache.synapse.mediators.builtin.LogMediator.getCustomLogMessage(LogMediator.java:139)
    at org.apache.synapse.mediators.builtin.LogMediator.getLogMessage(LogMediator.java:125)
    at org.apache.synapse.mediators.builtin.LogMediator.mediate(LogMediator.java:95)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:81)
    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.core.axis2.ProxyServiceMessageReceiver.receive(ProxyServiceMessageReceiver.java:185)
    at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
    at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:395)
    at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:142)
    at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: Attempted read on closed stream.
    at org.apache.commons.httpclient.AutoCloseInputStream.isReadAllowed(AutoCloseInputStream.java:183)
    at org.apache.commons.httpclient.AutoCloseInputStream.read(AutoCloseInputStream.java:107)
    at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:238)
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
    at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:116)
    at java.io.FilterInputStream.read(FilterInputStream.java:107)
    at org.wso2.carbon.relay.BinaryRelayBuilder.readAllFromInputSteam(BinaryRelayBuilder.java:39)
    at org.wso2.carbon.relay.StreamingOnRequestDataSource.getInputStream(StreamingOnRequestDataSource.java:59)
    at javax.activation.DataHandler.writeTo(DataHandler.java:305)
    at org.apache.axiom.util.stax.XMLStreamWriterUtils.writeBase64(XMLStreamWriterUtils.java:62)
    at org.apache.axiom.util.stax.XMLStreamWriterUtils.writeDataHandler(XMLStreamWriterUtils.java:138)
    at org.apache.axiom.om.impl.llom.OMTextImpl.internalSerialize(OMTextImpl.java:418)
    ... 24 more

Stepping through the code I can see that the response is available on the http connection. An inputstream is built around that connection but after the call is complete the HTTP Connection is closed in the cleanup method.

When the body is first accessed, the stream is read but by then it's already closed, which gives the error below.

How can I retrieve a PDF using the call mediator with blocking="true"?

Details

WSO2 ESB 4.9.0

Added the following to the message builders section of axis2_blocking_client.xml

<messageBuilder contentType="application/pdf" class="org.wso2.carbon.relay.BinaryRelayBuilder" />
Community
  • 1
  • 1
Louis Zelus
  • 133
  • 13

1 Answers1

1

Binary-Relay uses these Formatters and Builders to relay messages---both well formed as well as ill-formed messages---through Apache Synapse without processing ( e.g. . XML Validation or processing) those messages. Binary-Relay includes a Builder and a Formatter. When a message is received, the Builder creates a fake SOAP message, attaches the content of the incoming SOAP message as a binary XML node, and sends it through the Apache Axis2 kernel, and when it is being sent out, the Binary-Relay Formatter expands the SOAP messages and writes the attached content to the output channel. Consequently, the message goes through Apache Synapse without processing its content, since the message is handled at the bytes level, even non-XML messages may go through Apache Synapse.

For more information please read.