Unmarshalling a Socket's InputStream closes the Socket?
Asked Answered
P

2

9

I have a server-client architecture where the client sends an XML to the server who reads it and generates a PDF out of it and sends that back to the client.

On the client side:

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

Meanwhile on the server side:

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

If I don't unmarshall the client's InputStream (on the server side) and just send back a dummy PDF then everything's goes smoothly. So, I have to assume that the Unmarshaller closes the InputStream it is given, thus implicitly closing the client Socket ruining my day...

Any idea on solving this?

Puisne answered 23/7, 2011 at 10:12 Comment(0)
I
10

The class XMLEntityManager calls close on the InputStream.

You can use a FilterInputStream to avoid a close() call of the underlying stream.

Subclass FilterInputStream and override the close() method with an empty body:

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

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

Then change your unmarshall() call to

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

So the JAXB framework still calls close() on the stream, but it's now filtered out by your own stream instance and the socket stream remains open.

Ia answered 23/7, 2011 at 11:19 Comment(0)
N
7

If you don't want to explicitly override an InputStream in your code like vanje suggest, Apache commons-io provide a implementation that acheive this:

take a look at :

CloseShieldInputStream

Neoclassic answered 27/8, 2012 at 17:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.