Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unmarshalling a Socket's InputStream closes the Socket?

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?

like image 921
Kohányi Róbert Avatar asked Jul 23 '11 10:07

Kohányi Róbert


2 Answers

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.

like image 106
vanje Avatar answered Oct 18 '22 17:10

vanje


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

like image 33
Chuck Mah Avatar answered Oct 18 '22 17:10

Chuck Mah