Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Register ServletRequestListener from OSGi Bundle

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

Lucee Core Developer
Lucee.org

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



On 13 July 2017 at 19:21, Igal @ Lucee.org <igal@xxxxxxxxx> wrote:
Hello,

I have a JSR-356 (WebSocket API) code that is packaged in an OSGi bundle. The servlet loads the code via Apache Felix if needed.

I want to register a ServletRequestListener, which I would normally put in the web descriptor:

  <listener>
    <listener-class>path.to.my.RequestListener</listener-class>
  </listener>

but since the bundle is not in the classpath that wouldn't work.

How can I register the ServletRequestListener? I am thinking that maybe there would be a way with scanning for annotations but am not sure how to set that up. My other concern is that many users disable the scanning to improve startup time.

The listener's job is to initialize HttpSession so that I can retrieve the ServletContext in the WebSocket handshake. If there's a way to achieve that without the listener then that will work for me even better.

Any ideas?  Thanks!

p.s. This is a crosspost with https://stackoverflow.com/questions/45083982/register-servletrequestlistener-from-osgi-bundle

Igal Sapir
Lucee Core Developer
Lucee.org


_______________________________________________
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



--
Jan Bartel <janb@xxxxxxxxxxx>
www.webtide.com
Expert assistance from the creators of Jetty and CometD



_______________________________________________
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


Back to the top