Web Whiteboard, how to register a filter across bundles?

366 views
Skip to first unread message

Daniel McGreal

unread,
Dec 17, 2015, 8:25:33 AM12/17/15
to OPS4J
Hi Ops4J people,

I'm trying to export a Filter which is attached to Servlets which are exported from other Bundles.

I didn't quite find any specific documentation for this, but from various posts, Jira issues, etc, I found https://github.com/ops4j/org.ops4j.pax.web/commit/203c8eb8e2b25007157a364680badbf047146bf2 and have taken the test case as the model I should follow. Is this the right way?

LoginBundle should:
  • Register a Servlet at /login
  • Listen for other Servlets and register a Filter for each which detects Authorisation and does a RequestDispatcher.forward to the LoginServlet if not yet authorised.
ApplicationBundle(s) should:
  • Register a Servlet to be detected by LoginBundle (and Pax Whiteboard)

With a LoginBundle BundleActivator.start as follows:

                ServiceReference<WebContainer> webContainerReference = null;

               do{

                       webContainerReference = context.getServiceReference(WebContainer.class);

               } while(webContainerReference == null);

               

               WebContainer webContainer = context.getService(webContainerReference);

               SharedWebContainerContext httpContext = webContainer.getDefaultSharedHttpContext();


                Dictionary<String, String> properties = new Hashtable<String, String>();

               properties.put("httpContext.id", "shared");

               properties.put("httpContext.shared", "true");

               httpContextRegistration = context.registerService(HttpContext.class, httpContext, properties);

               

               LoginServlet loginServlet = new LoginServlet();

                properties.put(SERVLET_NAME_PROPERTY, LOGIN_SERVLET_NAME);

               loginUiRegistration = context.registerService(HttpServlet.class, loginServlet, properties);

               
#
... and so on, setting up a ServiceTracker which registers Filters for detected Servlets


I do not get a servlet at /login, and in the log I get:

karaf@root()> log:display
2015-12-17 13:08:23,167 | INFO  | Thread-34        | BundleWatcherImpl                | 24 - org.apache.karaf.bundle.core - 4.0.3 | [Watch] Updating watched bundle: web.login (0.0.1.BUILD-201512171220)
2015-12-17 13:08:23,201 | INFO  | Thread-34        | HttpServiceFactoryImpl           | 163 - org.ops4j.pax.web.pax-web-runtime - 4.2.3 | Unbinding bundle: [web.login [272]]
2015-12-17 13:08:23,232 | INFO  | Thread-34        | HttpServiceFactoryImpl           | 163 - org.ops4j.pax.web.pax-web-runtime - 4.2.3 | Binding bundle: [web.login [272]] to http service
2015-12-17 13:08:23,245 | WARN  | Thread-34        | HttpServiceStopped               | 163 - org.ops4j.pax.web.pax-web-runtime - 4.2.3 | Http service has already been stopped
2015-12-17 13:08:23,245 | WARN  | Thread-34        | HttpServiceStopped               | 163 - org.ops4j.pax.web.pax-web-runtime - 4.2.3 | Http service has already been stopped

If I remove the httpContext.id and httpContext.shared properties from the Servlet (but keep them on the HttpContext), the /login Servlet is registered successfully.

The same is true in the ApplicationBundle. If I register my Servlet there with the necessary httpContext properties, I get the "Http service has already been stopped" message when binding it. If I remove the properties, the Servlet is registered correctly - but my Filters are not attached.

I'd be delighted by any assistance you can give me!
Very best, 
Dan.

Achim Nierbeck

unread,
Dec 17, 2015, 11:51:27 AM12/17/15
to op...@googlegroups.com
Hi, 

first of all, in your sample tracking the webconsole should be tracked by a service tracker ;) 

second, you'll find a working example here [1]. 

It's crucial to register your httpContext as a shared Context, with the already given properties (if you use Pax-Web 6.0, it'll do this in a OSGi R6 like manner) 
To create such a shared context you can use the webcontainer.createDefaultSharedHttpContext (or the like)
This context should be created by the Servlet Bundle, the filters should be attached accordingly if the correct context type ist found. 

Hope this helps already, the sources should be self-explanatory :-) 

If you need more just keep on asking ...

regards, Achim 



--
--
------------------
OPS4J - http://www.ops4j.org - op...@googlegroups.com

---
You received this message because you are subscribed to the Google Groups "OPS4J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ops4j+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Apache Member
Apache Karaf <http://karaf.apache.org/> Committer & PMC
OPS4J Pax Web <http://wiki.ops4j.org/display/paxweb/Pax+Web/> Committer & Project Lead
blog <http://notizblog.nierbeck.de/>
Co-Author of Apache Karaf Cookbook <http://bit.ly/1ps9rkS>

Software Architect / Project Manager / Scrum Master 

Daniel McGreal

unread,
Dec 17, 2015, 12:26:21 PM12/17/15
to op...@googlegroups.com
Thanks Achim,

I think I covered all your points in the example code, so hopefully you’ll be able to comment on the below, with my pre-thanks.

first of all, in your sample tracking the webconsole should be tracked by a service tracker ;) 

Indeed! This is prototype code, it’ll likely be in DS or similar when I have it working...

It's crucial to register your httpContext as a shared Context, with the already given properties (if you use Pax-Web 6.0, it'll do this in a OSGi R6 like manner) 

This means:
  • An HttpContext must be registered through the service registry
  • Is the value of ‘httpContext.id’ my choice
  • I notice that the createDefaultHttpContext (i.e. -Shared) has an optional argument, so I wonder if the ‘name’ of the HttpContext is set at creation? Or does this method also register the HttpContext?
  • Can there be multiple ’shared' HttpContexts with different ids registered?
  • ‘httpContext.shared’ must be ‘true' for the HttpContext, the Servlets and the Filters

To create such a shared context you can use the webcontainer.createDefaultSharedHttpContext (or the like)

If I use this instead of the getDefaultSharedHttpContext method (as in my sample code, and the linked integration test), I get the same result.

This context should be created by the Servlet Bundle, the filters should be attached accordingly if the correct context type ist found. 

I can’t have a shared HttpContext created by a different bundle than the Servlet which I’m hoping to attach Filters to?
In my example, I would like to have two servlets, one from each bundle. I’m not sure if it’s necessary to have both Servlets share the same HttpContext, but it’s definitely true that the one from the ApplicationBundle should, so this will be a problem for me. However, in my example, neither Servlet works when I set the httpContext properties.


Thanks, Dan.

               httpContextRegistration = context.registerService(HttpContext.class,httpContext, properties);

You received this message because you are subscribed to a topic in the Google Groups "OPS4J" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ops4j/iKvj-qu7gS4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ops4j+un...@googlegroups.com.

Achim Nierbeck

unread,
Dec 19, 2015, 11:58:35 AM12/19/15
to op...@googlegroups.com
Hi Dan, 

yes you need to make sure at least one bundle creates a shared context which is re-used by the other Servlets and Filters. To reference that context just make sure to reference that httpContext. [1]

// register a filter
Hashtable<String, String> props = new Hashtable<String, String>();
props.put(ExtenderConstants.PROPERTY_URL_PATTERNS, "/sharedContext/*");
props.put(ExtenderConstants.PROPERTY_HTTP_CONTEXT_ID, "shared");
props.put(ExtenderConstants.PROPERTY_HTTP_CONTEXT_SHARED, "true");
filterReg = context.registerService(Filter.class,new SimpleOnlyFilter(), props);

regards, Achim 

Reply all
Reply to author
Forward
0 new messages