2016-05-08 5 views
1

Я получаю ошибку HttpMediaTypeNotAcceptableException, когда SseEmitter имеет время ожидания.Как избежать HttpMediaTypeNotAcceptableException с Spring SseEmitter по таймауту

При поиске в SO для этого кода ошибки я нахожу только ответы, относящиеся к регистрации преобразователя для ResponseBody. Но я не вижу, как это может быть та же проблема, с которой я столкнулся, поскольку тип содержимого - text/event-stream и автоматически обрабатывается Spring.

Однако сообщение, похоже, протекает хорошо иначе; сообщения отправляются должным образом клиенту.

@RequestMapping(path = "/channel") 
@CrossOrigin 
public SseEmitter channel() throws IOException { 

    SseEmitter emitter = new SseEmitter(); 

    // Storing the emitter 
    // ... 
    player.setEmitter(emitter); 

    return emitter; 
} 

В проигрывателе, я делаю это:

public void setEmitter(SseEmitter emitter) { 
    if (this.emitter != null) { 
     // Old emitter must be completed for user 
     this.emitter.complete(); 
    } 

    this.emitter = emitter; 
    this.emitter.onTimeout(() -> { 
     if (this.emitter != null) this.emitter.complete(); 
    }); 
    this.emitter.onCompletion(() -> this.emitter = null); 
} 

public void sendMessage(String message) { 
    if (this.emitter != null) { 
     emitter.send(message); 
    } 
} 

(Кстати, это хороший способ обработки эмиттер, то есть регистрации onTimeout и onCompletion Идея заключается в том, что новый эмиттер создается при каждом повторном подключении, а это значит, что старый нужно заменить.)

Отправленные сообщения представляют собой структуру данных, сериализованную в текст JSON. На клиенте JavaScript он правильно десериализуется в объект JSON. Я не указывал содержание JSON в любом месте, как я думаю, с точки зрения SseEmitter/SSE, это просто текст.

За время установления соединения все работает нормально. При каждом таймауте клиент повторно подключается, как следует. Однако я, кажется, всегда получаю следующее исключение в связи с тайм-аут и повторно процедуру:

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation 
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:191) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:183) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81) ~[spring-web-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) ~[javax.servlet-api-3.1.0.jar:3.1.0] 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) ~[javax.servlet-api-3.1.0.jar:3.1.0] 
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) ~[jetty-servlet-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587) ~[jetty-servlet-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:595) ~[jetty-security-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ContextHandler.__doHandle(ContextHandler.java:1127) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) ~[jetty-servlet-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.Server.handleAsync(Server.java:549) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:348) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:262) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) [jetty-util-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) [jetty-util-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at java.lang.Thread.run(Thread.java:745) [na:na] 

Я использую Spring Ботинок с Jetty. Я также получаю эту ошибку, но я думаю, что это является следствием первого:

java.lang.IllegalStateException: Committed 
    at org.eclipse.jetty.server.Response.resetBuffer(Response.java:1243) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.Response.sendError(Response.java:567) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.Response.sendError(Response.java:544) ~[jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:167) ~[javax.servlet-api-3.1.0.jar:3.1.0] 
    at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:167) ~[javax.servlet-api-3.1.0.jar:3.1.0] 
    at org.springframework.security.web.context.OnCommittedResponseWrapper.sendError(OnCommittedResponseWrapper.java:95) ~[spring-security-web-4.0.3.RELEASE.jar:4.0.3.RELEASE] 
    at org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.handleHttpMediaTypeNotAcceptable(DefaultHandlerExceptionResolver.java:257) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.doResolveException(DefaultHandlerExceptionResolver.java:121) ~[spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:137) [spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:74) [spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1185) [spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1022) [spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:973) [spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) [spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) [spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858) [spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) [javax.servlet-api-3.1.0.jar:3.1.0] 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) [spring-webmvc-4.2.6.RELEASE.jar:4.2.6.RELEASE] 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [javax.servlet-api-3.1.0.jar:3.1.0] 
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) [jetty-servlet-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587) [jetty-servlet-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:595) [jetty-security-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ContextHandler.__doHandle(ContextHandler.java:1127) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) [jetty-servlet-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.Server.handleAsync(Server.java:549) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:348) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:262) [jetty-server-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) [jetty-util-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) [jetty-util-9.2.14.v20151106.jar:9.2.14.v20151106] 
    at java.lang.Thread.run(Thread.java:745) [na:na] 

ответ

0

Ошибка была не на стороне сервера. Несколько раз щелкнув по клиенту, неожиданно появились два объекта EventSource на стороне клиента. Это и послужило причиной ошибок.

+0

Кстати, это также происходит, когда вы используете весеннюю загрузку со встроенным сервером tomcat, особенно когда вы прерываете соединение потока событий с сервером, вручную перезагружая страницу браузера. В обработчике тайм-аута на стороне сервера вы можете пометить поток как полный, но все же есть отправка, сделанная в MVC, которая не обрабатывается по умолчанию и приводит к этой ошибке. –