JAXB через сокеты и потоки - блоки чтения - PullRequest
4 голосов
/ 06 марта 2012

Я пытаюсь отправить экземпляры Java-бина по сетевому потоку.Я хочу выполнить маршалирование / демаршалирование java-экземпляров с помощью JAXB и обычного OutputStream, чтобы протолкнуть его по сети.

Серверы ждут в точке демаршала, но клиент уже намного дальше.

Сервер:

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();

Клиент:

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

РЕДАКТИРОВАТЬ: Я переключился на нормальный выходной поток, но он по-прежнему блокируется.Должен ли я послать какой-то специальный сигнал, чтобы сказать JAXB, чтобы он прекратил демаршаллинг?Если я закрою поток вывода клиента, сообщение прибудет на сторону сервера.

Ответы [ 3 ]

3 голосов
/ 07 марта 2012

Я переключился на XMLEventWriter и XMLEventWriter, и это работает. У меня ощущение, что XMLStreamReader глючит. Он застревает на каком-то skipSpaces() методе. Код XMLStreamReader выглядит так, как будто он должен вернуться, как только появится конец документа.

1 голос
/ 07 марта 2012

Казалось бы, unmarshaller задыхается от семантики выходного потока сокета. Я предполагаю, что он ожидает завершения потока, сигнализируя -1 для доступной длины, и блокирует чтение навсегда, когда вместо этого он получает 0. Хотя это может показаться хакерским, вы можете обойти эту проблему, используя промежуточные программы чтения / записи.

Вот пример, основанный на вашем коде, с использованием программы чтения / записи промежуточных строк:

Сервер:

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();

Клиент:

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();
0 голосов
/ 07 марта 2012

к сожалению, я думаю, что синтаксический анализатор xml ожидает завершения потока перед завершением (он не сдается только потому, что он получил «конец» xml).

один из вариантов - поместить потоковую оболочку поверх потока сокета, которая возвращает -1 после прочтения всех данных xml. однако выяснить, когда вы достигли этой точки, нетривиальная ситуация.

другой вариант - создать свой собственный XMLEventReader, который оборачивает делегат XMLEventReader и заканчивается после получения закрывающего события xml.

Это - другое решение (пользовательские метки «конец потока»).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...