Issue
Eclipse automatically adds all Maven dependencies to the class path.
How can I get Jetty to scan the jar files on the class path for web fragments, when started from Eclipse?
When packaged and placed in webapp/WEB-INF/lib/*.jar, the scanning works.
Server server = new Server(8080);
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/myapp");
webapp.setBaseResource(Resource.newResource(new File("webapp")));
// https://stackoverflow.com/questions/11768113/cant-get-jetty-to-scan-for-annotated-classes
webapp.setConfigurations(new Configuration[] { //
new AnnotationConfiguration(), // @WebServlet, @WebListener...
new WebXmlConfiguration(), // webapp/WEB-INF/web.xml
new WebInfConfiguration(), // ?
new MetaInfConfiguration(), // ?
new FragmentConfiguration(), // e.g. zkwebfragment-9.6.0.1.jar!/META-INF/web-fragment.xml
});
if(RUNNING_FROM_IDE)
{
// add project classes to classpath (e.g. target/classes)
webapp.getMetaData().setWebInfClassesDirs(Arrays.asList(Resource.newResource(MyAppMainClass.class.getProtectionDomain().getCodeSource().getLocation())));
// how to add maven dependencies?
// webapp.getMetaData().addWebInfJar(???);
}
server.setHandler(webapp);
server.start();
Solution
Don't manually set the configurations, that's the first mistake.
Your effort basically broke the configurations, as you didn't respect the original default configurations, or the delicate order requirements.
This is wrong way, by setting the webapp configurations directly.
webapp.setConfigurations(new Configuration[] { //
new AnnotationConfiguration(), // @WebServlet, @WebListener...
new WebXmlConfiguration(), // webapp/WEB-INF/web.xml
new WebInfConfiguration(), // ?
new MetaInfConfiguration(), // ?
new FragmentConfiguration(), // e.g. zkwebfragment-9.6.0.1.jar!/META-INF/web-fragment.xml
});
This is the correct way, by adjusting the default Configuration list at the Server level.
Configuration.ClassList classlist = Configuration.ClassList
.setServerDefault(server);
classlist.addBefore(
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration");
This should be enough.
You can see the default configuration order on the server dump.
server.setDumpAfterStart(true);
server.start();
// and then on the output (see your logger) ...
| | | +> Configurations Servlet Dump WebApp@4c163e3 size=5
| | | | +> org.eclipse.jetty.webapp.WebInfConfiguration@5e403b4a
| | | | +> org.eclipse.jetty.webapp.WebXmlConfiguration@5117dd67
| | | | +> org.eclipse.jetty.webapp.MetaInfConfiguration@5be49b60
| | | | +> org.eclipse.jetty.webapp.FragmentConfiguration@2931522b
| | | | +> org.eclipse.jetty.webapp.JettyWebXmlConfiguration@7674b62c
| | | +> Handler attributes Servlet Dump WebApp@4c163e3 size=3
This dump feature is useful, as it will likely tell you that the the $HOME/.m2/repository
jar files are not present in the webapp's own classpath.
| | | +> WebAppClassLoader{Servlet Dump WebApp}@5fb759d6
| | | | +> URLs size=1
| | | | | +> file:/tmp/jetty-0_0_0_0-8080-ROOT_war-_-any-15598896298108484560/webapp/WEB-INF/classes/
If you don't see your maven repository files here, then it's time for you to configure your WebAppContext.setExtraClasspath(String)
to include them before you start your webapp.
Another feature to be aware of are the 2 scan regexes used to identify which content (class files) are scanned. One for the webapp classes, and one for the server classes. Both of these are relevant for the discovery of anything in the servlet spec, be it annotated listeners, annotated servlets, web fragments, servlet container initializers, jsp level details, websocket level details, etc)
Both are set as attributes on the WebAppContext.setAttribute(String key, String value)
if you want to configure them.
By default, these values are empty, meaning all jars are scanned.
// This one controls server/container level discovery.
// An example of limited scanning would be
webappContext.setAttribute(
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern"
".*/[^/]*servlet-api-[^/]*\\.jar$|.*[^/]*jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");
// This one controls webapp specific discovery.
webappContext.setAttribute(
"org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern"
".*/[^/]*foo-[^/]*\\.jar$|.*/[^/]*bar.*\\.jar$");
An example of this would be ...
You have a webapp with ...
WEB-INF/lib/
foo-api-1.2.3.jar
foo-1.2.3.jar
bar-0.9.jar
boo-1.0.jar
And defined the webapp scanning like ...
webappContext.setAttribute(
"org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern",
".*/.*foo-api-[^/]\.jar$|./.*bar-[^/]\.jar$|./.*wibble[^/]*\.jar$");
Then the following files would match and be scanned:
WEB-INF/lib/
foo-api-1.2.3.jar
bar-0.9.jar
Answered By - Joakim Erdfelt
Answer Checked By - Mary Flores (JavaFixing Volunteer)