В веб-службе JAX-WS как принудительно закрыть сокет после каждого вызова Soap? - PullRequest
4 голосов
/ 16 сентября 2011

Я использую com.sun.httpserver.HttpServer и javax.xml.ws.Endpoint для публикации веб-службы JAX-WS, которая была сгенерирована путем запуска wsimport на существующем WSDL и реализации созданного интерфейса службы. Все это было частью JDK 1.6 (JAX-WS RI 2.1.6). Предполагается, что мой веб-сервис, работающий как Java-программа без дополнительного веб-контейнера, имитирует существующий сервис SOAP, который был реализован с использованием Apache Axis, работающего на Tomcat. Существующие клиенты также реализованы с использованием Apache Axis.

Проблема, с которой я столкнулся, заключается в том, что вызовы операций Soap от клиентов к моей службе JAX-WS на некоторое время зависают, а затем заканчиваются тайм-аутом сокета на стороне клиента. Это происходит, даже если служба JAX-WS сразу же возвращает ответ SOAP.

Проверяя пакеты с помощью tcpdump и wireshark, я заметил, что с существующим веб-сервисом Axis после отправки ответа SOAP с сервера на клиент сервер отправляет пакет «FIN ACK», на который клиенты отвечают "FIN ACK". На этом завершаются все пакеты, относящиеся к операции SOAP. С другой стороны, при работе со службой JAX-WS сервер не отправляет «FIN ACK» после отправки ответа SOAP клиенту. И клиент, кажется, продолжает читать поток ввода сокета для него.

Это наводит меня на мысль, что стек веб-службы JAX-WS каким-то образом сохраняет сокет открытым даже после отправки ответа на вызов SOAP. И кажется, что клиент ожидает закрытия сокета в конце операции SOAP. К сожалению, я не могу изменить клиента так, чтобы он вел себя по-другому.

Есть ли способ настроить экземпляры Endpoint или HttpServer, которые я использую для публикации службы JAX-WS, чтобы всегда закрывать сокет после каждой операции SOAP?

Я попытался установить для системного свойства http.keepAlive значение false, но, похоже, это не имело никакого значения.

Заранее спасибо за помощь.

1 Ответ

2 голосов
/ 19 сентября 2011

Я нашел способ обойти эту проблему, но она не очень элегантна. По сути, я получаю объект HttpHandler из HttpContext после того, как он был создан операцией Endpoint.publish. И я вызываю его метод handle () из другого написанного мною класса HttpHandler, который затем отправляет HttpHeader с параметром «Connection», установленным в «close». Примерно так:

  ...
  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();
    }
  }

Это работает для моих текущих нужд, но кажется, что должен быть лучший способ. Пожалуйста, пишите, если у вас есть другое решение. Спасибо!

...