Unmarshalling сокета InputStream закрывает сокет? - PullRequest
9 голосов
/ 23 июля 2011

У меня есть сервер-клиентская архитектура, где клиент отправляет XML на сервер, который читает его, генерирует из него PDF-файл и отправляет его обратно клиенту.

На стороне клиента:

JAXBElement<Xml> xml = ...
Socket sock = ...
Marshaller marshaller = ...
marshaller.marshal(xml, sock.getOutputStream());
sock.shutdownOuput();    

Между тем на стороне сервера:

ServerSocket server = ...
Socket client = server.accept();
Unmarshaller unmarshaller = ...
// client.isClosed() -> false
JAXBElement<Xml> xml =
  (JAXBElement<Xml>)) unmarshaller.unmarshall(client.getInputStream());
// client.isClosed() -> true
Pdf pdf = new Pdf(xml);
client.getOutputStream().write(pdf.toBytes());
// "socket is closed" IOException is thrown

Если я не отменю маршализацию InputStream (на стороне сервера) клиента и просто отправляю фиктивный PDF, тогда все идет гладко,Итак, я должен предположить, что Unmarshaller закрывает InputStream, который он дал, таким образом, неявно закрывая клиента Socket, разрушая мой день ...

Есть идеи по решению этого вопроса?

Ответы [ 2 ]

8 голосов
/ 23 июля 2011

Класс XMLEntityManager вызывает close для InputStream.

Вы можете использовать FilterInputStream , чтобы избежать вызова close () базового потока.

Подкласс FilterInputStream и переопределение метода close () пустым телом:

public class MyInputStream extends FilterInputStream {
  public MyInputStream(InputStream in) {
    super(in);
  }

  @Override 
  public void close() {
    // do nothing
  }
}

Затем измените свой вызов unmarshall () на

JAXBElement<Xml> xml =
    (JAXBElement<Xml>)) unmarshaller.unmarshall(new MyInputStream(client.getInputStream()));

Таким образом, среда JAXB по-прежнему вызывает close () в потоке, но теперь он отфильтровывается вашим собственным экземпляром потока, а поток сокетов остается открытым.

7 голосов
/ 27 августа 2012

Если вы не хотите явно переопределять InputStream в своем коде, как предлагает vanje, Apache commons-io предоставляет реализацию, которая достигает этого:

взгляните на:

CloseShieldInputStream

...