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 i开发者_StackOverflow中文版dea on solving this?
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.
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
精彩评论