locked
WCF file upload/download issue from Java client RRS feed

  • Question

  • User1112784522 posted

    I'm trying to create a WCF service (.Net 4.5 in VS2012) for file uploads that can be consumed by clients in other languages, Java (using CXF) in particular. I've got the WCF side of things working great from .Net clients, but am having some issues on the CXF side.

    I'm not sure if this is a WCF or CXF issue so I'm posting here and the CXF mailing lists to see if I'm doing something wrong on one side or the other.

    When I try to generate the proxy in CXF from the WSDL through Eclipse (4.2/Juno), I'm getting an exception that prevents the proxy from being created:

    wsdl2java -client -d C:\Users\Ryan\workspace\WcfProxy\.cxftmp/src -classdir C:\Users\Ryan\workspace\WcfProxy\build\classes -p http://tempuri.org/=org.tempuri -impl -validate -exsh false -dns true -dex true -wsdlLocation http://localhost:10186/UploadFile.svc?wsdl -verbose -defaultValues -fe jaxws -db jaxb -wv 1.1 http://localhost:10186/UploadFile.svc?wsdl
    wsdl2java - Apache CXF 2.7.0
    
    
    WSDLToJava Error: Schema Error : src-resolve: Cannot resolve the name 'ns0:StreamBody' to a(n) 'type definition' component.
    
    org.apache.cxf.tools.common.ToolException: Schema Error : src-resolve: Cannot resolve the name 'ns0:StreamBody' to a(n) 'type definition' component.
    

    My WCF service contract is as follows:

    <ServiceContract()>
    Public Interface IUploadFile
    
        <OperationContract()>
        Sub UploadFile(ByVal remoteFile As RemoteFile)
    
        <OperationContract()>
        Function DownloadFile() As RemoteFile
    
    End Interface

    My WCF message contract (RemoteFile) is as follows:

    <MessageContract()> _
    Public Class RemoteFile
        Implements IDisposable
    
        <MessageHeader(MustUnderstand:=True)> _
        Public FileName As String
    
        <MessageHeader(MustUnderstand:=True)> _
        Public Length As Long
    
        <MessageBodyMember(Order:=1)> _
        Public FileByteStream As System.IO.Stream
    
        Public Sub Dispose() Implements IDisposable.Dispose
            If FileByteStream IsNot Nothing Then
                FileByteStream.Close()
                FileByteStream = Nothing
            End If
        End Sub
    End Class

    My WCF service configuration is as follows:

    ...
    <system.serviceModel>
      <bindings>
        <basicHttpBinding>
          <binding name="FileTransferServicesBinding"
            transferMode="Streamed"
            messageEncoding="Mtom"
            maxReceivedMessageSize="10067108864">
          </binding>
        </basicHttpBinding>
      </bindings>
      <services>
        <service behaviorConfiguration="UploadServiceBehavior" name="Server.UploadFile">
          <endpoint address=""
                binding="basicHttpBinding"
                bindingConfiguration="FileTransferServicesBinding"
                contract="Server.IUploadFile" />
        </service>
      </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="UploadServiceBehavior">
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
    ...

    My WSDL is as follows:

    <?xml version="1.0" encoding="UTF-8"?>
    <wsdl:definitions name="UploadFile" targetNamespace="http://tempuri.org/">
    <wsp:Policy wsu:Id="BasicHttpBinding_IUploadFile_policy">
        <wsp:ExactlyOne>
            <wsp:All>
                <wsoma:OptimizedMimeSerialization/>
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>
    <wsdl:types>
        <xsd:schema targetNamespace="http://tempuri.org/Imports">
            <xsd:import schemaLocation="http://localhost:10186/UploadFile.svc?xsd=xsd1" namespace="http://tempuri.org/"/>
            <xsd:import schemaLocation="http://localhost:10186/UploadFile.svc?xsd=xsd0" namespace="http://schemas.microsoft.com/Message"/>
            <xsd:import schemaLocation="http://localhost:10186/UploadFile.svc?xsd=xsd2" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
        </xsd:schema>
    </wsdl:types>
    <wsdl:message name="RemoteFile">
        <wsdl:part name="parameters" element="tns:RemoteFile"/>
    </wsdl:message>
    <wsdl:message name="RemoteFile_Headers">
        <wsdl:part name="FileName" element="tns:FileName"/>
        <wsdl:part name="Length" element="tns:Length"/>
    </wsdl:message>
    <wsdl:message name="IUploadFile_DownloadFile_InputMessage"/>
    <wsdl:portType name="IUploadFile">
        <wsdl:operation name="UploadFile">
            <wsdl:input wsaw:Action="http://tempuri.org/IUploadFile/UploadFile" name="RemoteFile" message="tns:RemoteFile"/>
        </wsdl:operation>
        <wsdl:operation name="DownloadFile">
            <wsdl:input wsaw:Action="http://tempuri.org/IUploadFile/DownloadFile" message="tns:IUploadFile_DownloadFile_InputMessage"/>
            <wsdl:output wsaw:Action="http://tempuri.org/IUploadFile/DownloadFileResponse" name="RemoteFile" message="tns:RemoteFile"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="BasicHttpBinding_IUploadFile" type="tns:IUploadFile">
        <wsp:PolicyReference URI="#BasicHttpBinding_IUploadFile_policy"/>
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="UploadFile">
            <soap:operation soapAction="http://tempuri.org/IUploadFile/UploadFile" style="document"/>
            <wsdl:input name="RemoteFile">
                <soap:header message="tns:RemoteFile_Headers" part="FileName" use="literal"/>
                <soap:header message="tns:RemoteFile_Headers" part="Length" use="literal"/>
                <soap:body use="literal"/>
            </wsdl:input>
        </wsdl:operation>
        <wsdl:operation name="DownloadFile">
            <soap:operation soapAction="http://tempuri.org/IUploadFile/DownloadFile" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="RemoteFile">
                <soap:header message="tns:RemoteFile_Headers" part="FileName" use="literal"/>
                <soap:header message="tns:RemoteFile_Headers" part="Length" use="literal"/>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="UploadFile">
        <wsdl:port name="BasicHttpBinding_IUploadFile" binding="tns:BasicHttpBinding_IUploadFile">
            <soap:address location="http://localhost:10186/UploadFile.svc"/>
        </wsdl:port>
    </wsdl:service>
    </wsdl:definitions>

    Obviously the exception indicates it is having an issue creating the stream body type of the message, but does anyone see what I'm doing wrong or need to change to be able to enable non-.Net clients to use this WCF service?

    Wednesday, October 31, 2012 10:18 PM

