1

我使用NetBeans生成的Web服務客戶端代碼,客戶端式的JAX-WS,這樣我就可以調用Web服務的API。的Java Web服務客戶端 - 讓Http狀態代碼307

然而,當我調用Web服務API,我得到異常: com.sun.xml.internal.ws.client.ClientTransportException:服務器發送HTTP狀態碼307:臨時重定向

我爲什麼得到這個?什麼是解決方法?我知道問題不在Web服務本身,因爲我可以通過soapUI和.Net很好地得到響應。

回答

0

面對大約一個月前同樣的問題。使用Apache CXF生成

Web服務客戶端類和Web服務返回的HTTP 狀態307,這就導致了同樣的異常。

使用soapUI屬性Follow Redirects設置爲true的相同Web服務方法的調用已成功並返回了所需的數據。

一段時間谷歌搜索後,它看起來像有沒有財產,使下面的JAX-WS重定向這一點。

所以,下面是當前工作的代碼,雖然我不知道這是符合任何標準:

假設生成的客戶端類的樣子:現在

// generated service class 
public class MyWebServiceClient extends javax.xml.ws.Service { 
    // ... 
    private final QName portName = "..."; 
    // ... 
    public RetrieveMyObjects getRetrieveMyObjects() { 
     return super.getPort(portName, RetrieveMyObject.class); 
    } 
    // ... 
} 

// generated port interface 
// annotations here 
public interface RetrieveMyObjects { 

    // annotations here 
    List<MyObject> getAll(); 

} 

,在執行下面的代碼:

MyWebServiceClient wsClient = new MyWebServiceClient("wsdl/location/url/here.wsdl"); 
RetrieveMyObjectsPort retrieveMyObjectsPort = wsClient.getRetrieveMyObjects(); 

wsClient應該返回實例,它是RetrieveMyObjects兩個實例3210 javax.xml.ws.BindingProvider接口。它在JAX-WS的表面沒有任何地方,但是似乎很多代碼都是基於這個事實。我們可以再保證他\她通過執行類似:

if(!(retrieveMyObjectsPort instanceof javax.xml.ws.BindingProvider)) { 
    throw new RuntimeException("retrieveMyObjectsPort is not instance of " + BindingProvider.class + ". Redirect following as well as authentication is not possible"); 
} 

現在,當我們確信retrieveMyObjectsPortjavax.xml.ws.BindingProvider例如,我們可以把普通的HTTP POST請求給它,模擬SOAP請求(雖然它看起來令人難以置信不正確&難看,但這部作品在我的情況,我沒有找到更好的東西,而谷歌搜索),並檢查網絡服務是否將發送重定向狀態作爲響應:

// defined somewhere before 
private static void checkRedirect(final Logger logger, final BindingProvider bindingProvider) { 
    try { 
     final URL url = new URL((String) bindingProvider.getRequestContext().get(ENDPOINT_ADDRESS_PROPERTY)); 
     logger.trace("Checking WS redirect: sending plain POST request to {}", url); 
     final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
     connection.setInstanceFollowRedirects(true); 
     connection.setRequestMethod("POST"); 
     connection.setRequestProperty("Content-Type", "text/html; charset='UTF-8'"); 
     connection.setDoOutput(true); 

     if(connection.getResponseCode() == 307) { 
      final String redirectToUrl = connection.getHeaderField("location"); 
      logger.trace("Checking WS redirect: setting new endpoint url, plain POST request was redirected with status {} to {}", connection.getResponseCode(), redirectToUrl); 
      bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, redirectToUrl); 
     } 
    } catch(final Exception e) { 
     logger.warn("Checking WS redirect: failed", e); 
    } 
} 

// somewhere at the application start 
checkRedirect(logger, (BindingProvider) retrieveMyObjectsPort); 

現在,這個方法的作用是:它需要的retrieveMyObjectsPortBindingProvider.ENDPOINT_ACCESS_PROPERTY即網址whic h此端口方法將發送SOAP請求併發送如上所述的普通HTTP POST請求。然後它檢查響應狀態是否爲307 - Temporary Redirect(其他狀態等302或301也可以被包括在內),並且如果它是,獲取的URL的web服務被重定向,其並設置新的端點爲指定的端口。

在我的情況下,該checkRedirect方法爲每個Web服務端口接口調用一次,然後一切似乎很好地工作:

  1. 重定向是在URL檢查像http://example.com:50678/restOfUrl
  2. Web服務重定向到URL像https://example.com:43578/restOfUrl (請注意,存在Web服務客戶端身份驗證) - 端口的端點設置爲該URL
  3. 通過該端口執行的下一個Web服務請求成功執行

聲明:我對web服務相當陌生,這是我成功實現的,由於缺乏針對此問題的解決方案,所以如果出現問題,請糾正我的錯誤。

希望這有助於

0

是的,我知道這個帖子是老了,但我已經有類似的錯誤,也許想到有人會從我的解決方案中受益。
的一個困擾我最多的是:這原來是說一個不完整的響應頭

com.sun.xml.ws.client.ClientTransportException: The server sent HTTP status code 200: OK 

。顯然,jax-ws會進行一些驗證,包括驗證HTTP頭。而我使用的服務器只是發送一個空頭。

它的工作就像一個魅力加'application/soap+xml'Content-Type頭之後。