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头之后。