-
-
Notifications
You must be signed in to change notification settings - Fork 754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Jetty 9.3 and Atmosphere do not play nicely together #1998
Comments
Sound like in 9.3 Jetty's Native WebSocket Implementation with websocket is recycling the |
Workaround is to enable jsr 356 https://github.com/Atmosphere/atmosphere/wiki/Forcing-JSR-356-for-WebSocket-Application |
Can you describe when, in the lifecycle of the websocket, you are accessing these fields from the The stacktrace above doesn't indicate access to the Request object from within any of the websocket layers, but rather from the servlet itself (which is very strange to see) |
From the longer stacktrace at the vaadin side, the problem occurs through this path ...
and then you go and attempt to create a VaadinSession during this disconnect flow, and part of that logic is to extract parameters from the request object. Websocket isn't involved in that stacktrace, you have a disconnected/disconnecting client and are being notified of such, however you then attempt to create a VaadinSession during this state. You shouldn't be attempting to access the request object during this disconnect state. |
@joakime The issue arises because the original public boolean acceptWebSocket(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
setCreator(new WebSocketCreator() {
// @Override 9.1.x
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) {
req.getExtensions().clear();
if (!webSocketProcessor.handshake(request)) {
try {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "WebSocket requests rejected.");
} catch (IOException e) {
logger.trace("", e);
}
return null;
}
return new Jetty9WebSocketHandler(request, config.framework(), webSocketProcessor);
}
});
return super.acceptWebSocket(request, response);
} is getting recycled/reset in 9.3.0 to null after executing . @Override
public void onWebSocketConnect(Session session) {
logger.trace("WebSocket.onOpen.");
webSocket = new Jetty9WebSocket(session, framework.getAtmosphereConfig()); See One workaround in Atmosphere consists of loading the content of that request in memory but that's kind of bad because it's a copy of the original request object instead of the object itself. But that's a possible workaround for now. |
Note: the ServletUpgradeRequest, part of the WebSocketCreator method calls, is durable, and should be an immutable copy of the values of the original HttpServletRequest object. |
Referencing in-line comment on commit here too. The Use the ServletUpgradeRequest and its methods only, that's durable and long lasting (for the lifecycle of the WebSocket). Note: when WebSocket over HTTP/2 hits, this is going to be very important. If there are some methods missing in ServletUpgradeRequest that you need, ask for them, we'll expose them. Also, there's a method on ServletUpgradeRequest to access the original HttpServletRequest if you need it, but (again) the HttpServletRequest only valid during the Once the connection is upgraded, then the |
@joakime I clone the |
Is this going to be fixed? It seems to me that Jetty stable from now on will be using this new HTTP2 architecture that seems to be causing this issue. |
@benstpierre It is fixed in 2.3.3-SNAPSHOT |
There is still at least one NPE issue remaining, created #2154 to track that |
Issue #2154 has been closed due to an old JVM and its associated bugs. |
I am facing an issue in getting previsouly created HttpSession with Atmosphere request. It was working fine with jetty 9.2.9 but when I upgrade jetty to 9.3.5 , session info object created previously after login is now null in the onRequest of MessagingEndPoint of atmosphere The main cause of the issue is the following change in Jetty9websocketHandler in the Atmosphere-runtime library /** |
Note, the comment "9.3.0+ should use jsr 356" is pointless. Jetty offers both native websocket (worlds better then JSR356) and JSR356 support (v1.0 currently, 1.1 scheduled for Jetty 9.4). Both options have the same issue with HttpSession, the container is free to recycle the HttpServletRequest object once the upgrade is complete. The lifecycle of HttpServletRequest and HttpSession have no application when you have upgraded out of a HTTP request and into a WebSocket lifecycle. This is a problem for many libraries, not just yours. Even CDI has no solution for this lifecycle difference. Not even JSR356 has addressed this issue (its an open bug/issue on the JSR356 issue tracker). The HttpSession is also free to expire / idle timeout (and get recycled) as there's no activity on the HttpServletRequest, or HttpServletResponse while you are in WebSocket. There is some hope that the Servlet 4.x effort (currently underway) will properly declare how the 2 different lifecycles should behave. (Note: this will likely have some big impacts to your code once its properly defined) |
This is very bad style, and is the cause of your issues. private HttpServletRequest originalRequest(Session session) {
try {
// Oh boy...
ServletUpgradeRequest request = (ServletUpgradeRequest) session.getUpgradeRequest();
Field[] fields = ServletUpgradeRequest.class.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
Object o = f.get(request);
if (o instanceof HttpServletRequest) {
return HttpServletRequest.class.cast(o);
}
}
} catch (Exception ex) {
logger.error("", ex);
}
return null;
} Do not copy the If what you want is the But note that the For example:
There are not insurmountable issues for a library using WebSocket, many libraries built on top of Java WebSocket / JSR356 have adapted to this reality of ill defined specs and lifecycles just fine, atmosphere can too. |
@joakime Well, the Jetty API changed many times and that's the reason why I needed to use reflection here. I do agree this is quite ugly, but supporting 9.0/9.1/9.2 and 9.3 is a challenge with this unique code base. Now fixing the session should be straightforward...and the HttpServletRequest is later cloned in the code (it's content copied during the handshake) and the object never used after. So yes it's ugly, but we don't keep a reference to it after the handshake. |
The support for 9.0 is suspect, that was a transition release between Servlet 3.0 and Servlet 3.1, probably safe to drop support for 9.0. Depending on what specific version of 9.0.x you might either have a Servlet 3.0 support level, or a Servlet 3.1 beta/draft support level. As for popularity, we have statistics from maven central and download.eclipse.org to work with...
This shows you that Jetty 9.0.x and 9.1.x interest are practically statistical noise at this point and likely safe to start deprecating in your own releases. Note: Jetty 9.4.x is due out this summer, and Jetty 10.x has already been started (its the master branch in git ATM) |
@jfarcand - Are you going to fix this as you said now fixing the session should be straightforward? Thanks In Advance! |
@jyoti-sungard I don't have the cycle to do that this month...so contribution welcomed :-) |
@jfarcand - I need to pass copySession as true in theJetty9WebSocketHandler.java to get the previously created session. Do you guys have any concern as the comment says "This is a performance regression from 9.2 as we need to clone again the request. 9.3.0+ ". |
@jyoti-sungard That should be fine to re-use the session, event if we copy the request's state. |
Hi, Here the error code which seems to be related to a bad URI: (xyz is the pubsub topic i entered; spring-atmosphere is the application name) java.lang.IllegalStateException: Could not get HttpServletRequest URI: Expected hostname at index 5: ws://:0/messaging/realtime?topic=xyz org.springframework.http.server.ServletServerHttpRequest.getURI(ServletServerHttpRequest.java:98)\r\n\tat org.springframework.web.util.UriComponentsBuilder.fromHttpRequest(UriComponentsBuilder.java:282)\r\n\tat org.springframework.web.util.WebUtils.isSameOrigin(WebUtils.java:811)\r\n\tat org.springframework.web.cors.DefaultCorsProcessor.processRequest(DefaultCorsProcessor.java:71)\r\n\tat org.springframework.web.servlet.handler.AbstractHandlerMapping$CorsInterceptor.preHandle(AbstractHandlerMapping.java:503)\r\n\tat org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:134)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:954)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:687)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:790)\r\n\tat org.atmosphere.util.AtmosphereFilterChain.doFilter(AtmosphereFilterChain.java:135)\r\n\tat org.atmosphere.util.AtmosphereFilterChain.invokeFilterChain(AtmosphereFilterChain.java:96)\r\n\tat org.atmosphere.handler.ReflectorServletProcessor$FilterChainServletWrapper.service(ReflectorServletProcessor.java:333)\r\n\tat org.atmosphere.handler.ReflectorServletProcessor.onRequest(ReflectorServletProcessor.java:171)\r\n\tat org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:223)\r\n\tat org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:115)\r\n\tat org.atmosphere.container.Servlet30CometSupport.service(Servlet30CometSupport.java:68) Thanks! |
The websocket uri you are using The |
Tested using the chat sample and Atmosphere 2.3.2
Similar problems reported by a Vaadin user at https://vaadin.com/forum#!/thread/10309898
Jetty 9.3 issue or Atmosphere issue?
The text was updated successfully, but these errors were encountered: