Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable CachingWebAppClassLoader in Jetty Maven Plugin?

I'm trying to improve startup performance of a Java web app in development environment. It uses jetty-maven-plugin and mvn jetty:run is used to start the app.

I followed instructions at http://www.eclipse.org/jetty/documentation/9.3.x/jetty-classloading.html to register this new CachingWebAppClassLoader.

<Configure id="mywebapp" class="org.eclipse.jetty.webapp.WebAppContext">

...

  <Set name="classLoader">
    <New class="org.eclipse.jetty.webapp.CachingWebAppClassLoader">
      <Arg><Ref refid="mywebapp"/></Arg>
    </New>
  </Set>

...
</Configure>

However, org.eclipse.jetty.webapp.WebAppClassLoader.* continued to show up in jvisualvm CPU sampler but not the CachingWebAppClassLoader

I verified that my registration of classloader is at least being discovered by supplying an invalid class name in which case ClassNotFoundException was thrown. I'm guessing my configuration of classloader is being consumed but not being used or something like that. Any ideas?

In addition, please let me know if you are aware of any other variants of classloaders that could be used to improve performance.

like image 985
phanin Avatar asked Apr 05 '17 00:04

phanin


1 Answers

jetty-maven-plugin uses a specialized WebAppContext, called JettyWebAppContext:

JettyWebAppContext Extends the WebAppContext to specialize for the maven environment.

So your WebAppContext binding in jetty.xml is created but is then left unused.

An obvious workaround would be to set your WebApplicationContext class to org.eclipse.jetty.maven.plugin.JettyWebAppContext in your jetty.xml, but unfortunately this does not work:

You can define your resourcehandler in jetty.xml, however you shouldn't define your webapp in jetty.xml, as the purpose of the jetty maven plugin is to make development easier by automatically deploying your unassembled webapp. So if you take your webapp definition out of jetty.xml things should work.

Another possible workaround would have been to set the classLoader property on the defaultJettyWebAppContext instance in your pom.xml, using webApp configuration element as described here:

<webApp>         
    <classLoader>org.eclipse.jetty.webapp.CachingWebAppClassLoader</classLoader>
</webApp>  

Unfortunately that won't work either, as CachingWebAppClassLoader constructor requires a reference to the underlying WebAppClassLoader.Context, so it will fail to be instantiated.

I'm not sure if there is any other workaround for this (maybe using an additional contextHandler will do it), but even if you manage to make it work with a caching classloader, that will probably break the change detection and hot redeploy, which is basically the core idea behind the jetty-maven-plugin:

This goal is used in-situ on a Maven project without first requiring that the project is assembled into a war, saving time during the development cycle.

...

Once invoked, the plugin can be configured to run continuously, scanning for changes in the project and automatically performing a hot redeploy when necessary. This allows the developer to concentrate on coding changes to the project using their IDE of choice and have those changes immediately and transparently reflected in the running web container, eliminating development time that is wasted on rebuilding, reassembling and redeploying.

So I'm not sure if that would be a good idea anyway.

like image 61
zeppelin Avatar answered Nov 16 '22 18:11

zeppelin