Axis2
  1. Axis2
  2. AXIS2-4909

Simple MTOM web service no longer works due to missing closing MIME boundary.

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.5.2, 1.5.3
    • Fix Version/s: 1.5.4
    • Component/s: transports
    • Labels:
      None

      Description

      1) Use wsdl2java to generate service stubs from a simple wsdl (A), modify axis2.xml to turn MTOM on "<parameter name="enableMTOM">true</parameter>".
      2) In generated WebServiceSkeleton change getBinaryData to return some data (B).
      3) Use maven/pom file (C) to build a war, deploy war to tomcat.
      4) Generate a simple client to call the service (D).

      You will get the following exception on the client
      java.io.IOException: End of Stream, but boundary not found
      at org.apache.axiom.attachments.BoundaryPushbackInputStream.read(BoundaryPushbackInputStream.java:258)
      at org.apache.axiom.attachments.BoundaryPushbackInputStream.read(BoundaryPushbackInputStream.java:141)
      at org.apache.axiom.attachments.MIMEBodyPartInputStream.read(MIMEBodyPartInputStream.java:101)
      at org.apache.axiom.attachments.impl.PartFactory.readHeaders(PartFactory.java:192)
      at org.apache.axiom.attachments.impl.PartFactory.createPart(PartFactory.java:95)
      ... 15 more

      Because there is no closing MIME boundary in the server generated SOAP (E). This does not occur with axis2 version 1.5.1.

      (A)
      <?xml version="1.0" encoding="UTF-8"?>

      <wsdl:definitions xmlns:tns="http://webservice.mtom"
      xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
      xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
      xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
      xmlns:xmime="http://www.w3.org/2005/05/xmlmime"
      xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
      xmlns="http://schemas.xmlsoap.org/wsdl/"
      targetNamespace="http://webservice.mtom">
      <wsdl:types>
      <xsd:schema xmlns="http://schemas.xmlsoap.org/wsdl/"
      attributeFormDefault="qualified"
      elementFormDefault="qualified"
      targetNamespace="http://webservice.mtom">
      <xsd:element name="BinaryData">
      <xsd:complexType>
      <xsd:sequence>
      <xsd:element minOccurs="0" name="return" type="xsd:base64Binary" />
      </xsd:sequence>
      </xsd:complexType>
      </xsd:element>
      </xsd:schema>
      </wsdl:types>
      <wsdl:message name="getBinaryDataResponse">
      <wsdl:part name="parameters" element="tns:BinaryData">
      </wsdl:part>
      </wsdl:message>
      <wsdl:message name="getBinaryDataRequest">
      </wsdl:message>
      <wsdl:portType name="WebServicePortType">
      <wsdl:operation name="getBinaryData">
      <wsdl:input message="tns:getBinaryDataRequest"
      wsaw:Action="tns:getBinaryData">
      </wsdl:input>
      <wsdl:output message="tns:getBinaryDataResponse"
      wsaw:Action="tns:getBinaryDataResponse">
      </wsdl:output>
      </wsdl:operation>
      </wsdl:portType>
      <wsdl:binding name="WebServiceSoap12Binding"
      type="tns:WebServicePortType">
      <soap12:binding style="document"
      transport="http://schemas.xmlsoap.org/soap/http" />
      <wsdl:operation name="getBinaryData">
      <soap12:operation soapAction="tns:getBinaryData"
      style="document" />
      <wsdl:input>
      <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output>
      <soap12:body use="literal" />
      </wsdl:output>
      </wsdl:operation>
      </wsdl:binding>
      <wsdl:service name="WebService">
      <wsdl:port name="WebServiceHttpSoap12Endpoint"
      binding="tns:WebServiceSoap12Binding">
      <soap12:address
      location="http://localhost:8080/WebService/services/WebService.WebServiceHttpSoap12Endpoint/" />
      </wsdl:port>
      </wsdl:service>
      </wsdl:definitions>

      (B)
      public mtom.webservice.BinaryData getBinaryData(

      ) {
      BinaryData param = new BinaryData();
      DataHandler dh = new DataHandler(new DataSource() {
      private byte[] bytes = new byte[]

      { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

      ;

      @Override
      public String getContentType()

      { return "application/binary"; }

      @Override
      public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(bytes); }

      @Override
      public String getName() { return "application/binary"; }

      @Override
      public OutputStream getOutputStream() throws IOException

      { return null; }

      });
      param.set_return(dh);
      return param;
      }

      (C)
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>org.stern</groupId>
      <artifactId>WebService</artifactId>
      <packaging>war</packaging>
      <version>0.1-SNAPSHOT</version>
      <build>
      <plugins>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
      <source>1.6</source>
      <target>1.6</target>
      </configuration>
      </plugin>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-war-plugin</artifactId>
      <version>2.0.2</version>
      <configuration>
      <warName>WebService</warName>
      <warSourceDirectory>src/main/webapp</warSourceDirectory>
      <warSourceExcludes>*/.log</warSourceExcludes>
      </configuration>
      </plugin>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
      <execution>
      <id>copy-dependencies</id>
      <phase>package</phase>
      <goals>
      <goal>copy-dependencies</goal>
      </goals>
      <configuration>
      <outputDirectory>src/main/webapp/WEB-INF/lib</outputDirectory>
      </configuration>
      </execution>
      </executions>
      </plugin>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-resources-plugin</artifactId>
      <configuration>
      <outputDirectory>src/main/webapp/WEB-INF/classes</outputDirectory>
      </configuration>
      </plugin>
      </plugins>
      </build>
      <dependencies>
      <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.7</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>javax.activation</groupId>
      <artifactId>activation</artifactId>
      <version>1.1</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.ws.commons.axiom</groupId>
      <artifactId>axiom-api</artifactId>
      <version>1.2.10</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.ws.commons.axiom</groupId>
      <artifactId>axiom-dom</artifactId>
      <version>1.2.10</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.ws.commons.axiom</groupId>
      <artifactId>axiom-impl</artifactId>
      <version>1.2.10</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-adb</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-adb-codegen</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-ant-plugin</artifactId>
      <version>1.5.3</version>
      <type>maven-plugin</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-clustering</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-codegen</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-corba</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-fastinfoset</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-java2wsdl</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-jaxbri</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-jibx</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-json</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-kernel</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-metadata</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-mtompolicy</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-saaj</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-soapmonitor-servlet</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-spring</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-transport-http</artifactId>
      <version>1.5.3</version>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-transport-local</artifactId>
      <version>1.5.3</version>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-xmlbeans</artifactId>
      <version>1.5.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpcore</artifactId>
      <version>4.0</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.15</version>
      <type>jar</type>
      <scope>compile</scope>
      <exclusions>
      <exclusion>
      <groupId>com.sun.jdmk</groupId>
      <artifactId>jmxtools</artifactId>
      </exclusion>
      <exclusion>
      <groupId>com.sun.jmx</groupId>
      <artifactId>jmxri</artifactId>
      </exclusion>
      <exclusion>
      <groupId>javax.jms</groupId>
      <artifactId>jms</artifactId>
      </exclusion>
      </exclusions>
      </dependency>
      <dependency>
      <groupId>wsdl4j</groupId>
      <artifactId>wsdl4j</artifactId>
      <version>1.6.2</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>org.apache.ws.commons.schema</groupId>
      <artifactId>XmlSchema</artifactId>
      <version>1.4.3</version>
      <type>jar</type>
      <scope>compile</scope>
      </dependency>
      </dependencies>
      </project>

      (D)
      package webservice.client;

      import java.io.InputStream;

      import mtom.webservice.BinaryData;
      import mtom.webservice.WebServiceStub;

      public class Main {
      public static void main(String[] args) throws Exception {
      WebServiceStub stub = new WebServiceStub("http://localhost:8080/WebService/services/WebService.WebServiceHttpSoap12Endpoint/");
      BinaryData result = stub.getBinaryData();
      InputStream is = result.get_return().getInputStream();
      int next;
      while ((next = is.read()) != -1)

      { System.out.println(next); }

      }
      }

      (E)
      HTTP/1.1 200 OK
      Server: Apache-Coyote/1.1
      Content-Type: multipart/related; boundary="MIMEBoundary_c2fc5fe8cdf5bf17020e924dc81747527cb3fcbb77f7dec5"; type="application/xop+xml"; start="<0.d2fc5fe8cdf5bf17020e924dc81747527cb3fcbb77f7dec5@apache.org>"; start-info="application/soap+xml"; action="tns:getBinaryDataResponse"
      Transfer-Encoding: chunked
      Date: Fri, 10 Dec 2010 15:53:52 GMT

      289
      --MIMEBoundary_c2fc5fe8cdf5bf17020e924dc81747527cb3fcbb77f7dec5
      Content-Type: application/xop+xml; charset=UTF-8; type="application/soap+xml"
      Content-Transfer-Encoding: binary
      Content-ID: <0.d2fc5fe8cdf5bf17020e924dc81747527cb3fcbb77f7dec5@apache.org>

      <?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body><ns1:BinaryData xmlns:ns1="http://webservice.mtom"><ns1:return><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:1.e2fc5fe8cdf5bf17020e924dc81747527cb3fcbb77f7dec5@apache.org" /></ns1:return></ns1:BinaryData></soapenv:Body></soapenv:Envelope>
      e1

      --MIMEBoundary_c2fc5fe8cdf5bf17020e924dc81747527cb3fcbb77f7dec5
      Content-Type: application/binary
      Content-Transfer-Encoding: binary
      Content-ID: <1.e2fc5fe8cdf5bf17020e924dc81747527cb3fcbb77f7dec5@apache.org>

      0

      1. mtom.zip
        252 kB
        Kevin L. Stern

        Activity

        Hide
        Kevin L. Stern added a comment -

        A sample project to demonstrate the issue.

        Show
        Kevin L. Stern added a comment - A sample project to demonstrate the issue.
        Hide
        Andreas Veithen added a comment -

        The root cause of this issue is that AxisServlet wraps the ServletOutputStream in a BufferedOutputStream but doesn't care to flush the BufferedOutputStream, and thus relies on the message formatter to do so. This however is not a requirement specified by the MessageFormatter interface and is also a difference with respect to other transports that manage the output stream properly.

        In 1.5.1 this was not a problem because there was a call to OutputStream#flush() at the right place in Axiom. With the upgrade of the Axiom dependency in 1.5.2, this is no longer the case and the bug in AxisServlet becomes visible.

        The issue in AxisServlet was solved on the trunk by r823960. I've merged that change to the 1.5 branch, and the fix will be available in 1.5.4-SNAPSHOT build #111.

        Show
        Andreas Veithen added a comment - The root cause of this issue is that AxisServlet wraps the ServletOutputStream in a BufferedOutputStream but doesn't care to flush the BufferedOutputStream, and thus relies on the message formatter to do so. This however is not a requirement specified by the MessageFormatter interface and is also a difference with respect to other transports that manage the output stream properly. In 1.5.1 this was not a problem because there was a call to OutputStream#flush() at the right place in Axiom. With the upgrade of the Axiom dependency in 1.5.2, this is no longer the case and the bug in AxisServlet becomes visible. The issue in AxisServlet was solved on the trunk by r823960. I've merged that change to the 1.5 branch, and the fix will be available in 1.5.4-SNAPSHOT build #111.

          People

          • Assignee:
            Andreas Veithen
            Reporter:
            Kevin L. Stern
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development