All replies

  • User-1658256289 posted

    Hi, please check if you have configure the wcf service properly. Below article introduce some requirement to your application to allow java clients consuming wcf services.

    http://hoonzis.blogspot.com/2011/07/consuming-wcf-services-with-java-client.html

    Friday, November 2, 2012 4:11 AM
  • User1112784522 posted

    That's a good article that I hadn't seen before, thanks. I double checked everything he does against mine and unfortunately I'm still having the same issue. I've been trying out all sorts of settings on my service the past few days and haven't had any luck or change in behavior.

    Sunday, November 4, 2012 1:24 AM
  • User1112784522 posted

    Okay, here's more info that will hopefully help. Everything I'm seeing online related to the "Cannot resolve the name 'xxxxxxx' to a(n) 'type definition' component." error indicates an issue with the WSDL namespaces, so I've been poking around more in the generated WSDL and changing things on the code side to see the result.

    My particular message says it can't resolve 'ns0:StreamBody' so I referenced my main WSDL. My class "RemoteFile" is not defined directly in the WSDL, so it is imported with these statements:

    <xsd:import schemaLocation="http://localhost:10186/UploadFile.svc?xsd=xsd1" namespace="http://tempuri.org/"/>
    <xsd:import schemaLocation="http://localhost:10186/UploadFile.svc?xsd=xsd0" namespace="http://schemas.microsoft.com/Message"/>

    So, here is the schema definition of the one at "xsd1":

    <xs:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
      <xs:import schemaLocation="http://localhost:10186/UploadFile.svc?xsd=xsd0" namespace="http://schemas.microsoft.com/Message"/>
      <xs:element name="RemoteFile">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="FileByteStream" type="q1:StreamBody"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="FileName" nillable="true" type="xs:string"/>
      <xs:element name="Length" type="xs:long"/>
    </xs:schema>

    So far so good, here's my mapping to my "RemoteFile" class. Now, one more import to get the mapping for the import at "xsd0":

    <xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/Message">
      <xs:simpleType name="StreamBody">
        <xs:restriction base="xs:base64Binary"/>
      </xs:simpleType>
    </xs:schema>

    Cool, there's my mapping for the Stream parameter that is the cause of the exception. However, none of this looks problematic so I'm still somewhat stumped. I've tried using the new ?singleWsdl feature in 4.5 and the flattened WSDL it creates has the same issue.

    So, I'm still stumped at this point. If anyone has some insight, I'd love to hear it.


    Sunday, November 4, 2012 10:42 PM
  • User1112784522 posted

    Another followup, I managed to get the CXF client generated but now I'm encountering an http 400: Bad Request coming back from WCF when the CXF client tries to upload the file. Digging into the WCF traces, there's an exception being thrown:

    System.ServiceModel.CommunicationException: Error creating a reader for the MTOM message ---> System.Xml.XmlException: MIME part with Content-ID '<root.message@cxf.apache.org>' not found.

    Based on the error message on the server, the XOP starting header is missing but my interceptor on the CXF side shows it is there:

    --uuid:70dd56ae-7102-45c9-a5d9-b0078ad6ad13
    Content-Type: application/xop+xml; charset=UTF-8; type="text/xml";
    Content-Transfer-Encoding: binary
    Content-ID: <root.message@cxf.apache.org>

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> ...
    </soap:Envelope>

    --uuid:70dd56ae-7102-45c9-a5d9-b0078ad6ad13
    Content-Type: application/octet-stream
    Content-Transfer-Encoding: binary
    Content-ID: <4e2a3954-d8ec-490d-a844-ab55594e9c80-1@tempuri.org>

    ...file content here...


    Any ideas? As far as I can tell all of the content-type declarations are what WCF expects...

    Thursday, November 8, 2012 10:44 AM
  • User1112784522 posted

    I implemented the exact same service in a clean project with a byte array instead of a Stream object and I get the exact same error message:

    Error creating a reader for the MTOM message ---&gt; System.Xml.XmlException: MIME part with Content-ID '&lt;root.message@cxf.apache.org&gt;' not found.

    Regardless of whether the WCF service uses a Stream object or byte array, the CXF clients still use Java byte arrays.

    I'm at a loss here...

    Tuesday, November 13, 2012 9:18 PM
  • User1120386721 posted

    Have you solved the problem?

    I have the same...

    When I use wsimport.exe, in my artifacts I have one class who have an attribute byte[] instead of DataHandler..., but I have the same StreamBody like you.

    Thursday, October 17, 2013 3:22 PM
  • User1112784522 posted

    I haven't officially yet, however in another forum I recently got a response from someone indicating that updating to the most recent version of CXF fixed their issue. I haven't had a chance to actually test it myself to verify, but I'd at least start with that if you haven't already. :)

    Thursday, October 17, 2013 5:30 PM
  • User1120386721 posted

    Yes, it's correct. With a later version of CXF it works properly.

    Friday, October 18, 2013 11:42 AM
  • User1112784522 posted

    Yes, it's correct. With a later version of CXF it works properly.

    Awesome, glad to hear that worked. Can't wait to get back to it myself. Cool

    Friday, October 18, 2013 8:49 PM
  • User-331032610 posted

    Hi,

    For any future reference, the blog has been moved to:
    http://www.hoonzis.com/consuming-wcf-services-with-java-client/

    I can't edit the orginal link.

    Sunday, October 25, 2015 11:15 AM