在Netbeans中生成的Java web服务客户端-获取Http状态代码307



我使用Netbeans生成web服务客户端代码,即客户端风格的JAX-WS,这样我就可以调用web服务API。

然而,当我调用web服务API时,我会得到一个异常:com.sun.xml.internal.ws.client.ClientTransportException:服务器发送HTTP状态代码307:临时重定向

为什么我会得到这个?解决方法是什么?我知道问题不在于web服务本身,因为我可以通过soapUI和.Net获得良好的响应。

大约一个月前也遇到了同样的问题。

Web服务客户端类是使用Apache CXF生成的,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();

CCD_ 3应该返回既是CCD_;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的实例时,我们可以向它发送普通的HTTPPOST请求,模拟SOAP请求(尽管它看起来非常不正确和丑陋,但这在我的情况下有效,我在谷歌搜索时没有发现更好的东西),并检查web服务是否会发送重定向状态作为响应:

// 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,即该端口方法将向其发送SOAP请求的url,并如上所述发送纯HTTP POST请求。然后,它检查响应状态是否为307 - Temporary Redirect(也可以包括302或301等其他状态),如果是,则获取web服务重定向到的URL,并为指定端口设置新的端点

在我的例子中,这个checkRedirect方法对每个web服务端口接口调用一次,然后一切似乎都很好:

  1. 在类似http://example.com:50678/restOfUrl的url上检查重定向
  2. Web服务重定向到类似https://example.com:43578/restOfUrl的url(请注意,存在Web服务客户端身份验证)-端口的端点设置为该url
  3. 通过该端口执行的下一个web服务请求成功

免责声明:我对网络服务很陌生,由于缺乏这些问题的解决方案,这就是我所能做到的,所以如果这里有问题,请纠正我。

希望这能帮助

是的,我知道这篇文章很旧,但我也遇到过类似的错误,我想也许有人会从我的解决方案中受益
最困扰我的是:

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

这意味着一个不完整的响应标头。显然jax-ws会进行某种验证,其中也包括验证HTTP头。而我使用的服务器只是发送了一个空标头

在将'application/soap+xml'添加到Content-Type标头后,它就像一个符咒。

最新更新