Pax Web Whiteboard with DS: problems with making context path work

82 views
Skip to first unread message

Steinar Bang

unread,
Mar 31, 2018, 2:37:41 AM3/31/18
to op...@googlegroups.com
I'm in the process of transitioning a Vaadin war web application with
web.xml to the Pax Web Whiteboard extender.

One thing that was lost in the transition, was the web application
context path. The web.xml of the original webapp let the Vaadin servlet
match everything from "/*" which matched both the application itself and
the static resources from "/VAADIN/*".
https://github.com/steinarb/ukelonn/blob/ef57228437a305ef1d15b5671ddc82c59a04d572/ukelonn.bundle/src/main/webapp/WEB-INF/web.xml#L36

In the maven-bundle-plugin config (this was a war bundle meant for
karaf), I set the Web-ContextPath header in the manifest.mf of the war:
https://github.com/steinarb/ukelonn/blob/ef57228437a305ef1d15b5671ddc82c59a04d572/ukelonn.bundle/pom.xml#L179

Because the application context was "ukelonn", the actual path of the
web application was "/ukelonn/*", with the Vaadin static resources being
under "/ukelonn/VAADIN/*".

I've now got the Pax Web Whiteboard version working. However, in the
Pax Web Whiteboard version, the application context was gone and I had
to let the servlet match two paths from the top, ie.: "/ukelonn/*"
(containing the webapp) and "/VAADIN/*" (containing the static resources
of Vaadin).
https://github.com/steinarb/ukelonn/blob/7b69f7f081f56541d58f1dc8a4c619cd18ac02d6/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnServlet.java#L39
and the Shiro filter (handling authentication and authorization)
https://github.com/steinarb/ukelonn/blob/7b69f7f081f56541d58f1dc8a4c619cd18ac02d6/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnShiroFilter.java#L41

The downside of this, is that if I have two webapps that use VAADIN, the
webapps will have to use the exact same version of VAADIN.

I have now tried to add a context path to the property argument of the
@Component annotation, but that doesn't seem to work: the Vaadin servlet
now matches everything from the top (because of the "/*" pattern) and I
don't see the context anywhere.

