Plan to release Pax Web 8 + some information

181 views
Skip to first unread message

Grzegorz Grzybek

unread,
Sep 13, 2021, 6:27:49 AM9/13/21
to op...@googlegroups.com, Karaf Dev
Hello!

After almost 2 years of refactoring and development, I think Pax Web 8 is ready for release.
Manual updates are still on my list and some exhaustive documentation (and maybe a blog post) is being prepared...

TL;DR:

 - `mvn clean install -DskipTests` in `main` branch of https://github.com/ops4j/org.ops4j.pax.web
 - start with clean Karaf 4.3.3

karaf@root()> repo-remove org.ops4j.pax.web-7.3.19
karaf@root()> repo-add mvn:org.ops4j.pax.web/pax-web-features/8.0.0-SNAPSHOT/xml/features
karaf@root()> feature:install pax-web-http-tomcat
karaf@root()> feature:install pax-web-war
karaf@root()> bundle:install -s 'webbundle:mvn:io.hawt/hawtio-war/2.13.6/war?Web-ContextPath=/hawtio'


However I think it'd be good to describe the rationale behind the rewrite and some key points of the new release.

Background information:

My single, initial reason to start the refactoring was https://github.com/ops4j/org.ops4j.pax.web/issues/1413 issue (migrated from https://ops4j1.jira.com/browse/PAXWEB-1123): "HTTP Whiteboard and selection of the ServletContextHelper".

Whiteboard specification says, that every web element may reference a target ServletContextHelper using "osgi.http.whiteboard.context.select" service registration property and its value is an LDAP filter, which may also be:

osgi.http.whiteboard.context.select=(osgi.http.whiteboard.context.name=*)

which means "register the servlet into ALL available ServletContextHelpers".
Pax Web 7 was taking the osgi.http.whiteboard.context.select property value and was doing split("=") on it to get the name/id of the target context... Effectively 1:1 relation was assumed, while Whiteboard specification assumes 1:N relationship.

So I started to rewrite the internal Pax Web model... And somehow much much more was refactored.

Pax Web 8 goals:
  • I've carefully read chapters 102 (Http Service specification), 128 (Web Applications specification) and 140 (Whiteboard specification) of OSGi CMPN R7 and tried to implement everything in best possible way
  • I always appreciated how well and cleverly Pax Web was written by others from this list:
11:41 $ git shortlog -snc origin/pax-web-7.2.x
   894  adreg...@gmail.com
   747  anierbeck
   284  Achim Nierbeck
   182  ANierbeck
   123  Guillaume Nodet
   114  Jean-Baptiste Onofré
   103  Marc Schlegel
    77  jbonofre
    53  lostiniceland
    44  Stephan Siano
    37  Harald Wellmann
    21  Marc Klinger
    20  Freeman Fang
...
  • I wanted to keep the "spirit" of Pax Web - emphasizing target runtime (Jetty, Tomcat, Undertow) over "specification first" approach
  • I wanted to ensure that everything in Pax Web works as similar as possible in all 3 supported runtimes
  • I wanted to keep the possibility to use native container configuration (jetty.xml, tomcat-server.xml, undertow.xml) in addition to what we can pass through org.ops4j.pax.web PID
  • I wanted to make Pax Web 8 more reliable (no more flaky tests, no more random Thread.sleep() in tests, ...)
