开发者

In a JAX-WS web service, how do I force a socket close after each Soap call is returned?

I am using com.sun.httpserver.HttpServer and javax.xml.ws.Endpoint to publish a JAX-WS web service, which was generated by running wsimport on an existing WSDL and implementing the genere开发者_JAVA技巧ated service interface. All this was part of JDK 1.6 (JAX-WS RI 2.1.6). My web service, running as a Java program without an additional Web container is supposed to simulate an existing SOAP service that was implemented using Apache Axis, running on Tomcat. Existing clients are likewise implemented using Apache Axis.

The problem I am having is that Soap operation calls from the clients to my JAX-WS service hang for a while, and then end with socket time-out on the client's side. This occurs even though the JAX-WS service is returning the SOAP response right away.

Inspecting the packets with tcpdump and wireshark, I noticed that with the existing Axis web service, after the SOAP response is sent from the server to the client, the server sends a "FIN ACK" packet, to which the clients responds with "FIN ACK". This concludes all packets pertinent to the SOAP operation. On the other hand, when running with the JAX-WS service, the server does not send a "FIN ACK" after the SOAP response is sent to the client. And the client seems to continue reading the socket input stream for it.

This leads me to believe that the JAX-WS web service stack is somehow keeping the socket open, even after the response to a SOAP call has been sent. And it appears that the client is expecting the socket to close at the end of a SOAP operation. Unfortunately, I cannot modify the client to behave differently.

Is there a way to configure the Endpoint or the HttpServer instances that I am using to publish the JAX-WS service to always close a socket after each SOAP operation?

I tried setting the system property http.keepAlive to false, but this did not seem to make any difference.

Thanks in advance for your help.


I found a way around this problem, but it's not very elegant. Essentially I get the HttpHandler object from the HttpContext after it's been created by the Endpoint.publish operation. And I call its handle() method from another HttpHandler class I wrote, which follows it up by sending a HttpHeader with "Connection" set to "close". Something like this:

  ...
  HttpServer server = HttpServer.create(myInetSocketAddress, 5);
  HttpContext context = server.createContext(mySoapPath);
  Endpoint endpoint = Endpoint.create(mySoapImpl);
  endpoint.publish(context);

  MyHandler handler = new MyHandler(context.getHandler());
  server.removeContext(mySoapPath);
  server.createContext(mySoapPath, handler);
  server.start();
  ...

  private class MyHandler implements HttpHandler {
    private HttpHandler h;
    public MyHandler(HttpHandler in) {
      h = in;
    }
    public void handle(HttpExchange t) throws IOException {
      h.handle(t);
      t.getResponseHeaders().set("Connection", "close");
      t.sendResponseHeaders(200, 0);
      t.close();
    }
  }

It works for my current needs, but it just seems like there's got to be a better way. Please do post if you have another solution. Thanks!


When I had this problem in Java 8 all requests from JAX-WS RI 2.2.9 had header: Connection: keep-alive

To force closing TCP connection after each request I had to change this header to Connection: close

I had done it by:

SoapService service = new SoapService(url);
SoapPort port = service.getSomePort();

Map<String, List<String>> requestHeaders = new HashMap<>();
requestHeaders.put("Connection", Collections.singletonList("close"));
BindingProvider bindingProvider = (BindingProvider)port;
bindingProvider.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);

where:

public static final String HTTP_REQUEST_HEADERS = "javax.xml.ws.http.request.headers";
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