TL;DR 出于某种原因,我无法在使用 CXF 的 Java 优先 Web 服务中解组一个相当简单的对象。
我有一个 Java-First CXF Web 服务,其 API 类似于:
@WebMethod
public SearchResponse search(@WebParam(name = "searchRequest") SearchRequest searchRequest);
响应(不会解组的类)大致是:
public class SearchResponse {
private List<SearchResult> results;
public List<SearchResult> getResults() {
return results;
}
public void setResults(List<SearchResult> results) {
this.results = results;
}
}
SearchResult 是一个非常简单的两个属性类:
public class SearchResult {
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我可以通过 Soap-UI 调用此服务,它运行良好。但是,当我使用 jaxws 客户端调用时,出现错误:
javax.xml.ws.soap.SOAPFaultException: Unmarshalling Error: null
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:143)
at $Proxy67.search(Unknown Source)
at com.blah.MyTest.curseYouSearch(MyTest.java:76)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:131)
at java.util.AbstractList.add(AbstractList.java:91)
at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:290)
at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:254)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Scope.add(Scope.java:106)
at com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty$ReceiverImpl.receive(ArrayERProperty.java:195)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(UnmarshallingContext.java:524)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleEndElement(StAXStreamConnector.java:206)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:170)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:351)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:330)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:610)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:530)
at org.apache.cxf.jaxb.io.DataReaderImpl.read(DataReaderImpl.java:114)
at org.apache.cxf.interceptor.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:99)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:236)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:658)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:2139)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:2022)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1947)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:66)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:632)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:236)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:472)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:302)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:254)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:123)
... 24 more
我可以在 AbstractList.add 上设置一个断点,并根据生成的堆栈,似乎解组正在尝试添加到空列表中,这当然是不可变的:
Thread [main] (Suspended (breakpoint at line 131 in AbstractList))
Collections$EmptyList(AbstractList<E>).add(int, E) line: 131
Collections$EmptyList(AbstractList<E>).add(E) line: 91
Lister$CollectionLister<BeanT,T>.addToPack(T, Object) line: 290
Lister$CollectionLister<BeanT,T>.addToPack(Object, Object) line: 254
Scope<BeanT,PropT,ItemT,PackT>.add(Accessor<BeanT,PropT>, Lister<BeanT,PropT,ItemT,PackT>, ItemT) line: 106
ArrayERProperty$ReceiverImpl.receive(UnmarshallingContext$State, Object) line: 195
UnmarshallingContext.endElement(TagName) line: 524
StAXStreamConnector.handleEndElement() line: 206
StAXStreamConnector.bridge() line: 170
UnmarshallerImpl.unmarshal0(XMLStreamReader, JaxBeanInfo) line: 351
UnmarshallerImpl.unmarshal(XMLStreamReader, Class<T>) line: 330
JAXBEncoderDecoder.unmarshall(Unmarshaller, Object, QName, Class<?>, boolean) line: 610
JAXBEncoderDecoder.unmarshall(Unmarshaller, Object, MessagePartInfo, boolean) line: 530
DataReaderImpl<T>.read(MessagePartInfo, T) line: 114
DocLiteralInInterceptor.handleMessage(Message) line: 99
PhaseInterceptorChain.doIntercept(Message) line: 236
ClientImpl.onMessage(Message) line: 658
HTTPConduit$WrappedOutputStream.handleResponseInternal() line: 2139
HTTPConduit$WrappedOutputStream.handleResponse() line: 2022
HTTPConduit$WrappedOutputStream.close() line: 1947
HTTPConduit(AbstractConduit).close(Message) line: 66
HTTPConduit.close(Message) line: 632
MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(Message) line: 62
PhaseInterceptorChain.doIntercept(Message) line: 236
ClientImpl.invoke(BindingOperationInfo, Object[], Map<String,Object>, Exchange) line: 472
ClientImpl.invoke(BindingOperationInfo, Object[], Exchange) line: 302
ClientImpl.invoke(BindingOperationInfo, Object...) line: 254
JaxWsClientProxy(ClientProxy).invokeSync(Method, BindingOperationInfo, Object[]) line: 73
JaxWsClientProxy.invoke(Object, Method, Object[]) line: 123
...endless stack lines omitted...
我的客户端在 Spring 中设置为 jaxws:client:
<jaxws:client id="searchServiceClient"
serviceClass="qualified.class.of.Service"
address="${url.searchService}">
</jaxws:client>
我们有许多其他 Web 服务以非常相似的方式返回 List 并且工作正常;我有点不知所措,这与这个有什么区别。
该系统使用 Java 6、CXF 2.2.3。
任何建议都将受到欢迎。