Hello
Pax Web 8 is (modestly speaking) a huge refactoring of Pax Web 7 - mostly
with respect to context handling for Whiteboard specification.
I expected that after the upgrade/refactoring, some existing configs and
setups will stop working - I tried hard (adding hundreds of new integration
tests) to ensure that new behavior is consistent and compliant to all
specifications (Servlet API, Whiteboard, HttpService, WAB).
*1. Explaining why your configuration doesn't work*
All your four setups use "org.eclipse.jetty.servlet.ServletContextHandler"
class which are "almost" full web applications - that's why you've
correctly assumed you can add a servlet there. However Pax Web 8 uses
org.ops4j.pax.web.service.jetty.internal.PaxWebServletContextHandler
extension of org.eclipse.jetty.servlet.ServletContextHandler which adds A
LOT - mostly related to classloading.
I tried your config and simply org.eclipse.jetty.servlet.DefaultServlet
wasn't found by system class loader - no wonder...
*2. Suggesting better solution*
Jetty (I found it to be ... the most flexible of the 3 embeddable runtimes:
Jetty, Tomcat, Undertow) has a nice hierarchy of "handlers":
AbstractHandler (org.eclipse.jetty.server.handler)
AbstractHandlerContainer (org.eclipse.jetty.server.handler)
HandlerWrapper (org.eclipse.jetty.server.handler)
ScopedHandler (org.eclipse.jetty.server.handler)
ContextHandler (org.eclipse.jetty.server.handler)
ServletContextHandler (org.eclipse.jetty.servlet)
PaxWebServletContextHandler
(org.ops4j.pax.web.service.jetty.internal)
WebAppContext (org.eclipse.jetty.webapp)
And if you need resources, you can just use
org.eclipse.jetty.server.handler.ContextHandler.
Here's the config which I checked that works:
<Get name="handler">
<Call name="addHandler">
<Arg>
<New class="org.eclipse.jetty.server.handler.ContextHandler">
<Set name="resourceBase">/var/html/test</Set>
<Set name="contextPath">/app</Set>
<Set name="handler">
<New
class="org.eclipse.jetty.server.handler.ResourceHandler">
<Set name="directoriesListed">true</Set>
</New>
</Set>
</New>
</Arg>
</Call></Get>
I hope this helps ;)
regards
Grzegorz Grzybek
pt., 24 lut 2023 o 03:57 Kevin Schmidt <[email protected]> napisaĆ(a):
> Hi,
>
> I came across this page (
> http://ops4j.github.io/pax/web/SNAPSHOT/User-Guide.html#adding-specialized-contexthandlers)
> in the Pax-Web documentation on how to configure Jetty to serve up static
> content.
>
> Trying it with Karaf 4.3.7 works, specifically I take a brand new instance
> and install the http and webconsole features, and then adding this to
> jetty.xml allows serving up files in /var/html/test at
> http://localhost:8181/app/....
>
> <Get name="handler">
>
> <Call name="addHandler">
>
> <Arg>
>
> <New class="org.eclipse.jetty.servlet.ServletContextHandler">
>
> <Set name="contextPath">/app</Set>
>
> <Set name="resourceBase">/var/html/test</Set>
>
> <Call name="addServlet">
>
> <Arg>org.eclipse.jetty.servlet.DefaultServlet</Arg>
>
> <Arg>/</Arg>
>
> </Call>
>
> </New>
>
> </Arg>
>
> </Call>
>
> </Get>
>
> However, trying the same thing with 4.4.3 fails. I did it in an instance
> with a bunch of features already installed and got this warning:
>
> 20230223 18:27:19.312 [WARN ] paxweb-config-3-thread-1 (change controller)
> | 268:org.eclipse.jetty.util:9.4.50.v20221201 |
> org.eclipse.jetty.xml.XmlConfiguration | Config error at <Call
> name="addHandler">
>
> <Arg>
>
> <New class="org.eclipse.jetty.servlet.ServletContextHandler">
>
> <Set name="contextPath">/app</Set>
>
> <Set name="resourceBase">/var/html/test</Set>
>
> <Call name="addServlet">
>
> <Arg>org.eclipse.jetty.servlet.DefaultServlet</Arg>
>
> <Arg>/</Arg>
>
> </Call>
>
> </New>
>
> </Arg>
>
> </Call>
>
> 20230223 18:27:19.313 [WARN ] paxweb-config-3-thread-1 (change controller)
> | 268:org.eclipse.jetty.util:9.4.50.v20221201 |
> org.eclipse.jetty.xml.XmlConfiguration | Config error at <Get
> name="handler">
>
> <Call name="addHandler">
>
> <Arg>
>
> <New class="org.eclipse.jetty.servlet.ServletContextHandler">
>
> <Set name="contextPath">/app</Set>
>
> <Set name="resourceBase">/var/html/test</Set>
>
> <Call name="addServlet">
>
> <Arg>org.eclipse.jetty.servlet.DefaultServlet</Arg>
>
> <Arg>/</Arg>
>
> </Call>
>
> </New>
>
> </Arg>
>
> </Call>
>
> </Get>
>
> My Karaf 4.3.7 has Jetty 9.4.46 and Pax Web 7.3.25 while Karaf 4.4.3 has
> Jetty 9.4.50 and Pax Web 8.0.15
>
> Did something change with Jetty config that this is no longer valid? I
> wouldn't think so with the change from 9.4.46 to 9.4.50 but it clearly
> doesn't work.
>
> I tried changing the section in jetty.xml to this, using insertHandler
> instead:
>
> <Call name="insertHandler">
>
> <Arg>
>
> <New class="org.eclipse.jetty.servlet.ServletContextHandler">
>
> <Set name="contextPath">/app</Set>
>
> <Set name="resourceBase">/var/html/test</Set>
>
> <Call name="addServlet">
>
> <Arg>org.eclipse.jetty.servlet.DefaultServlet</Arg>
>
> <Arg>/</Arg>
>
> </Call>
>
> </New>
>
> </Arg>
>
> </Call>
>
> This doesn't have a config error, but instead fails finding the
> DefaultServlet class.
>
> 20230223 18:48:04.276 [WARN ] paxweb-config-3-thread-1 (change controller)
> | 268:org.eclipse.jetty.util:9.4.50.v20221201 |
> org.eclipse.jetty.servlet.BaseHolder |
>
> java.lang.ClassNotFoundException: org.eclipse.jetty.servlet.DefaultServlet
>
> at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
> ~[?:1.8.0_352]
>
> at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_352]
>
> at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
> ~[?:1.8.0_352]
>
> at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_352]
>
> at org.eclipse.jetty.util.Loader.loadClass(Loader.java:64) ~[?:?]
>
> at org.eclipse.jetty.servlet.BaseHolder.doStart(BaseHolder.java:89) ~[?:?]
>
> at org.eclipse.jetty.servlet.ServletHolder.doStart(ServletHolder.java:369)
> ~[?:?]
>
> at
> org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
> ~[?:?]
>
> at
> org.eclipse.jetty.servlet.ServletHandler.lambda$initialize$0(ServletHandler.java:749)
> ~[?:?]
>
> at java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357)
> ~[?:1.8.0_352]
>
> at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:483)
> ~[?:1.8.0_352]
>
> at
> java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
> ~[?:1.8.0_352]
>
> at
> java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:313)
> ~[?:1.8.0_352]
>
> at
> java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:743)
> ~[?:1.8.0_352]
>
> at
> java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:647)
> ~[?:1.8.0_352]
>
> at
> org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:774)
> ~[?:?]
>
> at
> org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:379)
> ~[?:?]
>
> at
> org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:916)
> ~[?:?]
>
> at
> org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:288)
> ~[?:?]
>
> at
> org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
> ~[?:?]
>
> at
> org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:169)
> ~[?:?]
>
> at org.eclipse.jetty.server.Server.start(Server.java:423) ~[?:?]
>
> at
> org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:110)
> ~[?:?]
>
> at
> org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:97)
> ~[?:?]
>
> at org.eclipse.jetty.server.Server.doStart(Server.java:387) ~[?:?]
>
> at
> org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:73)
> ~[?:?]
>
> at
> org.ops4j.pax.web.service.jetty.internal.JettyServerWrapper.start(JettyServerWrapper.java:623)
> ~[?:?]
>
> at
> org.ops4j.pax.web.service.jetty.internal.JettyServerController.start(JettyServerController.java:109)
> ~[?:?]
>
> at
> org.ops4j.pax.web.service.internal.Activator.performConfiguration(Activator.java:555)
> ~[?:?]
>
> at
> org.ops4j.pax.web.service.internal.Activator.updateController(Activator.java:445)
> ~[?:?]
>
> at
> org.ops4j.pax.web.service.internal.Activator.lambda$updateServerControllerFactory$1(Activator.java:347)
> ~[?:?]
>
> at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
> ~[?:1.8.0_352]
>
> at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_352]
>
> at
> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
> ~[?:1.8.0_352]
>
> at
> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
> ~[?:1.8.0_352]
>
> at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
> ~[?:1.8.0_352]
>
> at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
> ~[?:1.8.0_352]
>
> at java.lang.Thread.run(Thread.java:750) ~[?:1.8.0_352]
>
> I had run across an earlier issue with Pax Web 8 missing a package import (
> https://github.com/ops4j/org.ops4j.pax.web/issues/1817) so is this
> another one? Or what is the correct way to configure serving static
> content in jetty.xml with Karaf 4.4 / Pax Web 8?
>
> Thanks,
>
> Kevin
>
>