3

I am trying to respond PDFcontent from wso2 esb rest api and want to view in browser. I have enabled the messageFormatter and messageBuilder for application/pdf as well. But when I invoke my api from browser I am getting exception below in wso2 esb.

axis2.xml:

<messageBuilder contentType="application/pdf" class="org.wso2.carbon.relay.BinaryRelayBuilder"/>

<messageFormatter contentType="application/pdf" class="org.wso2.carbon.relay.ExpandingMessageFormatter"/>

Exception:

ERROR {org.apache.synapse.transport.passthru.PassThroughHttpSender} -  Failed to submit the response {org.apache.synapse.transport.passthru.PassThroughHttpSender}
java.lang.RuntimeException: ContentID is null
    at org.apache.axiom.om.impl.llom.OMTextImpl.getDataHandler(OMTextImpl.java:381)
    at org.wso2.carbon.relay.ExpandingMessageFormatter.findAndWrite2OutputStream(ExpandingMessageFormatter.java:179)
    at org.wso2.carbon.relay.ExpandingMessageFormatter.writeTo(ExpandingMessageFormatter.java:97)
    at org.apache.synapse.transport.passthru.PassThroughHttpSender.submitResponse(PassThroughHttpSender.java:573)
    at org.apache.synapse.transport.passthru.PassThroughHttpSender.invoke(PassThroughHttpSender.java:264)
    at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:442)
    at org.apache.synapse.core.axis2.Axis2Sender.sendBack(Axis2Sender.java:230)
    at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.send(Axis2SynapseEnvironment.java:531)
    at org.apache.synapse.mediators.builtin.SendMediator.mediate(SendMediator.java:118)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:97)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:59)
    at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:158)
    at org.apache.synapse.rest.Resource.process(Resource.java:343)
    at org.apache.synapse.rest.API.process(API.java:338)
    at org.apache.synapse.rest.RESTRequestHandler.apiProcess(RESTRequestHandler.java:123)
    at org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:101)
    at org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:56)
    at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:304)
    at org.apache.synapse.mediators.builtin.LoopBackMediator.mediate(LoopBackMediator.java:63)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:97)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:59)
    at org.apache.synapse.config.xml.AnonymousListMediator.mediate(AnonymousListMediator.java:37)
    at org.apache.synapse.config.xml.SwitchCase.mediate(SwitchCase.java:69)
    at org.apache.synapse.mediators.filters.SwitchMediator.mediate(SwitchMediator.java:148)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:97)
    at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:260)
    at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.mediateFromContinuationStateStack(Axis2SynapseEnvironment.java:775)
    at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:282)
    at org.apache.synapse.core.axis2.SynapseCallbackReceiver.handleMessage(SynapseCallbackReceiver.java:554)
    at org.apache.synapse.core.axis2.SynapseCallbackReceiver.receive(SynapseCallbackReceiver.java:188)
    at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
    at org.apache.synapse.transport.passthru.ClientWorker.run(ClientWorker.java:262)
    at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Unexpected error sending message back {org.apache.synapse.core.axis2.Axis2Sender}
org.apache.axis2.AxisFault: Failed to submit the response
    at org.apache.synapse.transport.passthru.PassThroughHttpSender.handleException(PassThroughHttpSender.java:632)
    at org.apache.synapse.transport.passthru.PassThroughHttpSender.invoke(PassThroughHttpSender.java:266)
    at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:442)
    at org.apache.synapse.core.axis2.Axis2Sender.sendBack(Axis2Sender.java:230)
    at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.send(Axis2SynapseEnvironment.java:531)
    at org.apache.synapse.mediators.builtin.SendMediator.mediate(SendMediator.java:118)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:97)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:59)
    at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:158)
    at org.apache.synapse.rest.Resource.process(Resource.java:343)
    at org.apache.synapse.rest.API.process(API.java:338)
    at org.apache.synapse.rest.RESTRequestHandler.apiProcess(RESTRequestHandler.java:123)
    at org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:101)
    at org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:56)
    at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:304)
    at org.apache.synapse.mediators.builtin.LoopBackMediator.mediate(LoopBackMediator.java:63)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:97)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:59)
    at org.apache.synapse.config.xml.AnonymousListMediator.mediate(AnonymousListMediator.java:37)
    at org.apache.synapse.config.xml.SwitchCase.mediate(SwitchCase.java:69)
    at org.apache.synapse.mediators.filters.SwitchMediator.mediate(SwitchMediator.java:148)
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:97)
    at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:260)
    at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.mediateFromContinuationStateStack(Axis2SynapseEnvironment.java:775)
    at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:282)
    at org.apache.synapse.core.axis2.SynapseCallbackReceiver.handleMessage(SynapseCallbackReceiver.java:554)
    at org.apache.synapse.core.axis2.SynapseCallbackReceiver.receive(SynapseCallbackReceiver.java:188)
    at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
    at org.apache.synapse.transport.passthru.ClientWorker.run(ClientWorker.java:262)
    at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

API Content:

<payloadFactory media-type="xml">
                  <format>
                     <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
                        <soapenv:Body>
                           <ns:binary xmlns:ns="http://ws.apache.org/commons/ns/payload">$1</ns:binary>
                        </soapenv:Body>
                     </soapenv:Envelope>
                  </format>
                  <args>
                     <arg evaluator="xml" expression="//*[local-name()='Binary']/text()"/>
                  </args>
               </payloadFactory>
               <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
               <property name="ContentType" value="application/pdf" scope="axis2" type="STRING"/>
               <property name="messageType" value="application/pdf" scope="axis2" type="STRING"/>
               <respond/>

