# Soap with Attachments - Unmarshalling Error



## ayibogan (14. Dez 2011)

Versuche grad mit Eclipse und CXF mit SOAP 1.2 Binding und dem Oracle Tutorial ein Testprojekt zu erstellen, bekomme aber leider ein Fehler. Einfache Parameter wie String, int usw. machen keine Probleme.

Webservice:

```
package de;
 
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
 
@WebService(targetNamespace = "http://de/", endpointInterface = "de.EndPoint", portName = "WebServicePort", serviceName = "WebServiceService")
public class test implements EndPoint{
 
    @WebMethod(operationName = "create", action = "urn:Create")
    public String create(@WebParam(name = "arg0") SOAPMessage message) {
 
        java.util.Iterator iterator = message.getAttachments();
        while (iterator.hasNext()) {
            AttachmentPart attachment = (AttachmentPart) iterator.next();
            String id = attachment.getContentId();
            String type = attachment.getContentType();
            if (type.equals("text/plain")) {
                Object content = null;
                try {
                    content = attachment.getContent();
                } catch (SOAPException e) {
                    e.printStackTrace();
                }
                System.out.println("Attachment contains:\n" + content);
            }
        }
        return "CREATED!";
    }
}
```

WSDL:
[XML]<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="WebServiceService" targetNamespace="http://de/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://de/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/">
  <wsdl:types>
    <schema xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://de/" schemaLocation="webservice_schema1.xsd"/>
</schema>
  </wsdl:types>
  <wsdl:message name="createResponse">
    <wsdlart name="parameters" element="tns:createResponse">
    </wsdlart>
  </wsdl:message>
  <wsdl:message name="create">
    <wsdlart name="parameters" element="tns:create">
    </wsdlart>
  </wsdl:message>
  <wsdlortType name="EndPoint">
    <wsdlperation name="create">
      <wsdl:input name="create" message="tns:create">
    </wsdl:input>
      <wsdlutput name="createResponse" message="tns:createResponse">
    </wsdlutput>
    </wsdlperation>
  </wsdlortType>
  <wsdl:binding name="WebServiceServiceSoapBinding" type="tns:EndPoint">
    <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdlperation name="create">
      <soap12peration soapAction="urn:Create" style="document"/>
      <wsdl:input name="create">
        <soap12:body use="literal"/>
      </wsdl:input>
      <wsdlutput name="createResponse">
        <soap12:body use="literal"/>
      </wsdlutput>
    </wsdlperation>
  </wsdl:binding>
  <wsdl:service name="WebServiceService">
    <wsdlort name="WebServicePort" binding="tns:WebServiceServiceSoapBinding">
      <soap12:address location="http://localhost:8080/WebServiceSOAP/services/WebServicePort"/>
    </wsdlort>
  </wsdl:service>
</wsdl:definitions>[/XML]

XSD:
[XML]<?xml version="1.0" encoding="utf-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://de/" elementFormDefault="unqualified" targetNamespace="http://de/" version="1.0">
<xs:element name="create" type="tns:create"/>
<xs:element name="createResponse" type="tns:createResponse"/>
<xs:complexType name="create">
    <xs:sequence>
      <xs:element minOccurs="0" name="arg0" type="tns:soapMessage"/>
    </xs:sequence>
  </xs:complexType>
<xs:complexType abstract="true" name="soapMessage">
    <xs:sequence>
      <xs:element minOccurs="0" name="contentDescription" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
<xs:complexType name="createResponse">
    <xs:sequence>
      <xs:element minOccurs="0" name="return" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>[/XML]

Endpoint:

```
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
 
@WebService(name = "EndPoint", targetNamespace = "http://de/")
public interface EndPoint {
 
    @WebMethod(operationName = "create", action = "urn:Create")
    public String create(@WebParam(name = "arg0") SOAPMessage message);
 
}
```

CLient:

