Tomcat: завершение работы приводит к преждевременной ошибке EOF в клиенте - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть сервлет, работающий на tomcat8 (с использованием Jersey) и клиентское приложение, написанное на Java.Для передачи данных, которые экспортируются из клиентского приложения непосредственно на веб-сервер (вместо того, чтобы сначала экспортировать все данные и затем выгружать данные), я использую пользовательскую реализацию InputStream.

Все работает нормально, кроме этого сценария:

Я начинаю передачу данных с клиента, затем выключаю tomcat, пока данные все еще передаются.Сообщения журнала показывают, что запрос завершен (я установил для unloadDelay очень высокое значение, чтобы запросы завершались до завершения работы), но клиент выдает исключение «Преждевременный EOF» при попытке прочитать ответ.

Я проверил, что поток полностью передан на сервер.Поэтому после того, как сервер обработает InputStream, он в результате возвращает String, но при попытке прочитать результат на клиенте сервер уже пропал (кажется).

Как я могу корректно завершить работу tomcat, поэтому запрашиваетвсе еще в процессе завершится без ошибок?

Вот часть кода:

Фрагмент из Джерси Ресурс

@POST
@Produces(MediaType.TEXT_PLAIN)
public Response handleData(InputStream data) {
    String result = service.put(data);
    log.info("handledData, result: " + result);
    return Response.status(201).entity(result).build();
}

Фрагментfrom WebRequests.java - вспомогательный класс, использующий джерси для вызова сервлета

private static Builder builder(String url, String sessionId, InputStream data) {
    WebResource resource = createClient().resource(url);
    Builder builder = resource.accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE, MediaType.APPLICATION_OCTET_STREAM_TYPE);
    builder.cookie(new Cookie("JSESSIONID", sessionId));
    builder.entity(data, MediaType.APPLICATION_OCTET_STREAM_TYPE);
    return builder;
}

private static Client createClient() {
    ClientConfig config = new DefaultClientConfig();
    config.getProperties().put(ClientConfig.PROPERTY_FOLLOW_REDIRECTS, false);
    Client client = Client.create(config);
    client.setChunkedEncodingSize(1024 * 100);
    return client;
}

вызывающий код (CommitStream - пользовательский поток ввода):

InputStream stream = new CommitStream(db, message, data, callback);
String result = WebRequests.builder("http://....", sessionId, stream).post(String.class);

Stacktrace

 java.io.IOException: Premature EOF
     at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:565)
     at sun.net.www.http.ChunkedInputStream.readAhead(ChunkedInputStream.java:609)
     at sun.net.www.http.ChunkedInputStream.read(ChunkedInputStream.java:696)
     at java.io.FilterInputStream.read(FilterInputStream.java:133)
     at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3444)
     at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
     at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
     at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
     at java.io.InputStreamReader.read(InputStreamReader.java:184)
     at java.io.Reader.read(Reader.java:140)
     at com.sun.jersey.core.util.ReaderWriter.readFromAsString(ReaderWriter.java:171)
     at com.sun.jersey.core.util.ReaderWriter.readFromAsString(ReaderWriter.java:157)
     at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.readFromAsString(AbstractMessageReaderWriterProvider.java:114)
     at com.sun.jersey.core.impl.provider.entity.StringProvider.readFrom(StringProvider.java:73)
     at com.sun.jersey.core.impl.provider.entity.StringProvider.readFrom(StringProvider.java:58)
     at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:634) 
...