Reputation: 669
I am trying to respond PDF
content 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.
Upvotes: 3
Views: 2776
Reputation: 1832
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:
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
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.
Upvotes: 4