JAXB over Sockets and Streams - Reader Blocks

I am trying to send java bean instances over a network stream. I want marshal / unmarshal java instances with JAXB and normal OutputStream to drag it over the network.

The servers are waiting at a non-marshal point, but the client is already much further.

Server:

 inputStream = new BufferedInputStream(this.socket.getInputStream()); outputStream = new BufferedOutputStream(this.socket.getOutputStream()); JAXBContext requestContext = JAXBContext.newInstance(this.requestClass); Unmarshaller unmarshaller = requestContext.createUnmarshaller(); @SuppressWarnings("unchecked") K request = (K) unmarshaller.unmarshal(inputStream); //blocks here respond(); 

Client:

 JAXBContext messageContext = JAXBContext.newInstance(message.getClass()); Marshaller marshaller = messageContext.createMarshaller(); out = new BufferedOutputStream(socket.getOutputStream()); marshaller.marshal(message, out); out.flush(); waitForResponse();// blocks here 

EDIT: I switched to the normal output stream, but it is still blocked. Should I send a special signal to tell JAXB to stop disassembling? If I close the client's output stream, the message comes from the server side.

+4
source share
3 answers

I switched to XMLEventWriter and XMLEventWriter and it works. I have a feeling that XMLStreamReader buggy. It gets stuck in some skipSpaces() method. The XMLStreamReader code looks as if it should return as soon as the end of the document appears.

+3
source

It would seem that unmarshaller suffocates the semantics of the socket output stream. I assume that the stream is expected to be terminated by a -1 signaling for the available length and will block the attempt to read forever when it gets 0 instead. Although this may seem hacky, you can work around this problem by using intermediate readers / writers.

Here is an example based on your code using a line read / write broker:

Server:

 final BufferedReader socketReader = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); final StringReader dataReader = new StringReader(socketReader.readLine()); JAXBContext requestContext = JAXBContext.newInstance(this.requestClass); Unmarshaller unmarshaller = requestContext.createUnmarshaller(); @SuppressWarnings("unchecked") K request = (K) unmarshaller.unmarshal(dataReader); respond(); 

Client:

 JAXBContext messageContext = JAXBContext.newInstance(message.getClass()); Marshaller marshaller = messageContext.createMarshaller(); final StringWriter dataWriter = new StringWriter(); marshaller.marshal(message, dataWriter); out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); out.write(dataWriter.toString()); out.newLine(); out.flush(); waitForResponse(); 
+1
source

Unfortunately, I think that the XML parser is waiting for the stream to finish (it does not refuse only that it received the "end" xml).

one option would be to put some wrapper on the stream on top of the socket stream, which returns -1 after all xml data has been read. however, figuring out when you have reached this point is a non-trivial situation.

another option is to create your own XMLEventReader, which wraps the XMLEventReader delegate and ends after the xml close event is received.

This is another solution (end-of-stream labels).

0
source

Source: https://habr.com/ru/post/1400078/


All Articles