This is my first web application, I am just trying to follow guides and launch my server with servlets specified at web.xml
, but it seems that my actions don't change functionality of the server and the result is 404 error. But if I programmatically specify servlets its OK. Could anyone figure it out how this all should work?
Here is my code for server
public class Launcher
{
public static void main(String[] args) throws Exception
{
Server server = new Server(8080);
WebAppContext web = new WebAppContext();
web.setContextPath("/");
web.setWar("src/main/web/WEB-INF/web.xml");
//web.addServlet(MyServlet.class,"/"); This line works just fine
server.setHandler(web);
server.start();
server.join();
}
}
And my web.xml looks like this
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>lab3.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>*</url-pattern>
</servlet-mapping>
</web-app>
The WEB-INF/web.xml
is the descriptor.
The call to WebAppContext.setWar(String)
is for the base resource location.
Note: The Base Resource location is mandatory. You must set it to a valid location so that the ServletContext
can function properly.
There are alternate APIs for setting the base resource location: you can use WebAppContext.setBaseResource(Resource)
and WebAppContext.setResourceBase(String)
as well, they mean the same thing.
If you want to specify the web descriptor location use WebAppContext.setDescriptor(String)
.
For your code example, it appears you want to use
Server server = new Server(8080);
WebAppContext web = new WebAppContext();
web.setContextPath("/");
web.setWar("src/main/web"); // TODO: resolve this to a an absolute path or URI!
server.setHandler(web);
server.start();
server.join();
About that TODO, see the examples at jetty-project/embedded-jetty-cookbook, specifically ...
- WebAppContextFromFileSystem.java
- WebAppContextFromClasspath.java
It's important to recognize that by default the classpath will be based off of the Base Resource location.
The classes will be looked up from ${base.resource.uri}/classes
.
I point this out, because we see the path src/main/web
in your example, I suspect you are trying to make a live (unbuilt) project in an IDE work. This kind of setup will require more manual work for you, as the base resource, and classes are in different locations.
In that case you'll need to specify where the classes are manually.
aka.
Server server = new Server(8080);
WebAppContext web = new WebAppContext();
web.setContextPath("/");
Path baseResource = new File("src/main/web").toPath();
Path classesDir = new File("target/thewebapp/WEB-INF/classes").toPath();
if (!Files.exists(baseResource))
throw new FileNotFoundException("Unable to find Base Resource Dir: " + baseResource);
if (!Files.exists(classesDir))
throw new FileNotFoundException("Unable to find Classes Dir: " + classesDir);
web.setBaseResource(new PathResource(baseResource.toAbsolutePath()));
web.setExtraClasspath(classesDir.toAbsolutePath().toString());
server.setHandler(web);
server.start();
server.join();
Finally I want to point out some other ways you can package a webapp up in embedded-jetty ...
embedded-jetty-uber-jar
https://github.com/jetty-project/embedded-jetty-uber-jar
This uses the ServletContextHandler
to manually build up a webapp, no WEB-INF/web.xml
is used, no bytecode scanning, no annotation scanning, and its blazingly fast to startup.
The above project builds a single jar with everything you need to run your webapp.
embedded-jetty-live-war
https://github.com/jetty-project/embedded-jetty-live-war
This project is a bit more complex, it builds 3 parts (webapp, server, bootstrap) and then assembles them together into a single war file.
This starts with a simple war, but then enhances it with a server preconfigured the way you want it. This new "live-war" is assembled as a new war file in a separate sub-project.
This war file can be deployed as normal, and it can be run directly as a standalone self-executing war file, complete with a full server instance.