简体   繁体   English

从 WSDL 开发 Web 服务客户端时出现异常

[英]Exception when developing a Webservice Client from a WSDL

I am creating a webservice client from a WSDL.我正在从 WSDL 创建一个 Web 服务客户端。

A typical SOAP request to the service looks something like this对服务的典型 SOAP 请求如下所示

<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:messageBody>
                    <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:我使用 JAX-WS 生成服务工件并填充我的对象,如下所示:

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). messageBody object 只有 1 个方法 messageBody.setAny(value)。 But i need to place a DataContainer Element inside it.但我需要在其中放置一个 DataContainer 元素。

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. org.w3c.dom.DocumentObject (我得到“javax.xml.ws.soap.SOAPFaultException:无法处理请求。”)可能是由于 Z0F635AB70E0Ccleration.32E76C77dedecleration.32E76CF
  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]") 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]") JAXBElement (我得到“[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或者我需要做什么才能在消息正文中获取 DataContainer

As you mentioned you have messageBody.setAny(value) which means that the XSI:type for MessageBody has been set to anytype .正如您所提到的,您有messageBody.setAny(value)这意味着 MessageBody 的XSI:type已设置为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.这意味着您可以在那里设置任何 object,需要注意的是 JAXB 应该能够在 JAX-WS wsdl2java 工具定义的上下文中编组它。 From the error message 'cannot find DataContainer in Conext' it seems like your DataContainer classes are not in the same context.从错误消息“在 Conext 中找不到 DataContainer”看来,您的 DataContainer 类不在同一个上下文中。

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.这是一个解决方法,您可以将 DataContainer Object 编组为JAXBElement<String> (或者可能只是一个字符串,但我不确定这是否可行) object 然后将其设置为 anyType。 This way you won't get Class not know in context as String is a basic JAXB type.这样你就不会在上下文中不知道 Class 因为 String 是基本的 JAXB 类型。

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.当您尝试使用第 2 点或第 3 点时,我不知道您是如何定义 package 结构的,所以我在这里进行了一次疯狂的尝试。 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.从错误消息来看,您单独生成的 DataContainer Class 似乎与 Message 及其子类不在同一个 package 中。 Try to move your DataContainer and its associated classes to the same package as the Message Class and merge the two ObjectFactory Classes together.尝试将您的 DataContainer 及其关联类移动到与消息 Class 相同的 package 中,并将两个 ObjectFactory 类合并在一起。 This should allow JAXB to find DataContainer in the same 'context' as Message.这应该允许 JAXB 在与 Message 相同的“上下文”中找到 DataContainer。

The error is probably occurring when you make the actual request and JAXB is marshaling the objects to create the request (ie JAX-WS is internally calling the JAXB Marshelling service).当您发出实际请求并且 JAXB 正在编组对象以创建请求时,错误可能发生(即 JAX-WS 在内部调用 JAXB 编组服务)。 In this case when you generated the client the JAXBContext was set to the package where Message class is.在这种情况下,当您生成客户端时,JAXBContext 设置为 package,其中消息 class 是。

Here is a simple tutorial which deals with JAXBContext Marshaling and unmarshaling.这是一个处理 JAXBContext 编组和解组的简单教程。 http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/JAXBUsing3.html http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/tutorial/doc/JAXBUsing3.ZFC35FDC70D5FC67D23E2C70D5FC69D23E28C

Also as per this , you can probably set the anyType to org.w3c.dom.Element and not org.w3c.dom.Document同样按照这个,您可以将 anyType 设置为 org.w3c.dom.Element 而不是 org.w3c.dom.Document

The secret for using the xs:any of non-included XSD type is @XmlSeeAlso .使用 xs:any of non-included XSD 类型的秘诀是@XmlSeeAlso When you create your JAXB classes from xjc tool you will get an interface defines the @WebService methods.当您从 xjc 工具创建 JAXB 类时,您将获得一个定义@WebService方法的接口。 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如果您不修改自动生成的 java 文件,您最好在 package 中扩展此接口并将@XmlSeeAlso({ExternalClassYouWantToReferTo.class})添加到此新接口,例如: 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.你所有的Service class 和@WebService都是从这个接口实现的。

When your client call getPort method, you should pass your new implemented interface as the second parameter like:当您的客户端调用getPort方法时,您应该将新实现的接口作为第二个参数传递,例如:

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. getPort方法将查看您为@XmlSeeAlso传递的接口并初始化其内部JAXBContext。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM