2011-09-27 57 views
3

在给定SOAP头元素具有给定值的情况下(例如,如果头标记“response”的值为“0”),我不希望Apache CXF返回响应。如何防止Apache CXF发送响应消息?

我该怎么做?看起来CXF认为所有的呼叫都会收到回应。我知道这在网络服务上下文中似乎很奇怪,但是如果你的传输是JMS,它似乎不太奇怪)。

回答

3

我已经能够用拦截拦截器链的拦截器来做到这一点。

我已经用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> 
1

长解释:根据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标头出现时放弃响应。

+0

我想过使用重复的操作定义(一个请求 - 响应定义和单向定义),但这不能很好地扩展到几十数百种服务(它使您必须实施的服务数量翻倍)。 – Jared

+0

我也考虑过基于ESB的解决方案,但重点在于消除发布响应的额外开销。我仍然会将响应推送到ESB层,以便放弃它们。 – Jared

0

@Jared:我基本同意Tomasz的解释。我能想到的一种解决方法是让我们说如果使用ws-addressing。 Ws-addressing允许你指定<ReplyTo> and <To>。因此,基本上,在情况下,您不希望将响应发送给请求的客户端,服务器端代码可以更改replyTo字段的值,并可以向虚拟URI发送响应。

0

对于您的特定情况,我认为正确的实施方式是使用两种操作。一个用于in-only,另一个用于in-out。

您尝试实施它的方式也可能在客户端导致问题。现在客户必须根据请求决定是否查找响应。另一方面,由于决定取自客户端客户端发送的值,因此可以决定调用in-only或in-out操作。