开发者

Exception when developing a Webservice Client from a WSDL

I am creating a webservice client from a WSDL.

A typical SOAP request to the service looks something like this

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:someGateway">
    <soapenv:Header/>
    <soapenv:Body>
        <urn:send>      
            <urn:message>
                <urn:messageID>1001</urn:messageID>
                <urn:messageB开发者_运维百科ody>
                    <DataContainer>
                        SOME MORE ELEMENTS
                    </DataContainer>
                </urn:messageBody>
            </urn:message>
        </urn:send>
    </soapenv:Body>
</soapenv:Envelope>

I used JAX-WS to generate the service artefacts and populated my objects as below:

Message message = objectFactory.createMessage();
//Set message ID
String messageID = "123456"
message.setMessageID(messageID );
//Set message Body
MessageBody messageBody = objectFactory.createMessageMessageBody()

The messageBody object has only 1 method messageBody.setAny(value). But i need to place a DataContainer Element inside it.

I have tried passing:

  1. org.w3c.dom.DocumentObject (I get "javax.xml.ws.soap.SOAPFaultException: Failed to process the request.") probbaly due to the xml decleration.
  2. DataContainer object as generated by JAXB from an XSD (I get "[javax.xml.bind.JAXBException: class DataContainer nor any of its super class is known to this context]")
  3. JAXBElement (I get "[javax.xml.bind.JAXBException: class DataContainer is not known to this context]")

What am I doing wrong? Or what do i Need to do to get the DataContainer in the message body


As you mentioned you have messageBody.setAny(value) which means that the XSI:type for MessageBody has been set to anytype. This means you can set any object there, the cavet being JAXB should be able to marshal it within the context defined by the JAX-WS wsdl2java tool. From the error message 'cannot find DataContainer in Conext' it seems like your DataContainer classes are not in the same context.

Here is a workaround for that, you can probably marshal your DataContainer Object into a JAXBElement<String> (or probably simply a String, but I am not sure if that will work) object and then set that into the anyType. This way you won't get Class not know in context as String is a basic JAXB type.

I don't know how you have defined your package structure when you were trying to use point 2 or 3, So I am taking a wild stab here. From the error message, it seems that your separately generated DataContainer Class is not in the same package as the Message and its sub classes. Try to move your DataContainer and its associated classes to the same package as the Message Class and merge the two ObjectFactory Classes together. This should allow JAXB to find DataContainer in the same 'context' as Message.

The error is probably occurring when you make the actual request and JAXB is marshaling the objects to create the request (i.e. JAX-WS is internally calling the JAXB Marshelling service). In this case when you generated the client the JAXBContext was set to the package where Message class is.

Here is a simple tutorial which deals with JAXBContext Marshaling and unmarshaling. http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/JAXBUsing3.html

Also as per this, you can probably set the anyType to org.w3c.dom.Element and not org.w3c.dom.Document


The secret for using the xs:any of non-included XSD type is @XmlSeeAlso. When you create your JAXB classes from xjc tool you will get an interface defines the @WebService methods. That interface will also be used by client and service implementation. If you won't to modify the auto-generated java files you'd better extends this interface in your package and add @XmlSeeAlso({ExternalClassYouWantToReferTo.class}) to this new interface, ex: IWebServiceInterface

@WebService(name = "IExternalXmlBatchReceive", targetNamespace = "http://External.ServiceContract.BatchReceive")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
    ObjectFactory.class, ExternalClassYouWantToReferTo.class
})
public IWebServiceInterface extends InterfaceYourAutoCreationCode {
@WebMethod(name=...)
 ......
}

All your Service class and @WebService are implemented from this interface.

When your client call getPort method, you should pass your new implemented interface as the second parameter like:

IWebServiceInterface wi = service.getPort(YOUR_QNAME, IWebServiceInterface.class);

The getPort method will look into the interface which you passed in for the @XmlSeeAlso and initialize its internal JAXBContext.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