3

Scenario:

I have a vfs-Proxy monitoring a folder for files with the extention .pdf. The Proxy parses the file-content in base64binary into

<axis2ns#:binary xmlns:axis2ns#="http://ws.apache.org/commons/ns/payload">JVBERi0xLjMKJfbk/N8K...</axis2ns#:binary>

# is a incremental number and as far as i know, i don't have an influence on this mater. With a payloadFactory i reformat the payload to be surrounded by

<datatype:pdf xmlns:datatype="http://mynamespace.org/payload"> instead.

Problem:

The resulting file looks like this:

--MIMEBoundary_e1f5b2321e28e0a638b52a178d5c7ee40c2f3ae08cd43818
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <0.f1f5b2321e28e0a638b52a178d5c7ee40c2f3ae08cd43818@apache.org>
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<datatype:pdf xmlns:datatype="http://mynamespace.org/payload">
JVBERi0xLjMKJfbk/N8K...
</datatype:pdf>
</soapenv:Body>
</soapenv:Envelope>
--MIMEBoundary_e1f5b2321e28e0a638b52a178d5c7ee40c2f3ae08cd43818--

instead of an actual pdf-document. What's necessary to change that? I'm pretty sure it has so be something with the content-types or the payloadFactory. Is there a way to specify which tags are treated as payload? I have already tried to a few different types, settings and searched but coudn't find a solution. If i interpret the resulting message correct mtom isn't working as it is supposed to. Shouldn't there be a

<xop:Include href="...">

inside the resulting message instead of the inline base64binary?

Simple Code for reproduction:

    <?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="VFSVFS"
       transports="vfs"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
     <property name="OUT_ONLY" value="true"/>
     <property name="enableMTOM" value="true" scope="axis2" type="STRING"/>
     <property name="enableSWA" value="false" scope="axis2" type="STRING"/>
     <property name="transportNonBlocking"
               value="true"
               scope="axis2"
               action="remove"/>
     <payloadFactory media-type="xml">
        <format>
           <datatype:pdf xmlns:datatype="http://mynamespace.org/payload">
              $1
           </datatype:pdf>
        </format>
        <args>
           <arg evaluator="xml" expression="$body/*[1]"/>
        </args>
     </payloadFactory>
     <property name="messageType" value="application/octet-stream" scope="axis2"/>
     <property name="transport.vfs.ReplyFileName" expression="fn:concat(fn:substring-after(get-property('MessageID'), 'urn:uuid:'), 'abc.pdf')" scope="transport"/>
         <property name="transport.vfs.Streaming" value="true" scope="transport" type="STRING"/>
     <send>
        <endpoint xmlns="http://ws.apache.org/ns/synapse" name="FileOut_VFS">
           <address uri="vfs:file:///home/user/Development/data/testfiles/init/out" optimize="mtom" />
        </endpoint>
     </send>
     <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
      </inSequence>
   </target>
   <parameter name="transport.vfs.ActionAfterProcess">DELETE</parameter>
   <parameter name="transport.PollInterval">5</parameter>
   <parameter name="transport.vfs.FileURI">file:///home/user/Development/data/testfiles/init/in</parameter>
   <parameter name="transport.vfs.MoveAfterFailure">file:///home/user/Development/data/failure</parameter>
   <parameter name="transport.vfs.Locking">false</parameter>
   <parameter name="transport.vfs.FileNamePattern">.*.pdf</parameter>
   <parameter name="transport.vfs.ContentType">application/octet-stream</parameter>
   <parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
   <parameter name="transport.vfs.FailedRecordsFileDestination">file:///home/user/Development/data/failure</parameter>
   <description/>
</proxy>

The code above is just for the purpose of simplification. The actual project performs those key operations:

  1. read-in a pdf

  2. aggregate the soap-message with additional information from various sources

  3. manipulate the pdf-content with a custom mediator

  4. write-out the new pdf

