【问题标题】:Mixed Content for JAXB not working from WSDLJAXB 的混合内容在 WSDL 中不起作用
【发布时间】:2013-11-29 15:19:23
【问题描述】:

我正在使用 NetBeans,我有两个项目:

  • 用于生成 Web 服务并将其部署到 GlassFish 的 EJB 模块
  • 一个简单的控制台客户端来测试和使用这个网络服务

对于网络服务,我使用的是具有混合内容元素的 XSD。 使用以下代码为 JAXB 导入添加绑定文件有效:

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
 xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
 xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc"
 jaxb:version="2.0">
  <jaxb:globalBindings generateMixedExtensions="true"/>
</jaxb:bindings>

它生成了这个代码:

@XmlMixed
@OverrideAnnotationOf
protected List<Serializable> contentOverrideForED;

我可以接受这个生成的代码,尽管它并不理想。

我的问题出在客户端上,为此我为我生成和部署的 web 服务添加了一个 Web 服务引用,它只在 localhost 上运行。

WSDL Customization: External Binding File 中使用相同的绑定文件不会产生content 代码,也不会直接将其用作Wsimport 的选项,也不会将其用作Jaxb option。我感觉这个设置不知何故被忽视了,但是怎么办?

为什么最初的 JAXB 生成包含它,为什么 wsimport 不使用它?我有点困惑。

【问题讨论】:

  • 您是否将 packagename 参数设置为 wsimport?从 wsimport 命令行中删除 -p 参数,如果您设置它将覆盖绑定文件。

标签: java web-services netbeans jaxb wsimport


【解决方案1】:

好问题!我和我的同事花了很多时间在课堂上解决我用 wsimport 生成的混合类型。我尝试了很多调整并得到List&lt;Object&gt;List&lt;Serializable&gt;List&lt;String&gt;。我们使用了简单的 wsimport,但我们不知道:

<jaxb:globalBindings generateMixedExtensions="true"/>

现在,我为您提供创建简单的 wsimport 批处理脚本并为客户发布。我认为您可以在 wsimport 脚本中使用外部绑定文件(-b 参数)。


Martin Grebac wrote great article关于这个话题:

这是一个很好的决定 避免使用混合内容,尤其是在设计大型架构时 有很多类型扩展。将这种模式映射到任何 绑定框架通常很复杂,会导致并发症和 发展放缓。 JAXB 从未被设计为处理这些 以一种方便的方式使用案例 - 它是一个 Java XML 映射框架, 并且不可能在层次结构中表示这种内容 Java 对象。

我完全同意 Martin 的观点。 JAXB 是简单的 Java XML 映射框架。但是现有的一种定制解决了在一个 XSD 中存在多种混合类型的问题。那是generateMixedExtensions="true"。这种定制是改变 JAXB 的行为。


I'd really like to know why wsimport does this differently from xjc  

我认为您在使用 xjc 和 wsimport 时会更改 JAXB 的行为,而使用没有此自定义的简单 JAXB。

请查看wsimport 2.0wsimport 2.1 文档以获取参数。这是关于 mixed content model 的链接,如果您使用 xs:any 混合类型 can you adjust it

