I have an application with an embedded jetty server which I'm starting up like this (placed in main() and launched with eclipse):
Server server = new Server(port);
WebAppContext context = new WebAppContext();
context.setResourceBase("web/");
context.setDescriptor("web/WEB-INF/web.xml");
context.setConfigurations(new Configuration[]{
new AnnotationConfiguration(), new WebXmlConfiguration(),
new WebInfConfiguration(), new TagLibConfiguration(),
new PlusConfiguration(), new MetaInfConfiguration(),
new FragmentConfiguration(), new EnvConfiguration()});
context.setContextPath("/");
context.setParentLoaderPriority(true);
server.setHandler(context);
server.start();
server.join();
My web.xml looks like this (empty for now, I'm not sure if I can remove it completely):
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
metadata-complete="false"
version="3.0">
</web-app>
And I have a simple class set up like this:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(urlPatterns={"/test"})
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/html/index.html").forward(request,response);
}
}
My application works fine when I use traditional servlet mappings in web.xml. But when I remove the web.xml mappings and use annotations, I only get 404s. It doesn't look like it's scanning for annotations at all. The console looks like this:
2012-08-01 17:40:37.021:INFO:oejs.Server:jetty-8.1.5.v20120716
2012-08-01 17:40:37.227:INFO:oejpw.PlusConfiguration:No Transaction manager found - if your webapp requires one, please configure one.
2012-08-01 17:40:37.294:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.547:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.547:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.547:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.641:INFO:oejs.AbstractConnector:Started [email protected]:8080
Some things that I have checked already from my research:
I've run out of ideas and am about to just revert back to the old web.xml, but it's killing me why I can't get this to work.
Update: June 2021
The example project has been updated to be Jetty version neutral.
https://github.com/jetty-project/embedded-servlet-server
It has branches for specific versions of Jetty now.
The older example projects have been archived.
Update: June 2015
The example project has been updated for Jetty 9 and Servlet 3.1
See: https://github.com/jetty-project/embedded-servlet-3.1
Original Answer:
From your description, and a sample project I whipped up using your code, you are doing everything correctly.
Sample project: https://github.com/jetty-project/embedded-servlet-3.0
In order for this to work, you'll want the following (only mentioning this as your question didn't include this detail)
Just from these limited requirements you'll see the following list of dependencies present.
$ mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building sample-webapp 1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ sample-webapp ---
[INFO] com.company.sample:sample-webapp:war:1-SNAPSHOT
[INFO] +- org.eclipse.jetty.orbit:javax.servlet:jar:3.0.0.v201112011016:provided
[INFO] +- org.eclipse.jetty:jetty-webapp:jar:8.1.5-SNAPSHOT:test
[INFO] | +- org.eclipse.jetty:jetty-xml:jar:8.1.5-SNAPSHOT:test
[INFO] | | \- org.eclipse.jetty:jetty-util:jar:8.1.5-SNAPSHOT:test
[INFO] | \- org.eclipse.jetty:jetty-servlet:jar:8.1.5-SNAPSHOT:test
[INFO] | \- org.eclipse.jetty:jetty-security:jar:8.1.5-SNAPSHOT:test
[INFO] | \- org.eclipse.jetty:jetty-server:jar:8.1.5-SNAPSHOT:test
[INFO] | +- org.eclipse.jetty:jetty-continuation:jar:8.1.5-SNAPSHOT:test
[INFO] | \- org.eclipse.jetty:jetty-http:jar:8.1.5-SNAPSHOT:test
[INFO] | \- org.eclipse.jetty:jetty-io:jar:8.1.5-SNAPSHOT:test
[INFO] \- org.eclipse.jetty:jetty-annotations:jar:8.1.5-SNAPSHOT:test
[INFO] +- org.eclipse.jetty:jetty-plus:jar:8.1.5-SNAPSHOT:test
[INFO] | +- org.eclipse.jetty.orbit:javax.transaction:jar:1.1.1.v201105210645:test
[INFO] | \- org.eclipse.jetty:jetty-jndi:jar:8.1.5-SNAPSHOT:test
[INFO] | \- org.eclipse.jetty.orbit:javax.mail.glassfish:jar:1.4.1.v201005082020:test
[INFO] | \- org.eclipse.jetty.orbit:javax.activation:jar:1.1.0.v201105071233:test
[INFO] +- org.eclipse.jetty.orbit:javax.annotation:jar:1.1.0.v201108011116:test
[INFO] \- org.eclipse.jetty.orbit:org.objectweb.asm:jar:3.1.0.v200803061910:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.771s
[INFO] Finished at: Fri Aug 10 18:17:46 MST 2012
[INFO] Final Memory: 6M/180M
[INFO] ------------------------------------------------------------------------
It is quite likely that you are just missing a dependency or JDK requirement.
AnntationConfiguration
class scans annotations via its scanForAnnotations(WebAppContext)
method.
In the method AnnotationConfiguration
class scans following path.
So if you want your servlet classes in your production code(i.e. the sources in the directory src/main/java
) to be scanned, add your production code into the WebAppContext
's metadata as WEB-INF/classes
.
Try the code bellow, for adding your code into WebAppContext
's metadata.
URL classes = getClass()
.getProtectionDomain()
.getCodeSource()
.getLocation();
WebAppContext context = new WebAppContext();
context.getMetaData()
.setWebInfClassesDirs(
Arrays.asList(Resource.newResource(classes)));
I had this same problem, but after many reads I got the solution! IMPORTANT: remember to have in your build path the following jars:
jetty-all-9.0.6.v20130930.jar
jetty-annotations-9.0.6.v20130930.jar
org.objectweb.asm-3.1.0.v200803061910.jar
javax.servlet-api-3.0.1.jar
jetty-plus-9.0.6.v20130930.jar
public class Main {
public static void main(String[] args) throws Exception {
//Create the server
Server server = new Server(8080);
ClassList clist = ClassList.setServerDefault(server);
//clist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration", "org.eclipse.jetty.plus.webapp.EnvConfiguration", "org.eclipse.jetty.plus.webapp.PlusConfiguration");
clist.addBefore(JettyWebXmlConfiguration.class.getName(), AnnotationConfiguration.class.getName());
//Here is the trick to scan current classpath!
webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/build/classes/");
webapp.setContextPath("/");
webapp.setResourceBase("./WebContent");
server.setHandler(webapp);
server.start();
server.join();
}
}
Based on the previous example provided by Joakim, I've uploaded a modified version that supports annotations in an embedded jetty without packaging the project into a war file. This project is ready to deploy to Heroku just running:
$java -cp target/classes:"target/dependency/*" com.example.Launcher
If you are interested in the details, the important lines are these ones from com.example.Launcher:
context.setConfigurations(new Configuration[] {
new AnnotationConfiguration(), new WebXmlConfiguration(),
new WebInfConfiguration(),
new PlusConfiguration(), new MetaInfConfiguration(),
new FragmentConfiguration(), new EnvConfiguration() });
// Important! make sure Jetty scans all classes under ./classes looking for annotations.
//'Classes' directory is generated running 'mvn package'
context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*/classes/.*");
You can change accordingly the JarPattern depending on the classes you want to scan for annotations.
Here you have the full example: https://github.com/pablormier/embedded-jetty-annotations-example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With