For the purpose of aggregation and manipulation i want to reformat the initial body with the payloadFactory. But as soon as I change a thing, the message no longer arrives in a fitting format. This applies even in the simple code above.

Here a few examples of tried out combination's and their results:

<ns:binary xmlns:ns="http://ws.apache.org/commons/ns/payload">$1</ns:binary> 
 WITH OR WITHOUT
<property name="ContentType" value="application/octet-stream" scope="axis2"/> 
 RESULTS IN
 INFO - AxisEngine [MessageContext: logID=6143bc348d4852f3ffa02dba72391ab0860fe7c27625f167] ContentID is null
 [2015-10-16 08:19:40,923] ERROR - AsyncCallback ContentID is null
java.lang.RuntimeException: ContentID is null
 EVEN WITH <property name="enableMTOM" value="false" scope="axis2" type="STRING"/>


 <ns:text xmlns:ns="http://ws.apache.org/commons/ns/payload">$1</ns:text> 
 WITH OR WITHOUT
 <property name="ContentType" value="application/octet-stream" scope="axis2"/> RESULTS IN 
 File with base64binary as plain/text in it -> no functioning pdf.
Community
  • 1
  • 1
  • I'm struggling with almost the same problem. The PDF data comes in as part of a JSON. The value is a base64 encoded string. I must write it down to a file that is a actual binary PDF. And I end up with the same "ContentID is null" error. Did you find any solution on this ? – Pontus Ullgren Nov 11 '15 at 20:24
  • Sorry for my late reply! So far my only solution is to write a own mediator... – Lukas Schober Mar 04 '16 at 13:04
  • Thanks for the reply. I also ended up with the same solution. – Pontus Ullgren Mar 05 '16 at 14:18

3 Answers3

1

I guess, you should change the format to the following so it will be treated as text.

<format>
           <ns:text xmlns:ns="http://ws.apache.org/commons/ns/payload">$1</ns:text>
        </format>

Hope that helps. I guess you won't be able to open the file because it will have the wrong encoding.

Regards Martin

Martin Hald
  • 676
  • 4
  • 11
  • Thank you for your reply! Sadly this results in files with just the base64binary-string as plain/text in it. I have added some combination's above. – Lukas Schober Oct 16 '15 at 06:52
0

Not sure if I get it right. If I look at the proxy it seems that you'd like to read a pdf and write it to some other location. So you just could use the following to write the file.

<send>           
  <endpoint>
    <address uri="vfs:file:///home/user/Development/data/testfiles/init/out"/>
  </endpoint>
</send>

Inside the ESB every message/file that arrives will be converted to a soap message.

Regards Martin

Elias Mårtenson
  • 3,820
  • 23
  • 32
Martin Hald
  • 676
  • 4
  • 11
  • Thank you for your reply :) sadly this is not what I'm looking for. The code above is just for the purpose of simplification. The actual project performs those key operations: 1. read-in a pdf 2. aggregate the soap-message with additional information from various sources 3. manipulate the pdf-content with a custom mediator 4. write-out the new pdf For the purpose of aggregation and manipulation i want to reformat the initial body with the payloadFactory. But as soon as I change a thing, the message no longer arrives in a fitting format. This applies even in the simple code above. – Lukas Schober Oct 15 '15 at 10:08
0

From this post on the ws-commons-dev mailing list finally send me in the right direction.

The problem is that to make this work the OMElement object has be have a Content ID OR have the flag isBinary set to true.
This is a attribute on the OMTextImpl and from what I can tell this has to be done on the object and can not be set from the XML payload. So in the end I had to add a script mediator to do this.

<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="$body/attachments/content"/>
  </args>
</payloadFactory>
<script language="js">
<![CDATA[
   var binaryNode =       
      mc.getEnvelope().getBody().getFirstElement().getFirstOMChild();  
   binaryNode.setBinary(true);
]]>
</script>

In the example above the base64 data comes in as part of the incoming message.

Pontus Ullgren
  • 697
  • 6
  • 24