Pax Web 8 highlights:
  • Latest versions of Jetty 9.4.x, Tomcat 9.0.x (without TIPI!) and Undertow 2.2.x are used
  • Web "elements" mentioned in Http Service and Whiteboard specifications are handled: servlets, filters, listeners, error pages
  • additionally, Pax Web 8 supports everything that can be configured in web.xml besides: <env-entry>, <post-construct>, <pre-destroy>, <resource-env-ref>, <resource-ref>, <administered-object>, <connection-factory>, <data-source>, <default-context-path>, <description>, <ejb-local-ref>, <ejb-ref>, <icon>, <jms-connection-factory>, <jms-destination>, <mail-session>, <message-destination>, <message-destination-ref>, <module-name>, <persistence-context-ref>, <persistence-unit-ref>, <service-ref>
  • "above" what we can find in web.xml, Pax Web 8 supports:
    • ServletContainerInitializers (SCI) - proved by working JSF/Primefaces/Vaadin examples
    • web-fragment.xmls
    • annotated web elements (@WebServlet, @WebFilter, @WebListener)
    • META-INF/resources locations
    • websockets via HttpService and Whiteboard
    • web fragment scanning using tomcat-util-scanner
  • without any mention in any CMPN specification, JSPs, welcome-pages, security configurations are supported
  • no more xbean used to scan the "class space"
  • no more dependency to ASM
  • single configuration thread that operates on global model and synchronizes the model changes with the state of target runtime (Jetty, Tomcat, Undertow)
  • consistent structure of pax-web-jetty, pax-web-tomcat and pax-web-undertow:
    • there's single org.ops4j.pax.web.service.<runtime>.internal.<Runtime>ServerController class (per runtime) implementing org.ops4j.pax.web.service.spi.ServerController#sendBatch() method
    • org.ops4j.pax.web.service.spi.task.Batch is a sequence of "operations" that change the model or affect the runtime
    • there's single org.ops4j.pax.web.service.<runtime>.internal.<Runtime>ServerWrapper class (per runtime) that:
      • keeps an instance of the "server" (org.eclipse.jetty.server.Server, org.apache.catalina.core.StandardServer or io.undertow.server.HttpHandler + collection of org.xnio.channels.AcceptingChannels) - Pax Web 8 DOESN'T use easy-to-use io.undertow.Undertow class!
      • implements org.ops4j.pax.web.service.spi.task.BatchVisitor interface that's used to react to state-changing operations (like registration of a servlet) - mind that a "batch" may be "transactional"
    • each runtime bundle contains some overriden runtime classes (like org.ops4j.pax.web.service.jetty.internal.PaxWebFilterHolder that extends org.eclipse.jetty.servlet.FilterHolder)
  • Knowing that we have 3 "ways into" the Pax Web (HttpService, Whiteboard, WABs), Pax Web 8 introduces the concept of "the view of the WebContainer" - each "way" uses specific "view" to interact with Pax Web runtime
  • The model is greatly simplified comparing to Pax Web 7:
    • there exist "model" classes (like org.ops4j.pax.web.service.spi.model.elements.ServletModel) which are held internall and passed around between whiteboard, war, runtime and target container bundles
    • from Whiteboard perspective, the "incoming" services, like "javax.servlet.Servlet" or "org.osgi.service.http.context.ServletContextHelper" are "tracked into" the model classes, so whether the servlet is registered by HttpService, Whiteboard or through a WAB, its processing is consistent and there's no problem mixing WABs, Whiteboard and HttpService approaches
    • the "model" classes are divided into "web elements" and "web contexts" and each "web element" may reference one or many "web contexts" and the relation is dynamic
  • ...
Pax Web 8 example:

The most important use-case is:
  • user/bundle registers (Whiteboard approach) a servlet without specifying a "context" and the servlet has mapping "/my-servlet"
  • this servlet should be available at URL http://localhost:8181/my-servlet
  • another user/bundle registers a org.osgi.service.http.context.ServletContextHelper service with "osgi.http.whiteboard.context.path=/my-context" and "osgi.http.whiteboard.context.name=default" properties
  • immediately (asap) the first servlet should be available at http://localhost:8181/my-context/my-servlet and no longer it should be available at the first URL
Yes, it works. Also shadowing may happen, because when two servlets are registered with the same name and target context, only the one with higher ranking/lower service.id should be available. There are many integration tests that show what happens when conflicting services are registered across different contexts.

Summary:

If you have some time, please checkout https://github.com/ops4j/org.ops4j.pax.web/tree/main, `mvn clean -DskipTests` it and give it a try.

For example in Karaf 4.3.3 (after uncommenting "karaf" user in `etc/users.properties`) we can do:

karaf@root()> repo-remove org.ops4j.pax.web-7.3.19
Removing features repository: mvn:org.ops4j.pax.web/pax-web-features/7.3.19/xml/features
karaf@root()> repo-add mvn:org.ops4j.pax.web/pax-web-features/8.0.0-SNAPSHOT/xml/features
Adding feature url mvn:org.ops4j.pax.web/pax-web-features/8.0.0-SNAPSHOT/xml/features
karaf@root()> feature:install pax-web-http-tomcat
karaf@root()> feature:install pax-web-war
karaf@root()> bundle:install 'webbundle:mvn:io.hawt/hawtio-war/2.13.6/war?Web-ContextPath=/hawtio'
Bundle ID: 68
karaf@root()> start 68

Then you can log in to http://localhost:8181/hawtio using karaf/karaf credentials (JAAS based authentication) and then navigate to http://localhost:8181/hawtio/jmx/attributes?nid=root-Catalina-WebResourceRoot-localhost-%2FServletContextModel-3-Cache which shows cache configuration for the default (resource) servlet used by /hawtio WAB.

kind regards and thanks for the patience ;)
Grzegorz Grzybek

Achim Nierbeck

unread,
Sep 13, 2021, 9:42:49 AM9/13/21
to op...@googlegroups.com, Karaf Dev
Big Kudos to Grzegorz for not giving up on this in the last two years!

best 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.
To view this discussion on the web visit https://groups.google.com/d/msgid/ops4j/CAAdXmhpRUK%2B-0fSYnXMXUevpfuDDLgSqhLXdq83Tae3c6usnCQ%40mail.gmail.com.


--

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>

Reply all
Reply to author
Forward
0 new messages