Jan,
Thank you for replying. Here is the scenario:
We have a FOSS project named Lucee, which is a Servlet based on
JSP, which allows for rapid development of web applications
because it's much simpler to use and easier to learn than JSP/JSF,
for example. The project is used by many developers and
organizations all over the world.
Lucee allows for extensions (or plugins), which are loaded via
OSGi, so that they can be loaded/unloaded/updated on demand
without restarting the Servlet container, as well as use different
versions of the same 3rd party libraries side by side.
I wrote an open source extension for Lucee which provides
WebSocket support: https://github.com/isapir/lucee-websocket --
The extension has the following requirements:
1) Be packaged as an OSGi bundle so that it can be installed
as a Lucee extension.
2) Be JSR-356 compliant because Lucee could run on any
Servlet container, so I can not use Jetty- or Tomcat- specific
APIs.
3) Allow for WebSocket configuration to be set at runtime, as
we do not know in advance what endpoint etc. the developer will
want to use.
4) Be able to communicate with the Lucee servlet for
Application and Session states.
In order to be able to retrieve the correct state from Lucee
(requirement 4) my code needs to know the root directory of the
ServletContext, e.g. servletContext.getRealPath("/"), at the
Handshake phase. This is required so that multiple contexts can
maintain their separate states without "mixing" up state between the
contexts, so that if there are two contexts, ServletContext1 and
ServletContext2, a user that connects to ServletContext2 he will get
the state from that context, and not the one from ServletContext1.
The only way that I found to retrieve the ServletContext through the
JSR-356 spec (requirement 2) is via the HttpSession in
ServerEndpointConfig.Configurator.modifyHandshake(), i.e.
handshakeRequest.getHttpSession().getServletContext().getRealPath("/").
The problem is, that according to the JSR, the Session should not be
initialized in handshakeRequest.getHttpSession() if one does not
exist, so by default, handshakeRequest.getHttpSession() always
returns null.
The "recommended" way to initialize the Session is with a
ServletRequestListener, where a simple call to
httpServletRequest.getHttpSession() does initialize the HttpSession
object. I have provided a class to do that --
https://github.com/isapir/lucee-websocket/blob/master/src/main/java/net/twentyonesolutions/servlet/listener/HttpSessionInitializer.java#L40
-- but because this is an OSGi bundle (requirement 1), this jar is
not on the classpath -- and can not be specified as-is in the web
descriptor.
The solution that I came up with, is to add a tiny jar file to the
classpath with a Servlet Filter that initializes the HttpSession --
https://github.com/isapir/servlet-filter-utils/blob/master/src/main/java/net/twentyonesolutions/servlet/filter/HttpSessionInitializerFilter.java#L70
-- Then the user adds the tiny jar to the classpath, and configures
the Filter to intercept WebSocket URIs.
But there has to be a simpler method than that, no? Again, my
ultimate goal here is to get the ServletContext's root directory, so
if there is another way to do that then I would not need to jump
through all those hoops. If not, I am looking to register the
ServletRequestListener so that the user will not need to add another
jar and/or modify web.xml.
Thank you,
Igal Sapir
On 7/14/2017 12:23 AM, Jan Bartel
wrote:
Igal,
Some more description of exactly what your setup is would
be good: do you have a bundle that is a traditional war? And
the websocket code bundle is external to the main webapp
bundle? What bundle is the "servlet" in? What does the
websocket bundle do? Without knowing more it is difficult to
give a cogent answer.
Assuming you have another bundle that contains a web.xml,
you could either put that listener definition in there (so
long as you manually get the manifest import statements
correct on the web bundle to refer to your websocket bundle);
or you could define a context listener in there whose job it
is to register the request listener programmatically - that
way tools like bnd will generate correct manifest import
statements for you. I don't know if you want to be able to
selectively enable this listener or not, or based on what
configuration ....
If you provide more info, then maybe I can suggest
something else.
cheers
Jan
_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/jetty-users