【讨论】:

    【解决方案2】:

    您可能需要考虑使用 Eclipse 来生成您需要的内容。即使您使用的 xsd 和 wsdl 未包含在问题中,我还是想出了一个似乎可行的简单示例。我没有使用绑定文件,Eclipse 中的向导选择了需要混合的事实,因为 XSD 中的混合 =“true”(可能想尝试你的没有绑定):

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/NewXMLSchema" xmlns:tns="http://www.example.org/NewXMLSchema" elementFormDefault="qualified">
    
    <xs:element name="letter">
      <xs:complexType mixed="true">
        <xs:sequence>
          <xs:element name="name" type="xs:string"/>
          <xs:element name="orderid" type="xs:positiveInteger"/>
          <xs:element name="shipdate" type="xs:date"/>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
    
    </xs:schema>
    

    WSDL:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.example.org/NewWSDLFile/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="NewWSDLFile" targetNamespace="http://www.example.org/NewWSDLFile/" xmlns:xsd1="http://www.example.org/NewXMLSchema">
      <wsdl:types>
        <xsd:schema targetNamespace="http://www.example.org/NewWSDLFile/">
          <xsd:element name="NewOperation">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="in" type="xsd:string"/>
              </xsd:sequence>
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="NewOperationResponse">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="out" type="xsd:string"/>
              </xsd:sequence>
            </xsd:complexType>
          </xsd:element>
        </xsd:schema>
        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <xsd:import namespace="http://www.example.org/NewXMLSchema"
                schemaLocation="NewXMLSchema.xsd">
            </xsd:import></xsd:schema></wsdl:types>
      <wsdl:message name="NewOperationRequest">
        <wsdl:part element="xsd1:letter" name="parameters"/>
      </wsdl:message>
      <wsdl:message name="NewOperationResponse">
        <wsdl:part element="tns:NewOperationResponse" name="parameters"/>
      </wsdl:message>
      <wsdl:portType name="NewWSDLFile">
        <wsdl:operation name="NewOperation">
          <wsdl:input message="tns:NewOperationRequest"/>
          <wsdl:output message="tns:NewOperationResponse"/>
        </wsdl:operation>
      </wsdl:portType>
      <wsdl:binding name="NewWSDLFileSOAP" type="tns:NewWSDLFile">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="NewOperation">
          <soap:operation soapAction="http://www.example.org/NewWSDLFile/NewOperation"/>
          <wsdl:input>
            <soap:body use="literal"/>
          </wsdl:input>
          <wsdl:output>
            <soap:body use="literal"/>
          </wsdl:output>
        </wsdl:operation>
      </wsdl:binding>
      <wsdl:service name="NewWSDLFile">
        <wsdl:port binding="tns:NewWSDLFileSOAP" name="NewWSDLFileSOAP">
          <soap:address location="http://www.example.org/"/>
        </wsdl:port>
      </wsdl:service>
    </wsdl:definitions>
    

    相关的Java:

        //
        // Generated By:JAX-WS RI IBM 2.2.1-11/28/2011 08:28 AM(foreman)- (JAXB RI IBM 2.2.3-11/28/2011 06:21 AM(foreman)-)
        //
    
    
        package org.example.newwsdlfile;
    
        import javax.jws.WebMethod;
        import javax.jws.WebParam;
        import javax.jws.WebResult;
        import javax.jws.WebService;
        import javax.jws.soap.SOAPBinding;
        import javax.xml.bind.annotation.XmlSeeAlso;
        import org.example.newxmlschema.Letter;
    
        @WebService(name = "NewWSDLFile", targetNamespace = "http://www.example.org/NewWSDLFile/")
        @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
        @XmlSeeAlso({
            org.example.newwsdlfile.ObjectFactory.class,
            org.example.newxmlschema.ObjectFactory.class
        })
        public interface NewWSDLFile {
    
    
            /**
             * 
             * @param parameters
             * @return
             *     returns org.example.newwsdlfile.NewOperationResponse
             */
            @WebMethod(operationName = "NewOperation", action = "http://www.example.org/NewWSDLFile/NewOperation")
            @WebResult(name = "NewOperationResponse", targetNamespace = "http://www.example.org/NewWSDLFile/", partName = "parameters")
            public NewOperationResponse newOperation(
                @WebParam(name = "letter", targetNamespace = "http://www.example.org/NewXMLSchema", partName = "parameters")
                Letter parameters);
    
        }
    

    实施:

        package org.example.newwsdlfile;
    
        import java.net.URL;
    
        import javax.xml.namespace.QName;
        import javax.xml.transform.Source;
        import javax.xml.ws.BindingProvider;
        import javax.xml.ws.Dispatch;
        import javax.xml.ws.Service;
        import javax.xml.ws.soap.SOAPBinding;
        import org.example.newxmlschema.Letter;
    
        public class NewWSDLFileSOAPProxy{
    
            protected Descriptor _descriptor;
    
            public class Descriptor {
                private org.example.newwsdlfile.NewWSDLFile_Service _service = null;
                private org.example.newwsdlfile.NewWSDLFile _proxy = null;
                private Dispatch<Source> _dispatch = null;
    
                public Descriptor() {
                    init();
                }
    
                public Descriptor(URL wsdlLocation, QName serviceName) {
                    _service = new org.example.newwsdlfile.NewWSDLFile_Service(wsdlLocation, serviceName);
                    initCommon();
                }
    
                public void init() {
                    _service = null;
                    _proxy = null;
                    _dispatch = null;
                    _service = new org.example.newwsdlfile.NewWSDLFile_Service();
                    initCommon();
                }
    
                private void initCommon() {
                    _proxy = _service.getNewWSDLFileSOAP();
                }
    
                public org.example.newwsdlfile.NewWSDLFile getProxy() {
                    return _proxy;
                }
    
                public Dispatch<Source> getDispatch() {
                    if (_dispatch == null ) {
                        QName portQName = new QName("http://www.example.org/NewWSDLFile/", "NewWSDLFileSOAP");
                        _dispatch = _service.createDispatch(portQName, Source.class, Service.Mode.MESSAGE);
    
                        String proxyEndpointUrl = getEndpoint();
                        BindingProvider bp = (BindingProvider) _dispatch;
                        String dispatchEndpointUrl = (String) bp.getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
                        if (!dispatchEndpointUrl.equals(proxyEndpointUrl))
                            bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, proxyEndpointUrl);
                    }
                    return _dispatch;
                }
    
                public String getEndpoint() {
                    BindingProvider bp = (BindingProvider) _proxy;
                    return (String) bp.getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
                }
    
                public void setEndpoint(String endpointUrl) {
                    BindingProvider bp = (BindingProvider) _proxy;
                    bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointUrl);
    
                    if (_dispatch != null ) {
                        bp = (BindingProvider) _dispatch;
                        bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointUrl);
                    }
                }
    
                public void setMTOMEnabled(boolean enable) {
                    SOAPBinding binding = (SOAPBinding) ((BindingProvider) _proxy).getBinding();
                    binding.setMTOMEnabled(enable);
                }
            }
    
            public NewWSDLFileSOAPProxy() {
                _descriptor = new Descriptor();
                _descriptor.setMTOMEnabled(false);
            }
    
            public NewWSDLFileSOAPProxy(URL wsdlLocation, QName serviceName) {
                _descriptor = new Descriptor(wsdlLocation, serviceName);
                _descriptor.setMTOMEnabled(false);
            }
    
            public Descriptor _getDescriptor() {
                return _descriptor;
            }
    
            public NewOperationResponse newOperation(Letter parameters) {
                return _getDescriptor().getProxy().newOperation(parameters);
            }
    
        }
    

    “字母”类:

        //
        // Generated By:JAX-WS RI IBM 2.2.1-11/28/2011 08:28 AM(foreman)- (JAXB RI IBM 2.2.3-11/28/2011 06:21 AM(foreman)-)
        //
    
    
        package org.example.newxmlschema;
    
        import java.io.Serializable;
        import java.math.BigInteger;
        import java.util.ArrayList;
        import java.util.List;
        import javax.xml.bind.JAXBElement;
        import javax.xml.bind.annotation.XmlAccessType;
        import javax.xml.bind.annotation.XmlAccessorType;
        import javax.xml.bind.annotation.XmlElementRef;
        import javax.xml.bind.annotation.XmlElementRefs;
        import javax.xml.bind.annotation.XmlMixed;
        import javax.xml.bind.annotation.XmlRootElement;
        import javax.xml.bind.annotation.XmlType;
        import javax.xml.datatype.XMLGregorianCalendar;
    
    
        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "", propOrder = {
            "content"
        })
        @XmlRootElement(name = "letter")
        public class Letter {
    
            @XmlElementRefs({
                @XmlElementRef(name = "name", namespace = "http://www.example.org/NewXMLSchema", type = JAXBElement.class),
                @XmlElementRef(name = "shipdate", namespace = "http://www.example.org/NewXMLSchema", type = JAXBElement.class),
                @XmlElementRef(name = "orderid", namespace = "http://www.example.org/NewXMLSchema", type = JAXBElement.class)
            })
            @XmlMixed
            protected List<Serializable> content;
    
    
            public List<Serializable> getContent() {
                if (content == null) {
                    content = new ArrayList<Serializable>();
                }
                return this.content;
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-28
      • 1970-01-01
      • 2021-05-25
      • 2016-06-22
      • 1970-01-01
      • 2015-04-26
      • 1970-01-01
      • 2021-08-01
      相关资源
      最近更新 更多