I have tried to convert binary to pdf using online tool and it works fine.

Community
  • 1
  • 1
Waqas Ali Razzaq
  • 659
  • 1
  • 5
  • 30
  • What actually are trying to achive? What is incoming message ? – simar Jun 19 '17 at 07:20
  • What scenario is? You want esb service to receive post http request with pdf file and respond with base64 encode content in soap response? – simar Jun 19 '17 at 09:10
  • Hi simar thanks for reply. My scenario was to save pdf file in db as binary and retrieve the pdf file again in browser as readable file. – Waqas Ali Razzaq Jun 19 '17 at 09:12
  • I did successfully load pdf file to ESB, but I can't find a way to send it back – simar Jun 19 '17 at 09:18
  • I am also stuck at same point.. – Waqas Ali Razzaq Jun 19 '17 at 09:22
  • Very weird behavior of ESB server. One api logs incoming messages even there is no log mediator. Second api (different url but copy first) doesn't log anything despite 3 logging mediators. Restart doesn't help. – simar Jun 19 '17 at 10:47

1 Answers1

3

Find out eventually how to do it.

I use postgres in my experiments. Let's create table which will store files content. It is pretty simple. Anyway there are 2 cases. File might be stored as base64 or blob (bytea in postgres). I implemented case when file is stored as string in base64 format in database.

drop table if exists pdf_files ;
create table pdf_files(
     id serial primary key, 
     file_name text, 
     pdf_base64 text, 
     pdf_binary bytea
 );

Insert data file content into table in base64 format. File in base64 format can be converted online here or any other online tool http://www.motobit.com/util/base64-decoder-encoder.asp

insert into pdf_files(file_name, pdf_base64)
values('title.pdf',   'JVBERi0x.....................NjMKJSVFT0YK');

Now lets get binary field filled

update pdf_files set pdf_binary = decode(pdf_base64, 'base64');

I got this in database:

Table content

First i tried to implement soap service which will respond pdf. There is service I made:

<proxy xmlns="http://ws.apache.org/ns/synapse" name="Sample" startOnLoad="true" statistics="disable" trace="disable" transports="http,https">
    <target>
        <inSequence>
            <dblookup>
                <connection>
                    <pool>
                        <dsName>pgConn</dsName>
                    </pool>
                </connection>
                <statement>
                    <sql>select pdf_base64 from pdf_files where id = ?</sql>
                    <parameter xmlns:nb="http://mru" expression="//nb:id" type="INTEGER"/>
                    <result column="pdf_base64" name="pdf_base64"/>
                </statement>
            </dblookup>
            <payloadFactory media-type="xml">
                <format>
                    <ns:binary xmlns:ns="http://ws.apache.org/commons/ns/payload">$1</ns:binary>
                </format>
                <args>
                    <arg evaluator="xml" expression="get-property('pdf_base64')"/>
                </args>
            </payloadFactory>
            <loopback/>
        </inSequence>
        <outSequence>
            <script language="js">
            var binaryNode = mc.getEnvelope().getBody().getFirstElement().getFirstOMChild();  
            binaryNode.setBinary(true);
            </script>
            <property name="messageType" scope="axis2" type="STRING" value="application/pdf"/>
            <respond/>
        </outSequence>
    </target>
    <description/>
</proxy>

It accepts request with tag id which is refers to table id(primary key)

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:nb="http://mru">
    <soap:Body>
        <nb:id>1</nb:id>
    </soap:Body>
</soap:Envelope>

Let's make request using curl (I assume request is saved in file request.xml)

curl -v -X POST -H "Content-Type:text/xml" -d @./request.xml http://localhost:8280/services/Sample.SampleHttpSoap12Endpoint > title1.pdf

This what i got

Curl request to soap service

As you see after I can open pdf file returned by service.

Now same thing for API. It is actually easy and almost the same. Only need to configure url-template to catch parameter id for sql query.

 <api xmlns="http://ws.apache.org/ns/synapse" name="GetPdf" context="/pdf">
    <resource methods="GET" uri-template="/id/{fileId}">
      <inSequence>
         <property name="ID" expression="get-property('uri.var.fileId')"/>
         <dblookup>
            <connection><pool><dsName>pgConn</dsName></pool></connection>
            <statement>
               <sql>select pdf_base64 from pdf_files where id = ?</sql>
               <parameter expression="get-property('ID')" type="INTEGER"/>
               <result name="pdf_base64" column="pdf_base64"/>
            </statement>
         </dblookup>
         <payloadFactory media-type="xml">
            <format>
               <ns:binary xmlns:ns="http://ws.apache.org/commons/ns/payload">$1</ns:binary>
            </format>
            <args>
               <arg evaluator="xml" expression="get-property('pdf_base64')"/>
            </args>
         </payloadFactory>
         <loopback/>
      </inSequence>
      <outSequence>
         <script language="js">
             var binaryNode = mc.getEnvelope().getBody().getFirstElement().getFirstOMChild();     
             binaryNode.setBinary(true);
         </script>
         <property name="messageType" value="application/pdf" scope="axis2" type="STRING"/>
         <respond/>
      </outSequence>
   </resource>
</api>

This api will return PDF file using proper Content-Type header so browser will understand it.

Picture is underneath. Browser properly identify content, via content type header, and use builtin pdf renderer to display pdf file served by wsoesb server.

PDF File opened in browser

simar
  • 1,782
  • 3
  • 16
  • 33