java - Register resources based on url pattern with pax web 8 and jetty 9 for osgi - Stack Overflow

I've created an application with an external dependency that registers WABs. The WABs are created

I've created an application with an external dependency that registers WABs. The WABs are created with a manifest.mf that contains the desired Web-ContextPath: '/custom/route' configuration. This works to register a new context and serve it's contents on that path. However with the move from pax web 7 to 8 that new context that's created now creates pathing conflicts with servlets under the same base URI. example servlet under /custom/route/myservlet can never be reached because the path match will grab the /custom/route context and my servlet isn't registered to that context. Those outside dependencies can change their path and I'd prefer to not have to register to those outside contexts. I've tried creating my own context to match i.e. create a new servletcontexthelper with the path /custom/route but then my servlets cannot be found ( presumably the precedence of the context created by the WAB wins out ).

So I've tried a lot of different solution at this point but they all don't work for one reason or another.

Can those WABs be registered under the default context (thus making the path matching work for the wab and servlets)? I've tried this with a DefaultServlet but then the resources aren't being served. Or is there a way to have the servlets take priority on the path matching even with the WABs being on their /custom/route context?

I've created an application with an external dependency that registers WABs. The WABs are created with a manifest.mf that contains the desired Web-ContextPath: '/custom/route' configuration. This works to register a new context and serve it's contents on that path. However with the move from pax web 7 to 8 that new context that's created now creates pathing conflicts with servlets under the same base URI. example servlet under /custom/route/myservlet can never be reached because the path match will grab the /custom/route context and my servlet isn't registered to that context. Those outside dependencies can change their path and I'd prefer to not have to register to those outside contexts. I've tried creating my own context to match i.e. create a new servletcontexthelper with the path /custom/route but then my servlets cannot be found ( presumably the precedence of the context created by the WAB wins out ).

So I've tried a lot of different solution at this point but they all don't work for one reason or another.

Can those WABs be registered under the default context (thus making the path matching work for the wab and servlets)? I've tried this with a DefaultServlet but then the resources aren't being served. Or is there a way to have the servlets take priority on the path matching even with the WABs being on their /custom/route context?

Share Improve this question asked Mar 21 at 20:45 SteveSteve 1511 gold badge1 silver badge7 bronze badges 1
  • This deserves serious explanation, which I'll provide later. For now: 1) be sure I'll explain it on Monday, 2) Pax Web 8 is huge refactoring of Pax Web 7 and much more OSGi CMPN compliant, 3) there's one big violation of the spec and it it exactly the one you see - WABs "take over" contexts - the reason is however Servlet API specification which IMO is more important than OSGi CMPN. – Grzegorz Grzybek Commented Mar 22 at 7:32
Add a comment  | 

1 Answer 1

Reset to default 1

Some justification at code level is provided here:

  • https://github/ops4j/.ops4j.pax.web/issues/1725
  • https://github/ops4j/.ops4j.pax.web/commit/b6cf8baa12abcd0c443c6d8430c0964e6cefe3e9

Let me clarify the issue you're seeing. You have a Web Application Bundle (as defined by OSGi CMPN Web Applications specification) with:

Web-ContextPath: /custom/route

header in META-INF/MANIFEST.MF.

At the same time you have a servlet mapped to /custom/route/myservlet URI (prefix mapping).

The problem here is that there are two worlds of Java web specifications:

  • Jakarta Servlet API - the specification that made Java an Enterprise-grade technology and ecosystem
  • 3 OSGi CMPN specification:
    • Chapter 102 - HttpService
    • Chapter 128 - Web Applications
    • Chapter 140 - Http Whiteboard

While OSGi web specifications are based on Servlet API, there's one clear difference:

  • Servlet API defines mapping URIs to components in a way, that the longest prefix path is matched against available contexts (you can think about context as single web application - like single WAR archive dropped to Tomcat's webapps directory)
  • OSGi specification (particularly the Whiteboard specification, section 140.2 The Servlet Context) allows kind of cross matching - if a URI is first matched to some context and there's no internal component (like servlet) in this context, shorter context is matched.

So if you have two contexts:

  • /my/context
  • /my

And you have URI /my/context/someServlet, then under Servlet API, if there's no /someServlet mapping in /my/context, there's no attempt to find a servlet mapped to /context/someServlet under /my context. However this is not true in OSGi Whiteboard specification.

Because Pax Web puts emphasis on using real Servlet containers (Jetty, Tomcat, Undertow), I decided to explicitly violate OSGi CMPN 140 Whiteboard specification to be more compliant with Servlet API specification. Mind that Felix HTTP implementation of the same OSGi specifications is based on single dispatcher servlet registered under single context in Jetty - this gives you more freedom and less benefits from underlying Servlet container.

There's however a way to make your scenario work. Instead of having:

  • WAB with /custom/route context
  • Servlet mapped to /custom/route/myservlet path under (implicit here!) / _context

you should have:

  • WAB with /custom/route context
  • Servlet mapped to /myservlet path under (explicit here!) /custom/route _context

While it seems that you have to put your servlet into your WAB, you can actually have the servlet registered to some other existing context (whether it's a context from existing WAB or other Whiteboard component).

So your servlet has to be registered with these OSGi Service properties:

  • osgi.http.whiteboard.servlet.pattern=/myservlet - for servlet mapping within some context
  • osgi.http.whiteboard.context.select=(osgi.http.whiteboard.context.path=/custom/route) - to tell Pax Web that this servlet has to be registered within ServletContextHelper mapped to /custom/route context path

Remember - with Whiteboard, if you don't specify osgi.http.whiteboard.context.select property, it defaults to osgi.http.whiteboard.context.select=(osgi.http.whiteboard.context.name=default) which is usually a kind of implicit context with / path.

See this Pax Web integration tests where WAB and Whiteboard are mixed together.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744334011a4569025.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信