我正在使用NetBeans,我有两个项目:
- 用于生成Web服务并将其部署到GlassFish的EJB模块
- 一个简单的控制台客户端,用于测试和使用此Web服务
对于Web服务,我使用的是具有混合内容元素的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不使用它?我在这里有点困惑。
好问题!我和同事们花了很多小时来解决我用wsimport生成的类中的混合类型。我尝试了多次调整,得到了List<Object>
、List<Serializable>
或List<String>
。我们使用了简单的wsimport,但我们不知道:
<jaxb:globalBindings generateMixedExtensions="true"/>
现在,我提供给您创建简单的wsimport批处理脚本,并为客户发布。我认为您可以在wsimport脚本中使用外部绑定文件(-b参数)。
Martin Grebac写了一篇关于这个主题的伟大文章:
这是一个很好的决定避免使用混合内容,尤其是在设计大型架构时有很多类型扩展。将这种模式映射到任何结合框架通常是复杂的,并导致并发症和发展放缓。JAXB从未被设计用于处理这些案例-它是一个Java<->XML映射框架,并且不可能在层次结构中表示这种内容Java对象。
我完全同意马丁的观点。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.0或wsimport 2.1文档。这里有一个关于混合内容模型的链接,如果您在混合类型中使用xs:any,您可以对其进行调整
您可能需要考虑使用Eclipse生成所需内容。尽管您正在使用的xsd和wsdl不包括在问题中,但我提出了一个似乎有效的简单示例。我没有使用绑定文件,Eclipse中的向导选择了需要mixed的事实,因为XSD中的mixed="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;
}
}