背景
我正在使用wsimport来创建本质上是一个Java Web服务客户端,连接到返回数据集的.Net webservice(不幸的是) . 更具体地说,我正在为ESRI ArcGIS Server 10.2的GeoEvent处理器套件开发项目(入站传输),但我认为这可以通过与JAXB和WSDL绑定相关的更一般的术语来回答 . 跟我在一起,因为大学以来我没有接触过Java(10年) .
出于WSDL的目的,.Net DataSet是一种多态类型,其实际布局直到运行时才确定,在DataSet填充数据之后 . 当您想要将该Web服务与除.Net之外的任何内容一起使用时,这会导致问题 .
经过一些研究后,我设法使用 wsimport 从webservice wsdl生成 . 然后,我能够将基于Web服务的结果作为DOM的基本概念验证程序放在一起,然后将该DOM作为节点列表 .
参考:
-
JAX-WS error on WSDL file: "Error resolving component 's:schema'"
-
https://weblogs.java.net/blog/vivekp/archive/2007/05/how_to_deal_wit_1.html
-
关于Toolkit Bindings的部分和http://msdn.microsoft.com/en-us/magazine/cc188755.aspx中的图6
我的wsimport看起来像这样(域名已被更改以保护无辜者):
C:\Development\ArcGIS\WSDL>wsimport -b http://www.w3.org/2001/XMLSchema.xsd -b xsd.xjb -keep -p com.somecompany.services -XadditionalHeaders http://services.somecompany.com/DataRetrieval.asmx?wsdl
问题
不幸的是,一旦我在ArcGIS GeoEvent处理器中实现,在我的概念验证中起作用的相同代码库,从Web服务获取结果就失败了 . 我的项目是ArcGIS GeoEvent处理器将控制的OSGI包的一部分 . 下面的错误如GeoEvent处理器的Apache Karaf日志中所示 .
根据错误,我的理解是我在wsimport中如何进行绑定存在问题,引用我上面列出的那些链接的通用模式 . 看起来通用模式缺少对由wsimport生成的类存在的某些元素的定义 . 当我检查wsimport的输出时,这些类看起来是正确生成的 .
由于发布限制,我没有包含WSDL,但如果需要,将包含在以后的响应中 .
我想弄清楚的是什么
-
如何解释此错误?
-
为什么在ArcGIS GeoEvent处理器中运行时,在我的基本概念验证中用于访问Web服务的相同wsimport生成代码会失败?
-
该错误提到了JAXB和SAX,我没有有意识地在概念验证或ArcGIS GeoEvent处理器项目中引用这些库中的任何一个 . 是否可以通过不同的方式处理Web服务的绑定/解组,使用ArcGIS GeoEvent处理器包装在JAXB / SAX中并且概念证明不是?
-
我该怎么做才能解决这个问题?
使用不同的自定义xsd和xjb来说明Web服务的预期模式?我不确定如何做到这一点 . 使用wsimport以外的东西来生成webservice引用类?在Java环境中为ArcGIS GeoEvent处理器调整一些东西?其他选择?提交seppuku,那不是我的问题吗?
错误
2014-09-23 16:10:14,365 | ERROR | ansport Listener | SomeInboundTransport | 367 - com.somecompany.arcgis.geoevent.transport.inbound.somecompanyInboundTransport - 1.0.0 | Unable to call Webservice
javax.xml.ws.soap.SOAPFaultException: Unmarshalling Error: unexpected element (uri:"http://www.w3.org/2001/XMLSchema", local:"element"). Expected elements are <{http://services.somecompany.com/}complexType>,<{http://services.somecompany.com/}annotation>,<{http://services.somecompany.com/}redefine>,<{http://services.somecompany.com/}element>,<{http://services.somecompany.com/}include>,<{http://services.somecompany.com/}attributeGroup>,<{http://services.somecompany.com/}group>,<{http://services.somecompany.com/}notation>,<{http://services.somecompany.com/}import>,<{http://services.somecompany.com/}simpleType>,<{http://services.somecompany.com/}attribute>
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)[120:org.apache.cxf.cxf-rt-frontend-jaxws:2.6.1]
at com.sun.proxy.$Proxy198.getCompanyArcgisData(Unknown Source)[367:com.somecompany.arcgis.geoevent.transport.inbound.somecompanyInboundTransport:1.0.0]
at com.somecompany.arcgis.geoevent.transport.inbound.SomeInboundTransport.callWebService(SomeInboundTransport.java:184)[367:com.somecompany.arcgis.geoevent.transport.inbound.somecompanyInboundTransport:1.0.0]
at com.somecompany.arcgis.geoevent.transport.inbound.SomeInboundTransport.run(SomeInboundTransport.java:257)[367:com.somecompany.arcgis.geoevent.transport.inbound.somecompanyInboundTransport:1.0.0]
at java.lang.Thread.run(Thread.java:722)[:1.7.0_17]
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[com.sun.istack.SAXParseException2; lineNumber: 1; columnNumber: 651; unexpected element (uri:"http://www.w3.org/2001/XMLSchema", local:"element"). Expected elements are <{http://services.somecompany.com/}complexType>,<{http://services.somecompany.com/}annotation>,<{http://services.somecompany.com/}redefine>,<{http://services.somecompany.com/}element>,<{http://services.somecompany.com/}include>,<{http://services.somecompany.com/}attributeGroup>,<{http://services.somecompany.com/}group>,<{http://services.somecompany.com/}notation>,<{http://services.somecompany.com/}import>,<{http://services.somecompany.com/}simpleType>,<{http://services.somecompany.com/}attribute>]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:425)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:362)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:339)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.doUnmarshal(JAXBEncoderDecoder.java:784)[91:org.apache.cxf.cxf-rt-databinding-jaxb:2.6.1]
at org.apache.cxf.jaxb.JAXBEncoderDecoder.access$100(JAXBEncoderDecoder.java:97)[91:org.apache.cxf.cxf-rt-databinding-jaxb:2.6.1]
at org.apache.cxf.jaxb.JAXBEncoderDecoder$1.run(JAXBEncoderDecoder.java:812)
at java.security.AccessController.doPrivileged(Native Method)[:1.7.0_17]
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:810)[91:org.apache.cxf.cxf-rt-databinding-jaxb:2.6.1]
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:644)[91:org.apache.cxf.cxf-rt-databinding-jaxb:2.6.1]
at org.apache.cxf.jaxb.io.DataReaderImpl.read(DataReaderImpl.java:157)[91:org.apache.cxf.cxf-rt-databinding-jaxb:2.6.1]
at org.apache.cxf.interceptor.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:108)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:798)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1667)[118:org.apache.cxf.cxf-rt-transports-http:2.6.1]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1520)[118:org.apache.cxf.cxf-rt-transports-http:2.6.1]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1428)[118:org.apache.cxf.cxf-rt-transports-http:2.6.1]
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:658)[118:org.apache.cxf.cxf-rt-transports-http:2.6.1]
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:532)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:464)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:367)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:320)[87:org.apache.cxf.cxf-api:2.6.1]
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:89)[119:org.apache.cxf.cxf-rt-frontend-simple:2.6.1]
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)[120:org.apache.cxf.cxf-rt-frontend-jaxws:2.6.1]
... 4 more
Caused by: com.sun.istack.SAXParseException2; lineNumber: 1; columnNumber: 651; unexpected element (uri:"http://www.w3.org/2001/XMLSchema", local:"element"). Expected elements are <{http://services.somecompany.com/}complexType>,<{http://services.somecompany.com/}annotation>,<{http://services.somecompany.com/}redefine>,<{http://services.somecompany.com/}element>,<{http://services.somecompany.com/}include>,<{http://services.somecompany.com/}attributeGroup>,<{http://services.somecompany.com/}group>,<{http://services.somecompany.com/}notation>,<{http://services.somecompany.com/}import>,<{http://services.somecompany.com/}simpleType>,<{http://services.somecompany.com/}attribute>
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:254)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:249)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:116)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.childElement(Loader.java:101)
at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.childElement(StructureLoader.java:243)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:478)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:459)
at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleStartElement(StAXStreamConnector.java:242)
at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:176)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:360)
... 28 more
Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.w3.org/2001/XMLSchema", local:"element"). Expected elements are <{http://services.somecompany.com/}complexType>,<{http://services.somecompany.com/}annotation>,<{http://services.somecompany.com/}redefine>,<{http://services.somecompany.com/}element>,<{http://services.somecompany.com/}include>,<{http://services.somecompany.com/}attributeGroup>,<{http://services.somecompany.com/}group>,<{http://services.somecompany.com/}notation>,<{http://services.somecompany.com/}import>,<{http://services.somecompany.com/}simpleType>,<{http://services.somecompany.com/}attribute>
... 39 more
代码(片段)
import com.somecompany.services.*; //generated by wsimport
import javax.xml.ws.*;
//...
private com.somecompany.services.DataRetrieval myWS;
private com.somecompany.services.DataRetrievalSoap port;
private byte[] callWebService(String userName, String pwd, long dataTimeFrame)
{
try
{
myWS = new com.somecompany.services.DataRetrieval();
port = myWS.getDataRetrievalSoap();
com.somecompany.services.AuthSoapHeader mySoapHeader = new com.somecompany.services.AuthSoapHeader();
mySoapHeader.setUserName(userName);
//Hash the password then set it for the SOAP header
String pwdHash = hashMD5(pwd);
mySoapHeader.setPassword(pwdHash);
Holder holder = new Holder<AuthSoapHeader>(mySoapHeader);
Date endTime = new Date();
Date startTime = new Date(endTime.getTime() - dataTimeFrame);
XMLGregorianCalendar gcEndTime = dateToGregorianTime(endTime);
XMLGregorianCalendar gcStartTime = dateToGregorianTime(startTime);
GetCompanyArcgisDataResponse.GetCompanyArcgisDataResult companyData = port.getCompanyArcgisData(gcStartTime, gcEndTime, holder);
if( ((AuthSoapHeader)holder.value).getError() != null)
{
log.error("Authentication to web services failed!");
//OSGI stop service
this.stop();
return null;
}else
log.info("Authentication to web services successful.");
//Convert the results to a java object and then to a byte array to send to the adapter
Object companyDataAny = companyData.getAny();
byte[] companyDataBytes = objectToBytes(companyDataAny);
return companyDataBytes;
}
catch(Exception ex)
{
log.error("Unable to call Webservice", ex);
//OSGI stop service
this.stop();
return null;
}
}
环境细节
-
JDK 7u17(1.7.0_17)64位 . ArcGIS GeoEvent处理器正在使用这个版本的JRE,所以在我意识到之前,我已经在1.7.0_51中完成了一些开发 .
-
wsimport - JAX-WS RI 2.2.4-b01
-
ArcGIS Server 10.2
-
ArcGIS GeoEvent处理器扩展
-
Karaf(由ArcGIS Geovent处理器用于运行OSGI包)
1 回答
这可能不是最好的答案,但这是我提出的 .
包装我的OSGI项目的ArcGIS GeoEvent处理器似乎正在对我在应用程序中引用的Web服务进行一些额外的绑定/解除绑定 . 我用来使.Net(DataSet返回值)Web服务在Java中运行的解决方法对GeoEvent处理器的包装器来说是不可接受的 .
我的解决方案
最终我所做的是创建一个辅助.Net Web服务,它接受DataSet值并将它们转换为JSON,并返回JSON字符串 . 这消除了尝试从Web服务引用DataSet返回值时遇到的问题,现在我正在处理一个简单的JSON字符串 . 该JSON Web服务的 wsimport 顺利进行,无需解决方法 . 我将新导入的Web服务文件隐藏到我的java项目中,现在没有问题 .
对于C#DataSet的参考JSON:
使用Newtonsoft.Json(http://james.newtonking.com/json) . 在玩了一些JSON序列化的其他库后,我认为这对我来说最有效 .
Newtonsoft.Json可通过NuGet包获得
Rick Strahl的网站是一个很大的帮助http://weblog.west-wind.com/posts/2008/Sep/03/DataTable-JSON-Serialization-in-JSONNET-and-JavaScriptSerializer