Reputation: 3677
I already have an answer to the question I am about to pose.
In any casse, I am asking it here so that it may help people migrating from JEE 6 to JEE 7 and that are thinking of using websocket - e.g to substitute long polling by websocket functionality.
QUESTION: In Weblogic 12.2.1.2, which supports JEE 7, and trying to setup websockets using a guide such as the following: http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/HomeWebsocket/WebsocketHome.html
NOTE: The guide above is extremely simple and all it says is correct and "should" work. Will not necessarily work in your application, as it did not in mine. But in concept it should.
Despite that. The websocket appliication goes into error during the handshake from browser to backed, where the HTTP connection is supposed to be upgraded to a tcp/ip web socket connection.
Weblogic, complains that tyrus cannot use Ascyn servlet behavior to handle this handshake protocol. The stack trace for the error during handshake is listed next:
2017-01-23 14:54:59,065 ThreadId:53 ERROR HTTP - [ServletContext@129852715[app:primefaces-60 module:primefaces-60path:null spec-version:3.1]] Servlet failed with an Exception <[ACTIVE] ExecuteThread: '5' for queue: 'weblogic.kernel.Default (self-tuning)'> java.lang.IllegalStateException: The async-support is disabled on this request: weblogic.servlet.internal.ServletRequestImpl@2c87c663[ GET /primefaces-60/actions HTTP/1.1 Connection: Upgrade Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Origin: http://localhost:7001 Sec-WebSocket-Version: 13 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36 DNT: 1 Accept-Encoding: gzip, deflate, sdch, br Accept-Language: en-US,en;q=0.8,pt-PT;q=0.6,pt;q=0.4,fr;q=0.2,it;q=0.2,de;q=0.2 Sec-WebSocket-Key: flKcAkxO3CJBIc8cYvwvlA== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
] at weblogic.servlet.internal.ServletRequestImpl.startAsync(ServletRequestImpl.java:2029) at weblogic.servlet.internal.ServletRequestImpl.startAsync(ServletRequestImpl.java:2005) at javax.servlet.ServletRequestWrapper.startAsync(ServletRequestWrapper.java:432) at weblogic.websocket.tyrus.TyrusServletFilter.doFilter(TyrusServletFilter.java:241) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78) at filter.DummyTimeoutFilter2.doFilter(DummyTimeoutFilter2.java:81) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78) at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:32) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78) at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3683) at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3649) at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:326) at weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197) at weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203) at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71) at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2433) at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2281) at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2259) at weblogic.servlet.internal.ServletRequestImpl.runInternal(ServletRequestImpl.java:1691) at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1651) at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:270) at weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:348) at weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:333) at weblogic.work.LivePartitionUtility.doRunWorkUnderContext(LivePartitionUtility.java:54) at weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41) at weblogic.work.SelfTuningWorkManagerImpl.runWorkUnderContext(SelfTuningWorkManagerImpl.java:640) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:406) at weblogic.work.ExecuteThread.run(ExecuteThread.java:346)
Based on the assumption that the backend code to setup a websocket endpoint is perfect, and the javascript code used to try to establish a websocket connection is perfect. Can sombody explain why the above error is gotten, following the guide to the letter?
NOTE: - The above stack trace is already isolated in a sample application that having a working websocket endpoint was corrupted into the above exception, based on the analysis of the real application.
The answer is simple once you know it... I will be answering in a day or so if no one rights back the right solution.
Upvotes: 2
Views: 3078
Reputation: 3677
To answer my own question.
The issue that the application was experiencing while attempting to open a web-socket connection was related to the fact that tyrus uses features of Sevlet 3.0 specificaiton, namely asynchronous servlet processing.
Even on the most trivial of web applications, one is likely to have filters in place that cross cutingly apply to all web requests. Such as a filter with filter mapping / *.
Well that was precisely the problem. As explained in the following reference, in order an asynchronous servlet to be allowed to run the full chain of filters leading up to the servlet must themsevles support asynchronous request handling.
https://blogs.oracle.com/enterprisetechtips/entry/asynchronous_support_in_servlet_3
The asyncSupported attribute is needed to differentiate code written for synchronous processing from that written for use in an asynchronous context. In fact, for an application to use the asynchronous feature, the entire request processing chain must have the have this attribute set either through the annotation or in its deployment descriptor. An IllegalStateException will be thrown if an application tries to start an asynchronous operation and there is a servlet or servlet filter in the request processing chain that does not support asynchronous processing.
So, to fix the issue, the set of filters had to be given an additional element:
<async-supported>true</async-supported>
For example:
<filter>
<filter-name>AFilter</filter-name>
<filter-class>webapp.AFilter</filter-class>
<async-supported>true</async-supported>
</filter>
In the case of the stack trace above, all that was needed to make the issue reproducible in a stand-alone application was to add a dummy filter that does absolutely nothing except pass the request along to the next filter. THe filter was : DummyTimeoutFilter2. This filter was declared without the async supported true.
So, to conclude, be aware that your container may be requiring asynchronous servlets to open web sockets. And if you have any filter interecepting the requests to your websocket endpoint, you might be surprised by just such a side effect. This is especially true for applications coming out of JEE 6, but it could easily happen to any brand new JEE 7 application.
Most people, however, will likely have no filters intercepting a call to a websocket endpoint...
Upvotes: 4