在给定SOAP头元素具有给定值的情况下(例如,如果头标记“response”的值为“0”),我不希望Apache CXF返回响应。如何防止Apache CXF发送响应消息?
我该怎么做?看起来CXF认为所有的呼叫都会收到回应。我知道这在网络服务上下文中似乎很奇怪,但是如果你的传输是JMS,它似乎不太奇怪)。
在给定SOAP头元素具有给定值的情况下(例如,如果头标记“response”的值为“0”),我不希望Apache CXF返回响应。如何防止Apache CXF发送响应消息?
我该怎么做?看起来CXF认为所有的呼叫都会收到回应。我知道这在网络服务上下文中似乎很奇怪,但是如果你的传输是JMS,它似乎不太奇怪)。
我已经能够用拦截拦截器链的拦截器来做到这一点。
我已经用HTTP配置(WebSphere返回一个空的200)和一个ActiveMQ配置(没有响应返回到响应队列)来测试它。
package my.super.interceptor;
public final class Suppressor extends AbstractSoapInterceptor {
public Suppressor() { super(Phase.SETUP); }
@Override
public void handleMessage(final SoapMessage message) throws Fault
{
final boolean suppressResponse = this.suppressResponse(message);
if(suppressResponse) {
log.debug("-> Suppressing response");
message.getInterceptorChain().abort();
}
//if you want to suppress both responses and faults, you need
//to check them separately.
//Change this code to check headers for whatever criteria you want
//(Note you may need to change the super(Phase...))
//The code's a bit messy here - just sketching out the idea for the answer
private boolean suppressResponse(final Message message) {
final Fault fault = (Fault)message.getContent(Exception.class);
if(fault != null) {
final String faultMessage = fault.getMessage();
return faultMessage.indexOf("Something-you-want-to-match") > 0;
} else {
final MessageInfo messageInfo = (MessageInfo)message.get("org.apache.cxf.service.model.MessageInfo");
final String operation = messageInfo.getOperation().getOutputName();
return operation.indexOf("Something-you-want-to-match") > 0;
}
}
和你的applicationContext.xml:
<jaxws:endpoint ...>
<jaxws:outInterceptors>
<bean class="my.super.interceptor.Suppressor"/>
</jaxws:outInterceptors>
<jaxws:outFaultInterceptors>
<bean class="my.super.interceptor.Suppressor"/>
</jaxws:outFaultInterceptors>
</jaxws:endpoint>
长解释:根据SOAP协议规范思考SOAP Web服务。 Web服务不仅仅是HTTP上的一个花哨层,它实际上是一种描述实现的各种message exchange patterns的双向通信的方式。下面的模式是最常见的:
请求 - 响应(输入 - 输出):在HTTP环境中,这是一个典型的HTTP请求/响应呼叫与一些请求消息从客户机发送给服务器并回复消息。在JMS环境中,您将获得两个独立且独立的消息。
单向(In-Only):在此模型中,客户端发送请求,但不期望也不关心响应。在JMS中,它相当于发送给代理的简单消息。另一方面,在HTTP中(至少这是在Apache CXF中如何实现单向方法),您将在SEI上获得void
方法。此外,CXF默认会使用单独的线程池来处理此请求,因此客户端甚至不会等待响应,并且服务器甚至无法发送该响应(因为客户端可能已经断开连接)。
现在重要的部分:在WSDL你要么定义方法请求/响应(通过输入/输出消息定义)或单向的(仅在消息提供)。这在服务合同中得到了解决。你不能做出一种方法,一旦返回响应(out消息准确),而其他时间则不会。
很明显,您可以定义一个可以为空或包含某些内容的外出消息,但仍然必须返回一些内容。
简短解释:SOAP协议不够灵活,无法满足您的要求。您要么返回一个响应,要么不。创建两个方法,并选择在客户端调用哪一个,而不是添加自定义标头。
另一个提示:您可能会使用ESB执行某种转换,以便在某个SOAP标头出现时放弃响应。
@Jared:我基本同意Tomasz的解释。我能想到的一种解决方法是让我们说如果使用ws-addressing。 Ws-addressing允许你指定<ReplyTo> and <To>
。因此,基本上,在情况下,您不希望将响应发送给请求的客户端,服务器端代码可以更改replyTo字段的值,并可以向虚拟URI发送响应。
对于您的特定情况,我认为正确的实施方式是使用两种操作。一个用于in-only,另一个用于in-out。
您尝试实施它的方式也可能在客户端导致问题。现在客户必须根据请求决定是否查找响应。另一方面,由于决定取自客户端客户端发送的值,因此可以决定调用in-only或in-out操作。
我想过使用重复的操作定义(一个请求 - 响应定义和单向定义),但这不能很好地扩展到几十数百种服务(它使您必须实施的服务数量翻倍)。 – Jared
我也考虑过基于ESB的解决方案,但重点在于消除发布响应的额外开销。我仍然会将响应推送到ESB层,以便放弃它们。 – Jared