【发布时间】:2023-04-01 00:17:01
【问题描述】:
TL;DR : 我尝试创建一个测试,该测试在 2 个不同的 SOAP 操作(saveUser 和 getUser)上执行 2 个 CXF 调用,但第二个失败,因为设置了 http 请求中的 SOAPAction作为“保存用户”而不是“获取用户”。 我找到了 2 个解决方案来解决这个问题,但我对它们并不完全满意。
配置
这是我的端点配置:
final JaxWsProxyFactoryBean jaxWsProxyFactory = new JaxWsProxyFactoryBean();
jaxWsProxyFactory.setServiceClass(Internal.class);
jaxWsProxyFactory.setAddress(backendUrl + "INTERNAL");
jaxWsProxyFactory.setFeatures(getFeatures());
final Internal portType = (Internal) jaxWsProxyFactory.create();
((BindingProvider) portType).getRequestContext().put("thread.local.request.context", "true");
((BindingProvider) portType).getRequestContext().put("schema-validation-enabled", "false");
这是我的用法:
internalBackendG5.saveUser(getRequest);
internalBackendG5.getUser(saveRequest);
这两个操作被定义为(感谢 wsdl2java):
(为了更简洁,我重写了一些包,下面的代码可能包含错字)
@WebMethod(action = "http://www.test.org/internal/saveUser")
@WebResult(name = "saveUserResponse", targetNamespace = "urn:test.com:xsd:internal:userpreferences", partName = "parameters")
public com.test.internal.type.SaveUserResponseType saveUser(
@WebParam(partName = "parameters", name = "saveUser", targetNamespace = "urn:test.com:xsd:internal:userpreferences")
com.test.internal.type.SaveUserRequestType parameters
);
和
@WebMethod(action = "http://www.test.org/internal/getUser")
@WebResult(name = "getUserResponse", targetNamespace = "urn:test.com:xsd:internal:userpreferences", partName = "parameters")
public com.test.internal.type.GetUserResponseType getUser(
@WebParam(partName = "parameters", name = "getUser", targetNamespace = "urn:test.com:xsd:internal:userpreferences")
com.test.internal.type.GetUserRequestType parameters
);
运行时
当我运行我的测试时,我在第二次调用时收到一个错误,该错误是作为 Soap 异常从后端抛出的:
javax.xml.ws.soap.SOAPFaultException: Unexpected element {urn:test.com:xsd:internal:userpreferences}getUser found. Expected {urn:test.com:xsd:internal:userpreferences}saveUser.
当我查看服务器收到的 Soap 请求时,我得到:
对于第一个请求(saveUser):
Headers: {[...] SOAPAction=["http://www.test.org/internal/saveUser"], user-agent=[Apache CXF 2.7.12]}
Payload: <soap:Envelope><soap:Body><saveUser>[...]</ns5:saveUser></soap:Body></soap:Envelope>
对于第二个请求(getUser):
Headers: {[...] SOAPAction=["http://www.test.org/internal/saveUser"], user-agent=[Apache CXF 2.7.12]}
Payload: <soap:Envelope><soap:Body><getUser>[...]</getUser></soap:Body></soap:Envelope>
当我只启动两个请求中的一个时,它们都可以工作。
我找到的解决方案
经过一番研究,我发现 Apache Cxf 拦截器 SoapPreProtocolOutInterceptor 是负责任的。
当请求中已经存在 SoapAction 字符串时,它不会覆盖它。我的第二次调用(由于某些原因我无法解释)重用了在处理第一次调用时计算的 Cxf 请求上下文!
我做了什么来克服这个问题: - 在 SoapPreProtocolOutInterceptor 之前编写一个拦截器,强制在标头中删除 SoapAction,以强制此拦截器重新计算操作。 - 或者,我可以重置 2 个请求之间的请求上下文:
((BindingProvider) portType).getRequestContext().put(Header.HEADER_LIST, emptyList);
问题
所以我的问题是:是否存在 CXF 错误?(requestContext 不应在 2 个请求之间共享)或 我错过了一些 Cxf 配置?
PS:我使用了这个依赖项:
group:'org.apache.cxf', name:'cxf-rt-transports-http-jetty', version:'2.7.5'
group: 'org.apache.cxf', name: 'cxf-rt-features-clustering', version:'2.7.12'
group:'org.apache.cxf', name:'cxf-rt-frontend-jaxws', version:'2.7.12'
group: 'org.apache.cxf', name: 'cxf-api', version: '2.7.12'
group: 'org.apache.cxf', name: 'cxf-rt-bindings-soap', version: '2.7.12'
提前致谢!
【问题讨论】:
-
遇到一个非常相似的问题,也许这是cxf中的一个错误?你有没有确定是否是这种情况?
-
不,很抱歉,我的时间很短,并使用我自己的解决方案,如上面的帖子中所述。但如果有人找到答案,我会很感兴趣!
-
供将来参考,当您使用 CXF 时,所有依赖项的版本都应匹配。我遇到了同样的问题,我(最初)通过固定所有版本的 cxf 来解决。
标签: java soap http-headers cxf