You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@karaf.apache.org by Kevin Schmidt <kt...@gmail.com> on 2023/02/24 02:56:27 UTC

Serving static content with Jetty in Karaf 4.4

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

Re: Serving static content with Jetty in Karaf 4.4

Posted by Grzegorz Grzybek <gr...@gmail.com>.
Hello

The documentation, after release of Pax Web 8 is quite outdated... I was
thinking about it since I started the refactoring, but you know... Feel
free to contribute and/or to open a GitHub ticket.

regards
Grzegorz Grzybek

pt., 24 lut 2023 o 14:35 Kevin Schmidt <kt...@gmail.com> napisał(a):

> Thanks!  That did the trick.
>
> Does an issue need to be opened to get the documentation link I posted up
> to date?
>
> On Thu, Feb 23, 2023 at 11:01 PM Grzegorz Grzybek <gr...@gmail.com>
> wrote:
>
>> 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 <kt...@gmail.com> 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
>>>
>>>

Re: Serving static content with Jetty in Karaf 4.4

Posted by Kevin Schmidt <kt...@gmail.com>.
Thanks!  That did the trick.

Does an issue need to be opened to get the documentation link I posted up
to date?

On Thu, Feb 23, 2023 at 11:01 PM Grzegorz Grzybek <gr...@gmail.com>
wrote:

> 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 <kt...@gmail.com> 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
>>
>>

Re: Serving static content with Jetty in Karaf 4.4

Posted by Grzegorz Grzybek <gr...@gmail.com>.
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 <kt...@gmail.com> 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
>
>