2016-01-20 81 views
2

我們有一個基於Spring WS的(工作)SOAP Web服務,其中DefaultWsdl11DefinitionSpring WS(DefaultWsdl11Definition)HTTP狀態碼,無效

這基本上是什麼樣子:

@Endpoint("name") 
public class OurEndpoint { 

    @PayloadRoot(namespace = "somenamespace", localPart = "localpart") 
    public void onMessage(@RequestPayload SomePojo pojo) { 
     // do stuff 
    } 
} 

它是有線在春天,它是正確處理所有的SOAP請求。唯一的問題是該方法返回202接受。這是而不是呼叫者需要什麼,他寧願讓我們返回204否內容(或者如果那是不可能的空的200行)。

我們的其他端點有一個有效的響應對象,並返回200 OK。看來無效原因當可能更合適?

是否有可能在Spring WS中更改響應代碼?我們似乎無法找到正確的方法來做到這一點。

東西,我們嘗試和沒有工作:

  • 更改返回類型:
    • HttpStatus.NO_CONTENT
    • org.w3c.dom.Element中< - 不接受
  • 加入@ResponseStatus < - 這是爲MVC,而不是WS

任何想法?

+0

202表示請求已被接受但處理未完成。我想這是由於'void'返回類型,因此DefaultMethodEndpointAdapter不會調用'handleMethodReturnValue',因爲沒有什麼可處理的。我想最簡單的方法返回200(或其他)是創建一個自定義的'SoapMessageDispatcher'並重新實現'receive'方法。您可能需要複製整個類(層次結構),因爲該類非常封閉(最終方法)。 –

回答

0

當發現我們確實遇到了一些醜陋的問題適當的解決辦法:

  • 創建自定義適配器/攔截器是有問題的,因爲用handleResponse方法不受春天調用時你沒有響應(無效)
  • 手動設置狀態碼不起作用,因爲HttpServletConnection保持一個布爾statusCodeSet它沒有更新

但幸運的是,我們設法得到它具有以下變化工作:

<sws:interceptors> 
    <bean class="com.something.NoContentInterceptor"/> 
</sws:interceptors> 

非常感謝:

/** 
* If a web service has no response, this handler returns: 204 No Content 
*/ 
public class NoContentInterceptor extends EndpointInterceptorAdapter { 

    @Override 
    public void afterCompletion(MessageContext messageContext, Object o, Exception e) throws Exception { 
     if (!messageContext.hasResponse()) { 
      TransportContext tc = TransportContextHolder.getTransportContext(); 
      if (tc != null && tc.getConnection() instanceof HttpServletConnection) { 
       HttpServletConnection connection = ((HttpServletConnection) tc.getConnection()); 
       // First we force the 'statusCodeSet' boolean to true: 
       connection.setFaultCode(null); 
       // Next we can set our custom status code: 
       connection.getHttpServletResponse().setStatus(204); 
      } 
     } 
    } 
} 

接下來我們需要註冊這個攔截器,這可以很容易地使用Spring的XML完成以@ m-deinum爲我們指引正確的方向!

0

而不是我在評論中寫的,它可能是最容易創建一個委託類型的解決方案。

public class DelegatingMessageDispatcher extends MessageDispatcher { 
    private final WebServiceMessageReceiver delegate; 

    public DelegatingMessageDispatcher(WebServiceMessageReceiver delegate) { 
     this.delegate = delegate; 
    } 

    public void receive(MessageContext messageContext) throws Exception { 
     this.delegate.receive(messageContext); 
     if (!messageContext.hasResponse()) { 
      TransportContext tc = TransportContextHolder.getTransportContext(); 
      if (tc != null && tc.getConnection() instanceof HttpServletConnection) { 
       ((HttpServletConnection) tc.getConnection()).getHttpServletResponse().setStatus(200); 
      } 
     } 
    } 
} 

然後,你需要配置一個名爲messageDispatcher這將包裹默認SoapMessageDispatcher豆。

@Bean 
public MessageDispatcher messageDispatcher() { 
    return new DelegatingMessageDispatcher(soapMessageDispatcher()); 
} 

@Bean 
public MessageDispatcher soapMessageDispatcher() { 
    return new SoapMessageDispatcher(); 
} 

像這樣的事情應該做的伎倆。現在,當創建響應時(在返回類型爲空的情況下),您想要的狀態將發送回客戶端。

+0

提供的解決方案並不完全正常,主要原因是HttpServletConnection中的'statusCodeSet'字段爲假(即使我們手動設置)。但是你已經幫助我朝着正確的方向發展,我很快就會發佈一個工作版本! –