```
public static void create() throws Exception {
        QName serviceName = new QName("http://de/", "WebServiceService");
        QName portName = new QName("http://de/", "WebServicePort");
 
        Service service = Service.create(serviceName);
        service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING,
                "http://localhost:8080/WebServiceSOAP/services/WebServicePort?wsdl");
        de.EndPoint client = service.getPort(portName, de.EndPoint.class);
 
        MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        SOAPMessage message = factory.createMessage();
        AttachmentPart attachment = message.createAttachmentPart();
        String stringContent = "Update address for Sunny Skies " +
                "Inc., to 10 Upbeat Street, Pleasant Grove, CA 95439";
 
            attachment.setContent(stringContent, "text/plain");
            attachment.setContentId("update_address");
            message.addAttachmentPart(attachment);
 
        String response = client.create(message);
        System.out.println("SOAP Response: " + response);
    }
```

Kommt folgende Exception:
Caused by: org.apache.cxf.binding.soap.SoapFault: Unmarshalling Error: Unable to create an instance of javax.xml.soap.SOAPMessage
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterce ptor.java:75)
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInIntercep tor.java:46)
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInIntercep tor.java:35)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiator Observer.java:105)
at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.ja va:69)
at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.ja va:34)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:797)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.jav a:1618)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1491)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1399)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:646)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(Mes sageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:533)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:463)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:366)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:319)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:88)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
... 36 more


Jemand eine Idee?


----------



## SlaterB (15. Dez 2011)

was läßt dich denn vermuten, dass es funktionieren könnte, also mit SOAPMessage als eigenen Parameter,
gibt es Internet-Beispiele dazu? hast du die exakt übernommen mit Fehler oder laufen diese?

---

wo tritt die Exception auf, kannst du irgendwo einen try/catch setzen und mehr Informationen abfragen, 
z.B. einen Cause in der Exception?


----------



## ayibogan (15. Dez 2011)

Der Fehler taucht direkt bei Aufruf des WebServices:
client.create(message);

Auf SAAJ Tutorial - The Java EE 5 Tutorial unter Adding Attachments steht wie man ein Atchment erstellt.

Da als Parameter verschieden primitive typen, Objekte, Collections usw. übergeben werden können, dachte ich mir, dass dies auch mit SOAPMessage geht. Habe leider dazu kein Bsp gefunden, wie ich den erstellten SoapMessage an den Webservice schicken kann.

Hier nochmal der komplette StackTrace
15.12.2011 13:08:09 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
INFO: Creating Service {http://de/}WebServiceService from class de.EndPoint
SOAP request
javax.xml.ws.soap.SOAPFaultException: Unmarshalling Error: Unable to create an instance of javax.xml.soap.SOAPMessage 
	at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)
	at $Proxy31.create(Unknown Source)
	at de.EndPointClient.main(EndPointClient.java:43)
Caused by: org.apache.cxf.binding.soap.SoapFault: Unmarshalling Error: Unable to create an instance of javax.xml.soap.SOAPMessage 
...
geht weiter wie oben gepostet


----------



## SlaterB (15. Dez 2011)

ich kann leider auch keine Beispiele geben wie man gut was auch immer versenden kann/ muss/ soll,

ich sehe nur den strukturellen Fehler: du erzeugst das SOAPMessage-Objekt in einer Factory, nicht über einen einfachen Konstruktor,
der allgemeine Mechanismus muss das übertragende Objekt aber automatisch zusammenbauen, braucht einen Default-Konstruktor usw., 
daher die Fehlermeldung 'Unable to create an instance of javax.xml.soap.SOAPMessage',

SOAPMessage scheint mir nicht als Parameter geeignet, wird vielleicht intern bei dem ganzen Kram automatisch verwendet


----------



## ayibogan (15. Dez 2011)

hab mir grad meherer Axis Beispiele angeschaut, da wird oft als Parameter Datahandler genutzt.
Hab das bei mir eingebaut, das geht auch. Das Problem ist, irgendwie wird der Inhalt vom Client für datahandler.getName() (z.B. DateiName) bei Ankunft bei server auf NULL gesetzt.

Ich bin leider neu in SOAP, in was für ein Format schickt man eigentlich Binärdaten z.B. PDF an eine SOAPSchnitstelle bzw. was sollte der Webservice als Paramter erwarten?


----------