The servlet annotation looks like this:
@Component(
property= {
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN+"=/*",
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME+"=ukelonn",
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME+"=ukelonn",
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH+"=/ukelonn"},
service=Servlet.class,
immediate=true
)
public class UkelonnServlet extends TouchKitServlet {


The filter annotation looks like this:
@Component(
property= {
HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN+"=/*",
"servletNames=ukelonn",
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=ukelonn",
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + "=/ukelonn"},
service=Filter.class,
immediate=true
)
public class UkelonnShiroFilter extends AbstractShiroFilter {


Does anyone know how to set the context on a servlet (and a filter) when
using Pax Web Whiteboard Extender with OSGi Declarative Services (DS)?

Thanks!

- Steinar

Steinar Bang

unread,
Mar 31, 2018, 6:53:32 AM3/31/18
to op...@googlegroups.com
>>>>> Steinar Bang <s...@dod.no>:

> I have now tried to add a context path to the property argument of the
> @Component annotation, but that doesn't seem to work: the Vaadin servlet
> now matches everything from the top (because of the "/*" pattern) and I
> don't see the context anywhere.

> The servlet annotation looks like this:
> @Component(
> property= {
> HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN+"=/*",
> HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME+"=ukelonn",
> HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME+"=ukelonn",
> HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH+"=/ukelonn"},
> service=Servlet.class,
> immediate=true
> )
> public class UkelonnServlet extends TouchKitServlet {

As far as I can tell from the code that is called when a Servlet service
is registered, there is nothing using the HTTP_WHITEBOARD_CONTEXT_NAME
or WHITEBOARD_CONTEXT_PATH properties:
https://github.com/ops4j/org.ops4j.pax.web/blob/master/pax-web-extender-whiteboard/src/main/java/org/ops4j/pax/web/extender/whiteboard/internal/tracker/ServletTracker.java#L81

> The filter annotation looks like this:
> @Component(
> property= {
> HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN+"=/*",
> "servletNames=ukelonn",
> HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=ukelonn",
> HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + "=/ukelonn"},
> service=Filter.class,
> immediate=true
> )
> public class UkelonnShiroFilter extends AbstractShiroFilter {

Nothing in the code handling Filter services supports the
https://github.com/ops4j/org.ops4j.pax.web/blob/master/pax-web-extender-whiteboard/src/main/java/org/ops4j/pax/web/extender/whiteboard/internal/tracker/ServletTracker.java#L81

> The filter annotation looks like this:
> @Component(
> property= {
> HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN+"=/*",
> "servletNames=ukelonn",
> HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=ukelonn",
> HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + "=/ukelonn"},
> service=Filter.class,
> immediate=true
> )
> public class UkelonnShiroFilter extends AbstractShiroFilter {

Nothing in the code handling Filter services directly supports the
HTTP_WHITEBOARD_CONTEXT_NAME or WHITEBOARD_CONTEXT_PATH properties,
either:
https://github.com/ops4j/org.ops4j.pax.web/blob/master/pax-web-extender-whiteboard/src/main/java/org/ops4j/pax/web/extender/whiteboard/internal/tracker/FilterTracker.java#L52

There seems to be some services FilterMapping and ServletMapping that
are listened for as well, but (so far) I don't know how to set them up
and what they can contain, and the service tracers don't do much when
receiving them (the trackers just creates a FilterMappingWebElement or a
ServletMappingWebElement).

Steinar Bang

unread,
Mar 31, 2018, 7:22:27 AM3/31/18
to op...@googlegroups.com
> Nothing in the code handling Filter services directly supports the
> HTTP_WHITEBOARD_CONTEXT_NAME or HTTP_WHITEBOARD_CONTEXT_PATH
> properties, either:
> https://github.com/ops4j/org.ops4j.pax.web/blob/master/pax-web-extender-whiteboard/src/main/java/org/ops4j/pax/web/extender/whiteboard/internal/tracker/FilterTracker.java#L52

The handler for the ServletContextHelper service seems to do stuff with
both HTTP_WHITEBOARD_CONTEXT_NAME and HTTP_WHITEBOARD_CONTEXT_PATH, but
I havn't yet determined how it works and how to connect things to a
servlet, and (hopefully also) a Filter.

Steinar Bang

unread,
Mar 31, 2018, 1:03:28 PM3/31/18
to op...@googlegroups.com
>>>>> Steinar Bang <s...@dod.no>:

> The handler for the ServletContextHelper service seems to do stuff with
> both HTTP_WHITEBOARD_CONTEXT_NAME and HTTP_WHITEBOARD_CONTEXT_PATH, but
> I havn't yet determined how it works and how to connect things to a
> servlet, and (hopefully also) a Filter.

Ok, now I've got it working[1].

The changes are:
1. Added a ServletContextHelper OSGi component[2] whose only purpose is
to add an OSGi service that has a service attribute named
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH
(ie. "osgi.http.whiteboard.context.path") with the value of the web
applications context path
2. Changed the servlet pattern of the servlet component, and added a
property HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT
(ie. "osgi.http.whiteboard.context.select") containing a select
expression that will find the ServletContextHelper[3]
3. Made the same changes for the Shiro filter component as for the
servlet component (change the URL pattern to "/*" and add an
expression that will find the ServletContextHelper)[4]

I found an example of how to do this in the blog article "Http
Whiteboard – Simply Simple – Part II"[5]

Another blog article with some useful clues (but with an approach that
doesn't currently work on the Pax Web Whiteboard Extender), is "Access
OSGi Services via web interface"[6].


References:
[1] <https://github.com/steinarb/ukelonn/commit/b1cece3ff166d62e5eb52ec8b5c51d2304025c2f>
[2] <https://github.com/steinarb/ukelonn/blob/b1cece3ff166d62e5eb52ec8b5c51d2304025c2f/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnServletContextHelper.java#L6>
[3] <https://github.com/steinarb/ukelonn/blob/b1cece3ff166d62e5eb52ec8b5c51d2304025c2f/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnServlet.java#L39>
[4] <https://github.com/steinarb/ukelonn/blob/b1cece3ff166d62e5eb52ec8b5c51d2304025c2f/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnShiroFilter.java#L41>
[5] <https://blog.osoco.de/2016/09/http-whiteboard-simply-simple-part-ii/>
[6] <http://blog.vogella.com/2017/04/20/access-osgi-services-via-web-interface/>

Steinar Bang

unread,
Apr 1, 2018, 5:39:08 PM4/1/18
to op...@googlegroups.com
>>>>> Steinar Bang <s...@dod.no>:

>> The handler for the ServletContextHelper service seems to do stuff with
>> both HTTP_WHITEBOARD_CONTEXT_NAME and HTTP_WHITEBOARD_CONTEXT_PATH, but
>> I havn't yet determined how it works and how to connect things to a
>> servlet, and (hopefully also) a Filter.

> Ok, now I've got it working[1].

[snip!]
> References:
> [1] <https://github.com/steinarb/ukelonn/commit/b1cece3ff166d62e5eb52ec8b5c51d2304025c2f>
[snip!]
> [4] <https://github.com/steinarb/ukelonn/blob/b1cece3ff166d62e5eb52ec8b5c51d2304025c2f/ukelonn.bundle/src/main/java/no/priv/bang/ukelonn/impl/UkelonnShiroFilter.java#L41>

I had to make an additional change to UkelonnShiroFilter to get rid of
an annoying issue where Shiro kept adding "login.jsp" to the URL:
https://github.com/steinarb/ukelonn/commit/153fd423a9316c415664adbdfbd5647d82dafd1e

(FWIW it still worked even with the login.jsp in place, since the Vaadin
servlet doesn't care about other local paths than the top / and
/VAADIN/*, but it didn't look good)

The change is to make sure the IniFilterChainResolverFactory get the Map
from the WebIniSecurityManagerFactory.getBeans() method. The Map
contains the results from the [main] section on the shiro.ini file
(eg. the authc.loginUrl setting, ie. without the authc.loginUrl the
FormAuthenticationFilter will get the default loginUrl, which is
"logn.jsp").

Reply all
Reply to author
Forward
0 new messages