Announcement Announcement Module
Collapse
No announcement yet.
Binary data lost on client when using MTOM Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Binary data lost on client when using MTOM

    I am currently evaluating spring-ws 1.5.9 for a webservice, that has to send medium sized binary attachments (pdfs and images).

    I wrote a sample service with an operation 'getPdfDocument', that should return a pdf document of about 160k. I tried to follow the mtom-sample and as far as I can see, I did everything that is suggested.

    As long, as I dont enable mtom, everything works fine. The binary data gets transmitted inline the message body and the client can access it. But when i enable mtom, the clientside datahandler does not contain any data.

    Ive enabled message tracing for server and client and the messages seem to be correct in both scenarios. With mtom disabled, the data is transmitted b64-encoded within the message body. With mtom enabled, i can see the binary data as attachment in a separate message part, both for client and server. From message tracing point of view, everything looks fine.

    The problem is, that with mtom enabled, the binary data is not available for my client. In both scenarios i use the following code to write the data to a file. Without mtom the file contains a valid pdf document, but with mtom enabled, the file has a size of 0 bytes. No exceptions or warnings are shown, everything looks fine except the fact, that the data is lost.

    Code:
    FileOutputStream fout = new FileOutputStream(...);
    DataHandler dataHandler = result.getDocumentData();  
    dataHandler.writeTo(fout);
    fout.flush();
    xsd definition for documentData is:

    Code:
    ...
    <xsd:sequence>
      <xsd:element name="documentData" 
          type="xsd:base64Binary"
          xmime:expectedContentTypes="application/octet-stream"/>
    </xsd:sequence>
    ...
    Im using SaajSoapMessageFactory and jaxb2 marshallers both on server and client and Im working with the libraries included in the spring-ws distribution. It seems that for some reason attachment data is not correctly bound to the datahandler, but after two days of trying and looking through various forums, I still dont have a clue whats wrong.

    The fallback strategy would be not using mtom, but given the attachments size and the fact, that our service will have heavy traffic, Im not happy with that approach. Any help would be highly appreciated.

    Andreas


    Edit: I forgot to mention that the service is running under WAS 7.0.0.5 with parent-last classloading and the following libs attached from the spring-ws distribution: activation-1.1.1, jaxb-api-2.1, jaxb-impl.2.1.5, mail-1.4.1, saaj-api-1.3, saaj-impl-1.3.2, sping-ws-1.5.9-all and the spring-2.5.6 libs.
    Last edited by andino; Oct 20th, 2010, 10:43 AM. Reason: additional information

  • #2
    pelase help

    hi could uou please let me know what you did further...Am seeing a similar issue here

    Originally posted by andino View Post
    I am currently evaluating spring-ws 1.5.9 for a webservice, that has to send medium sized binary attachments (pdfs and images).

    I wrote a sample service with an operation 'getPdfDocument', that should return a pdf document of about 160k. I tried to follow the mtom-sample and as far as I can see, I did everything that is suggested.

    As long, as I dont enable mtom, everything works fine. The binary data gets transmitted inline the message body and the client can access it. But when i enable mtom, the clientside datahandler does not contain any data.

    Ive enabled message tracing for server and client and the messages seem to be correct in both scenarios. With mtom disabled, the data is transmitted b64-encoded within the message body. With mtom enabled, i can see the binary data as attachment in a separate message part, both for client and server. From message tracing point of view, everything looks fine.

    The problem is, that with mtom enabled, the binary data is not available for my client. In both scenarios i use the following code to write the data to a file. Without mtom the file contains a valid pdf document, but with mtom enabled, the file has a size of 0 bytes. No exceptions or warnings are shown, everything looks fine except the fact, that the data is lost.

    Code:
    FileOutputStream fout = new FileOutputStream(...);
    DataHandler dataHandler = result.getDocumentData();  
    dataHandler.writeTo(fout);
    fout.flush();
    xsd definition for documentData is:

    Code:
    ...
    <xsd:sequence>
      <xsd:element name="documentData" 
          type="xsd:base64Binary"
          xmime:expectedContentTypes="application/octet-stream"/>
    </xsd:sequence>
    ...
    Im using SaajSoapMessageFactory and jaxb2 marshallers both on server and client and Im working with the libraries included in the spring-ws distribution. It seems that for some reason attachment data is not correctly bound to the datahandler, but after two days of trying and looking through various forums, I still dont have a clue whats wrong.

    The fallback strategy would be not using mtom, but given the attachments size and the fact, that our service will have heavy traffic, Im not happy with that approach. Any help would be highly appreciated.

    Andreas


    Edit: I forgot to mention that the service is running under WAS 7.0.0.5 with parent-last classloading and the following libs attached from the spring-ws distribution: activation-1.1.1, jaxb-api-2.1, jaxb-impl.2.1.5, mail-1.4.1, saaj-api-1.3, saaj-impl-1.3.2, sping-ws-1.5.9-all and the spring-2.5.6 libs.

    Comment


    • #3
      MTOM - no xop tag generateed in SOAP message

      Hi,

      I am using the simmilar configuration as yours except for WAS its tomcat.Were you able to find the solution to this problem?

      The issue which i face is that there is no xop tag generated in the SOAP request and the content is send in the message.I think the problem is with JAXB but still I am not sure.

      did anyone get a successful implementation of MTOM in spring 3.0 with JAXB 2?

      Comment


      • #4
        Did you check on this?

        @Yash2013,

        I did have it successfully configured now.

        Spring 3.0 with tomcat and MTOM really works great.

        But did you check whether the server is sending the data inline with the soap message or as an attachment?
        That might help you with understanding the absence of xop tag in the soap response.

        Thanks
        Priya

        Originally posted by Yash2013 View Post
        Hi,

        I am using the simmilar configuration as yours except for WAS its tomcat.Were you able to find the solution to this problem?

        The issue which i face is that there is no xop tag generated in the SOAP request and the content is send in the message.I think the problem is with JAXB but still I am not sure.

        did anyone get a successful implementation of MTOM in spring 3.0 with JAXB 2?

        Comment


        • #5
          Hi,

          Yes,I checked it in SOAPUI the response xml looks like this

          Code:
                   <ns3:Object>
                      <ns2:Mimetype>application/pdf</ns2:Mimetype>
                   <ns2:Content>B3TFSn2EDpPGaYooZ9SWdcbevZUiJA2JLVlUpKoj9JutU73t3E0Y3OTuu2MjlppLYJpZZC+TVB50oGbOsnvcf9yuhZMcsmER5plRBcbZqmuMJUEX+T8XaEo+0+dt33PvvksW3t+Z3fnp842G</ns2:Content>
                   </ns3:Object>
          Pasting only the tag which contains the document content.I have used the following settings to ensure MTOM works
          1.In xsd the the Tag for Content is like this

          Code:
          <xs:element name="Content" type="xs:base64Binary"  xmime:expectedContentTypes="application/octet-stream" minOccurs="0"/>

          2.In my config file the settings are --

          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
          	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          	xmlns:context="http://www.springframework.org/schema/context"
          	xmlns:sws="http://www.springframework.org/schema/web-services"
          	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
          	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 
          	http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
          	http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd">
          
          <!-- This is important tag.It enables annotation and hence facilitates endpoint mappings  -->
          <sws:annotation-driven />
              
          <bean id="defaultMethodEndpointAdapter" class="org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter">
            <property name="methodArgumentResolvers">
             <list>
              <ref bean="marshallingPayloadMethodProcessor"/>
             </list> 
            </property>
            <property name="methodReturnValueHandlers">
             <list>
              <ref bean="marshallingPayloadMethodProcessor"/>
             </list>
            </property>
           </bean>    
           
           <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping"/>
           
           <bean id="marshallingPayloadMethodProcessor" class="org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor">
            <constructor-arg ref="jaxbmarshaller"/>
           </bean>
          
          <bean id="soapMessageFactory" class="javax.xml.soap.MessageFactory" factory-method="newInstance" />
          <bean id="saajMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
                  <constructor-arg ref="soapMessageFactory" />
          </bean>
              
            <bean id="jaxbmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
            	 <property name="packagesToScan">
                        <list>
                        	<value>com.mydoc.project.schemas</value>
                        	<value>com.mydoc.project.recievedoc</value>
            	    </list>
                    </property>
                    <property name="mtomEnabled" value="true" />
                </bean>
             
            	 <bean id="recieveDocEndpoint" class="com.mydoc.project.recievedoc.RecieveDocEndPoint">
            	 	<ref bean="recieveDocService"/>
             		<property name="validateInput" value="false"/>
             		<property name="validateOutput" value="false"/>		
             	</bean>
             	
             	<bean id="recieveDocService" class="com.mydoc.project.recievedoc.RecieveDocImpl"/>
             	
             	
             	<bean id="recieveDoc" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
             		<property name="schema">
                  	<bean class="org.springframework.xml.xsd.SimpleXsdSchema">
                  		<property name="xsd" value="/WEB-INF/classes/services/recievedoc/recievedoc.xsd"/>
                  	</bean>	
                  	</property>
             		<property name="portTypeName" value="recieveDoc"/>
             		<property name="locationUri" value="http://localhost:8080/recievedoc/webservice"/>				
          	</bean>
             </beans>
          3.In my code ,I am using data handlar to set the content as following
          Code:
          javax.activation.DataHandler dataHandler = new javax.activation.DataHandler(new FileDataSource("test.pdf"));
          System.out.println("Content Type " + dataHandler.getContentType());
          obj.setContent(dataHandler);

          This is as per the specifications,i am not sure where its going wrong either the JAXB is not marshalling it as attachment or there is some other way to set the content in JAXb object.Can you please suggest if your configuration is different.

          Comment


          • #6
            @Yash2013

            You might want to have a look at the following

            I see that the pdf file is coming inline in the SOAP UI response that you have pasted. It does not seem to be an attachment in the response at all. Seems to come as an inline pdf in the SOAP response that is coming. This might be the reason I am thinking that you are not able to get the pdf that is coming through.

            If it comes as inline pdf in the SOAP response, I have literally seen that a SaajFactory with mtom=false really works and gets the inline pdf as required.

            If the pdf comes as attachment, then you might want to have AxiomFactory with mtom=true and this will catch the pdf attachment in SOAP response.

            I have tried both and it works. Can you please let me know what happens? I shall share my config if at all that would help too

            Originally posted by Yash2013 View Post
            Hi,

            Yes,I checked it in SOAPUI the response xml looks like this

            Code:
                     <ns3:Object>
                        <ns2:Mimetype>application/pdf</ns2:Mimetype>
                     <ns2:Content>B3TFSn2EDpPGaYooZ9SWdcbevZUiJA2JLVlUpKoj9JutU73t3E0Y3OTuu2MjlppLYJpZZC+TVB50oGbOsnvcf9yuhZMcsmER5plRBcbZqmuMJUEX+T8XaEo+0+dt33PvvksW3t+Z3fnp842G</ns2:Content>
                     </ns3:Object>
            Pasting only the tag which contains the document content.I have used the following settings to ensure MTOM works
            1.In xsd the the Tag for Content is like this

            Code:
            <xs:element name="Content" type="xs:base64Binary"  xmime:expectedContentTypes="application/octet-stream" minOccurs="0"/>

            2.In my config file the settings are --

            Code:
            <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
            	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            	xmlns:context="http://www.springframework.org/schema/context"
            	xmlns:sws="http://www.springframework.org/schema/web-services"
            	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
            	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 
            	http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
            	http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd">
            
            <!-- This is important tag.It enables annotation and hence facilitates endpoint mappings  -->
            <sws:annotation-driven />
                
            <bean id="defaultMethodEndpointAdapter" class="org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter">
              <property name="methodArgumentResolvers">
               <list>
                <ref bean="marshallingPayloadMethodProcessor"/>
               </list> 
              </property>
              <property name="methodReturnValueHandlers">
               <list>
                <ref bean="marshallingPayloadMethodProcessor"/>
               </list>
              </property>
             </bean>    
             
             <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping"/>
             
             <bean id="marshallingPayloadMethodProcessor" class="org.springframework.ws.server.endpoint.adapter.method.MarshallingPayloadMethodProcessor">
              <constructor-arg ref="jaxbmarshaller"/>
             </bean>
            
            <bean id="soapMessageFactory" class="javax.xml.soap.MessageFactory" factory-method="newInstance" />
            <bean id="saajMessageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
                    <constructor-arg ref="soapMessageFactory" />
            </bean>
                
              <bean id="jaxbmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
              	 <property name="packagesToScan">
                          <list>
                          	<value>com.mydoc.project.schemas</value>
                          	<value>com.mydoc.project.recievedoc</value>
              	    </list>
                      </property>
                      <property name="mtomEnabled" value="true" />
                  </bean>
               
              	 <bean id="recieveDocEndpoint" class="com.mydoc.project.recievedoc.RecieveDocEndPoint">
              	 	<ref bean="recieveDocService"/>
               		<property name="validateInput" value="false"/>
               		<property name="validateOutput" value="false"/>		
               	</bean>
               	
               	<bean id="recieveDocService" class="com.mydoc.project.recievedoc.RecieveDocImpl"/>
               	
               	
               	<bean id="recieveDoc" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
               		<property name="schema">
                    	<bean class="org.springframework.xml.xsd.SimpleXsdSchema">
                    		<property name="xsd" value="/WEB-INF/classes/services/recievedoc/recievedoc.xsd"/>
                    	</bean>	
                    	</property>
               		<property name="portTypeName" value="recieveDoc"/>
               		<property name="locationUri" value="http://localhost:8080/recievedoc/webservice"/>				
            	</bean>
               </beans>
            3.In my code ,I am using data handlar to set the content as following
            Code:
            javax.activation.DataHandler dataHandler = new javax.activation.DataHandler(new FileDataSource("test.pdf"));
            System.out.println("Content Type " + dataHandler.getContentType());
            obj.setContent(dataHandler);

            This is as per the specifications,i am not sure where its going wrong either the JAXB is not marshalling it as attachment or there is some other way to set the content in JAXb object.Can you please suggest if your configuration is different.

            Comment


            • #7
              Thanks for replying.

              I have tried with SaajFactory option and yes the file comes as attachment since its put explicitly as attachment in code.That is in the message context

              But with this options ,my understanding is that this is not MTOM .This is SOAP with attachment.What i want to achieve is to get the response as MTOM attachment.Also,the response soap message will not have a xop tag but usual content tag with the value set in it.

              I can try with Axiom but i was wondering if that will also result in providing the file as attachment rather than MTOM attachment.

              I am able to get the PDF attachment at client and stream it into the file.Sorry if I posted in wrong thread but my problem is not data loss but MTOM feature not working at all for me.Since its working for you ,may be you can validate if I have done something wrong in this.Thanks once again.

              Comment


              • #8
                Think you are close.

                @Yash2013,

                Ok. I reread this thread. This is what I understand

                1. with mtom enabled, you had the Saajfactory in your code - Is it? If this is the case, you might surely want to change the facotry to ASIOM as shown below in the code snipper.
                2. Both the server and the client - you are writing and you are using the client to test the server.

                In my case
                1.I was having a SOAP client. The server was sending data as SOAP attachment NOT INLINE ATTACHMENT FILE with MTOM enabled.
                2. Intiially,when I had my client with MTOM = true and a SAAJMessage factory, I was able to see that the client was able to receive the file only when it was an INLINE MESSAGE in the soap response from server. If it was aN MTOM ENABLED ATTCHMENT from the SOAP server, the file at the client reported 0 bytes.
                3. In the above scenario, I went and changed the message factory in the client to AXIOM factory with MTOM =true and this did the magic. The client was able to receive the MTOM ATTACHMENT from server immediately - the following code snippet was at the client then.

                As far as I know, Saaj factory does not support MTOM attachments properly if at all. AxiomFactory is the trick for MTOM enabled attachment.

                Please let me know what you find

                Code:
                <bean id="messageFactory"
                		class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
                		<property name="attachmentCaching" value="true" />
                		<property name="payloadCaching" value="true" />
                		<property name="attachmentCacheThreshold" value="1024" />
                		<property name="attachmentCacheDir" value="directory name" />
                	</bean>
                
                <!-- by default, id="webServiceTemplate will make use of the soap SAAJMessage factory.  -->
                	<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
                		<constructor-arg ref="messageFactory" />
                		<property name="marshaller" ref="marshaller" />
                		<property name="unmarshaller" ref="marshaller" />
                		<property name="defaultUri"
                			value="url here" />
                	</bean>
                
                	<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
                		<property name="contextPath" value="org.ets.ipackager.webservice" />
                		<property name="mtomEnabled" value="true" />
                
                	</bean>
                
                client handler extends extends WebServiceGatewaySupport
                
                In client handler, I used the following code to catch the attachment (mtom enabled attaachment file - no inline attachment in my case was sent)
                 responseObject = getWebServiceTemplate()
                                    .marshalSendAndReceive(requestObject)
                Originally posted by priyavenkat View Post
                @Yash2013

                You might want to have a look at the following

                I see that the pdf file is coming inline in the SOAP UI response that you have pasted. It does not seem to be an attachment in the response at all. Seems to come as an inline pdf in the SOAP response that is coming. This might be the reason I am thinking that you are not able to get the pdf that is coming through.

                If it comes as inline pdf in the SOAP response, I have literally seen that a SaajFactory with mtom=false really works and gets the inline pdf as required.

                If the pdf comes as attachment, then you might want to have AxiomFactory with mtom=true and this will catch the pdf attachment in SOAP response.

                I have tried both and it works. Can you please let me know what happens? I shall share my config if at all that would help too

                Comment


                • #9
                  Thanks for the information.

                  1.Yes I do have SaajFactory with MTOM enabled in Server.And I am using the same to send the attachment to the client..So this is SOAP with Attachment.I am able to get the attachment at client ,stream it and save it and open it and all works.

                  The response SOAP message contains no xop tag and document is sent as a usual SOAP attachment.And this is my core and only problem. I am not worried about the client implementation and soapui does the job of client for me very well.

                  What i want is, to send the attachment from Server to Client (any) as MTOM attachment i.e the response soap message should contain the xop tag with reference to MIME attachment in the SOAP response message.

                  I believe the settings you have mentioned here are for client and not for server side settings.Though it might be useful for me later but if you have idea on how to send the MTOM attachment from server to client (Not SOAP attachment) ,please let me know.Thank you.

                  Comment


                  • #10
                    try this

                    ok. Here is the link where they use the SaajMessageFactory itself for MTOM

                    http://stackoverflow.com/questions/1...llo-world-test

                    http://blog.hpxn.net/2012/06/

                    Let me know if it works or not.


                    Originally posted by Yash2013 View Post
                    Thanks for the information.

                    1.Yes I do have SaajFactory with MTOM enabled in Server.And I am using the same to send the attachment to the client..So this is SOAP with Attachment.I am able to get the attachment at client ,stream it and save it and open it and all works.

                    The response SOAP message contains no xop tag and document is sent as a usual SOAP attachment.And this is my core and only problem. I am not worried about the client implementation and soapui does the job of client for me very well.

                    What i want is, to send the attachment from Server to Client (any) as MTOM attachment i.e the response soap message should contain the xop tag with reference to MIME attachment in the SOAP response message.

                    I believe the settings you have mentioned here are for client and not for server side settings.Though it might be useful for me later but if you have idea on how to send the MTOM attachment from server to client (Not SOAP attachment) ,please let me know.Thank you.

                    Comment

                    Working...
                    X