Web Application Deployment
Most of the time you want to be able to customize the deployment of your web applications, for example by changing the contextPath
, or by adding JNDI entries, or by configuring virtual hosts, etc.
Jetty supports the deployment of each web application to a specific environment. The available environments are:
-
Java EE 8 — Supports Servlet 4.0 (and associated specifications) in the
javax.*
packages. -
Jakarta EE 9 — Supports Servlet 5.0 (and associated specifications) in the
jakarta.*
packages. -
Jakarta EE 10 — Supports Servlet 6.0 (and associated specifications) in the
jakarta.*
packages. -
Jetty Core — Supports web applications written against the Jetty
Handler
APIs, without any Servlet dependencies.
This means that you can simultaneously deploy an old Java EE 8 web application, say old-ee8.war
, alongside a new Jakarta EE 10 web application, say new-ee10.war
, alongside a web application that only uses the Jetty Handler
APIs, say app-jetty.xml
.
The customization of the deployment (for example, web application context path, etc.) is performed by processing Jetty context XML files.
The deploy
module contains the DeploymentManager
component that scans the $JETTY_BASE/webapps
directory for changes, following the deployment rules described in this section.
For each specific environment there is a specific deploy module that you must enable:
-
For Java EE 8,
ee8-deploy
-
For Java EE 9,
ee9-deploy
-
For Java EE 10,
ee10-deploy
-
For Jetty Core,
core-deploy
Each of these modules provide the environment specific features, and depend on the deploy
module that provides the scanning features.
Hot vs Static Deployment
The DeploymentManager
scans the $JETTY_BASE/webapps
directory for changes every N
seconds, where N
is configured via the jetty.deploy.scanInterval
property.
By default, the scan interval is 0
seconds, which means static deployment, and the DeploymentManager
will not scan the $JETTY_BASE/webapps
directory for changes.
This means that to deploy/redeploy/undeploy a web application you will need to stop and restart Jetty.
Setting the scan interval to a value of 1
second (or greater) means that hot deployment is enabled: if a file is added/changed/removed from the $JETTY_BASE/webapps
directory, the DeploymentManager
will notice the change and respectively deploy/redeploy/undeploy the web application.
The following command line enables hot deployment by specifying the jetty.deploy.scanInterval
property on the command line, and therefore only for this particular run:
$ java -jar $JETTY_HOME/start.jar jetty.deploy.scanInterval=1
To make hot deployment persistent, you need to edit the appropriate <env>-deploy
module configuration file, $JETTY_BASE/start.d/<env>-deploy.ini
(eg: ee10-deploy.ini
), uncomment the module property jetty.deploy.scanInterval
and change the value to 1
second (or greater):
--module=deploy
jetty.deploy.scanInterval=1
...
Deployment Rules
Adding a *.war
file, a *.war
directory, a Jetty context XML file or a normal directory to $JETTY_BASE/webapps
causes the DeploymentManager
to deploy the new web application.
Updating a *.war
file or a Jetty context XML file causes the DeploymentManager
to redeploy the web application, which means that the Jetty context component representing the web application is stopped, then reconfigured, and then restarted.
Removing a *.war
file, a *.war
directory, a Jetty context XML file or a normal directory from $JETTY_BASE/webapps
causes the DeploymentManager
to undeploy the web application, which means that the Jetty context component representing the web application is stopped and removed from the Jetty server.
Context Path Resolution
When a file or directory is added to $JETTY_BASE/webapps
, the DeploymentManager
derives the web application contextPath
from the file or directory name, with the following rules:
-
If the directory name is, for example,
mywebapp/
, it is deployed as a standard web application if it contains aWEB-INF/
subdirectory, otherwise it is deployed as a web application of static content. ThecontextPath
would be/mywebapp
(that is, the web application is reachable athttp://localhost:8080/mywebapp/
). -
If the directory name is
ROOT
, case-insensitive, thecontextPath
is/
(that is, the web application is reachable athttp://localhost:8080/
). -
If the directory name ends with
.d
, for exampleconfig.d/
, it is ignored, although it may be referenced to configure other web applications (for example to store common files). -
If the
*.war
file name is, for example,mywebapp.war
, it is deployed as a standard web application with the context path/mywebapp
(that is, the web application is reachable athttp://localhost:8080/mywebapp/
). -
If the file name is
ROOT.war
, case-insensitive, thecontextPath
is/
(that is, the web application is reachable athttp://localhost:8080/
). -
If both the
mywebapp.war
file and themywebapp/
directory exist, only the file is deployed. This allows the directory with the same name to be the*.war
file unpack location and avoid that the web application is deployed twice. -
A Jetty context XML file named
mywebapp.xml
is deployed as a web application by processing the directives contained in the XML file itself, which must set thecontextPath
, which could be different from the name of the XML file. -
If both
mywebapp.xml
andmywebapp.war
exist, only the XML file is deployed. This allows the XML file to reference the*.war
file and avoid that the web application is deployed twice.
Environment Resolution
A web application is always deployed to a specific environment, which is either configured for the deployed application or set to the default environment.
If only a single specific deployer module is enabled, for example ee10-deploy
, then it is the default environment and applications will be deployed to it without any additional configuration.
If multiple deployer modules are enabled, then the default environment is:
-
The most recent Jakarta EE environment of the
ee{8,9,10}-deploy
modules that are enabled. -
Otherwise, the
core
environment, if thecore-deploy
module is enabled. -
Otherwise, no deployer environment has been enabled, and therefore no application can be deployed.
For example, if core-deploy
, ee9-deploy
and the ee10-deploy
modules are enabled, then ee10
is the default environment, to which applications will be deployed unless otherwise configured (see below).
To configure a specific environment for an application, you add a *.properties
file with the same name of the web application.
For example, an application deployed to $JETTY_BASE/webapps/my-ee9-app.war
is configured with the file $JETTY_BASE/webapps/my-ee9-app.properties
, with the following content:
environment=ee9
In case of simultaneous multiple deployer environments, it is good practice to always specify the *.properties
file for your web applications.
If you do not specify the For example, if you have enabled the deployer Jetty module for all Jakarta EE versions, and you deploy an EE 9 web application without the This unspecified deployment may not work as the EE 9 web application may use APIs that have been removed in EE 10, causing an error at runtime. |
Deploying Jetty Context XML Files
A Jetty context XML file is a Jetty XML file that allows you to customize the deployment of web applications.
Recall that the DeploymentManager component of the Jetty deploy module gives priority to Jetty context XML files over *.war files or directories.
|
To deploy a web application using a Jetty context XML file, simply place the file in the $JETTY_BASE/webapps
directory.
A simple Jetty context XML file, for example named wiki.xml
is the following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext"> (1)
<Set name="contextPath">/wiki</Set> (2)
<Set name="war">/opt/myapps/myapp.war</Set> (3)
</Configure>
1 | Configures a WebAppContext , which is the Jetty component that represents a standard Servlet web application. |
2 | Specifies the web application contextPath , which may be different from the *.war file name. |
3 | Specifies the file system path of the *.war file. |
The Jetty content XML file may be accompanied by a *.properties
file that specifies the environment to use for the deployment:
environment=ee10
Refer to this section for more information about specifying the environment.
The $JETTY_BASE
directory would look like this:
$JETTY_BASE ├── resources │ └── jetty-logging.properties ├── start.d │ ├── deploy.ini │ └── http.ini └── webapps ├── wiki.properties └── wiki.xml
The *.war file may be placed anywhere in the file system and does not need to be placed in the $JETTY_BASE/webapps directory.
|
If you place both the Jetty context XML file and the *.war file in the $JETTY_BASE/webapps directory, remember that they must have the same file name, for example wiki.xml and wiki.war , so that the DeploymentManager deploys the web application only once using the Jetty context XML file (and not the *.war file).
|
You can use the features of Jetty XML files to avoid to hard-code file system paths or other configurations in your Jetty context XML files, for example by using system properties:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Set name="contextPath">/wiki</Set>
<Set name="war"><SystemProperty name="myapps.dir"/>/myapp.war</Set>
</Configure>
Note how the *.war
file path is now obtained by resolving the system property myapps.dir
that you can specify on the command line when you start Jetty:
$ java -jar $JETTY_HOME/start.jar -Dmyapps.dir=/opt/myapps
Deploying Environment Specific Context XML Files
Jetty context XML file files can be applied to all webapps deployed to a particular environment
.
Add a properties file to the deployment directory that contains a property naming the location of the xml file to apply.
The properties file name must be prefixed by the name of the environment
.
For example ee8.properties, ee8-more.properties ee8-other.properties
would all apply to all contexts deployed in the ee8
environment.
If the property file(s) contain one or more properties whose names are prefixed with org.eclipse.jetty.deploy.environmentXml
, then their values are used as additional context XML files to apply to all contexts deployed in the corresponding environment.
So for example org.eclipse.jetty.deploy.environmentXml, org.eclipse.jetty.deploy.environmentXml.more, org.eclipse.jetty.deploy.environmentXml.other
are all acceptable as names.
Each property configures the location of a context XML file to apply to a context when it is being created and deployed.
The location may be either absolute or relative to the parent of the deployment directory.
So if your webapp deployment directory is $JETTY_BASE/webapps
, then $JETTY_BASE
will be used to resolve any relative filenames.
All environment-specific Jetty context XML files will be applied to the webapp before any context XML file associated with the webapp. The order in which they are applied is determined by the name of the properties that define them.
The contents of the environment specific context XML file may only contain references to classes appropriate for that environment. |
For example, given the previous example of a $JETTY_BASE/webapps/wiki.xml
and its accompanying $JETTY_BASE/webapps/wiki.properties
file that declares the wiki
webapp should be deployed to environment ee10
, files called $JETTY_BASE/webapps/ee10.properties
and $JETTY_BASE/webapps/ee10-feature.properties
can be defined to further configure the webapp.
The ee10.properties
file contains:
jetty.deploy.environmentXml=etc/ee10-context.xml
The ee10-feature.properties
file contains:
jetty.deploy.environmentXml.feature=etc/ee10-feature.xml
The ee10-context.xml
file contains:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure id="wac" class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Call name="setAttribute">
<Arg>common</Arg>
<Arg>value</Arg>
</Call>
</Configure>
The ee10-feature.xml
file contains:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure id="wac" class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Call name="addEventListener">
<Arg>
<New class="com.example.MyListenerFeature"/>
</Arg>
</Call>
</Configure>
The directory structure would look like this:
$JETTY_BASE
|- etc
│ |-ee10-context.xml
| |-ee10-feature.xml
|- webapps
|-ee10.properties
|-ee10-feature.properties
|-wiki.properties
|- wiki.xml
The contents of the $JETTY_BASE/etc/ee10-context.xml
then $JETTY_BASE/etc/ee10-feature.xml
files will be applied to the wiki
webapp instance before wiki.xml
, allowing the contents of the latter to override the contents of the former.
WEB-INF/jetty-ee{8,9,10}-web.xml
As discussed above, a Jetty context XML file can be used to configure a webapp during deployment.
The webapp can also be configured during its startup phase by a WEB-INF/jetty-ee{8,9,10}-web.xml
file.
The contents of this file is the same as a Jetty context XML file.
This file can be useful:
-
to place all configuration inside your webapp archive
-
to perform configuration that can only occur after the webapp’s classpath has been created
it is good practice to name the file according to the environment into which the webapp will be deployed. If your webapp can be deployed to multiple environments then you should include a WEB-INF file for each one. If you only deploy to a single environment then you can omit it from the filename, however be aware that you cannot change environments without updating the contents of the file.
|
Configuring JNDI Entries
A web application may reference a JNDI entry, such as a JDBC DataSource
from the web application web.xml
file.
The JNDI entry must be defined in a Jetty XML file, for example a context XML like so:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure id="wac" class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Set name="contextPath">/mywebapp</Set>
<Set name="war">/opt/webapps/mywebapp.war</Set>
<New class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid="wac"/></Arg>
<Arg>jdbc/myds</Arg>
<Arg>
<New class="com.mysql.cj.jdbc.MysqlConnectionPoolDataSource">
<Set name="url">jdbc:mysql://localhost:3306/databasename</Set>
<Set name="user">user</Set>
<Set name="password">password</Set>
</New>
</Arg>
</New>
</Configure>
For more information and examples on how to use JNDI in Jetty, refer to the JNDI feature section.
Class If the class is instead present within the web application, then the JNDI entry must be declared in a |
Configuring Virtual Hosts
A virtual host is an internet domain name, registered in the Domain Name Server (DNS), for an IP address such that multiple virtual hosts will resolve to the same IP address of a single server instance.
If you have multiple web applications deployed on the same Jetty server, by using virtual hosts you will be able to target a specific web application.
For example, you may have a web application for your business and a web application for your hobbies , both deployed in the same Jetty server.
By using virtual hosts, you will be able to have the first web application available at http://domain.biz/
, and the second web application available at http://hobby.net/
.
Another typical case is when you want to use different subdomains for different web application, for example a project website is at http://project.org/
and the project documentation is at http://docs.project.org
.
Virtual hosts can be used with any context that is a subclass of ContextHandler.
Virtual Host Names
Jetty supports the following variants to be specified as virtual host names:
www.hostname.com
-
A fully qualified domain name. It is important to list all variants as a site may receive traffic for both
www.hostname.com
andhostname.com
. *.hostname.com
-
A wildcard domain name which will match only one level of arbitrary subdomains. *.foo.com will match www.foo.com and m.foo.com, but not www.other.foo.com.
10.0.0.2
-
An IP address may be set as a virtual host to indicate that a web application should handle requests received on the network interface with that IP address for protocols that do not indicate a host name such as HTTP/0.9 or HTTP/1.0.
@ConnectorName
-
A Jetty server
Connector
name to indicate that a web application should handle requests received on the serverConnector
with that name, and therefore received on a specific socket address (either an IP port forServerConnector
, or a Unix-Domain path forUnixDomainServerConnector
). A serverConnector
name can be set via https://javadoc.jetty.org/jetty-12/org/eclipse/jetty/server/AbstractConnector.html#setName(java.lang.String). www.√integral.com
-
Non-ASCII and IDN domain names can be set as virtual hosts using Puny Code equivalents that may be obtained from a Punycode/IDN converters. For example if the non-ASCII domain name
www.√integral.com
is given to a browser, then the browser will make a request that uses the domain namewww.xn—integral-7g7d.com
, which is the name that should be added as the virtual host name.
Virtual Hosts Configuration
If you have a web application mywebapp.war
you can configure its virtual hosts in this way:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Set name="contextPath">/mywebapp</Set>
<Set name="war">/opt/webapps/mywebapp.war</Set>
<Set name="virtualHosts">
<Array type="java.lang.String">
<Item>mywebapp.com</Item>
<Item>www.mywebapp.com</Item>
<Item>mywebapp.net</Item>
<Item>www.mywebapp.net</Item>
</Array>
</Set>
</Configure>
Your web application will be available at:
-
http://mywebapp.com/mywebapp
-
http://www.mywebapp.com/mywebapp
-
http://mywebapp.net/mywebapp
-
http://www.mywebapp.net/mywebapp
You configured the As such, a request to Likewise, a request to |
Same Context Path, Different Virtual Hosts
If you want to deploy different web applications to the same context path, typically the root context path /
, you must use virtual hosts to differentiate among web applications.
You have domain.war
that you want to deploy at http://domain.biz/
and hobby.war
that you want to deploy at http://hobby.net
.
To achieve this, you simply use the same context path of /
for each of your webapps, while specifying different virtual hosts for each of your webapps:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war">/opt/webapps/domain.war</Set>
<Set name="virtualHosts">
<Array type="java.lang.String">
<Item>domain.biz</Item>
</Array>
</Set>
</Configure>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war">/opt/webapps/hobby.war</Set>
<Set name="virtualHosts">
<Array type="java.lang.String">
<Item>hobby.net</Item>
</Array>
</Set>
</Configure>
Different Port, Different Web Application
Sometimes it is required to serve different web applications from different socket addresses (either different IP ports, or different Unix-Domain paths), and therefore from different server Connector
s.
For example, you want requests to http://localhost:8080/
to be served by one web application, but requests to http://localhost:9090/
to be served by another web application.
This configuration may be useful when Jetty sits behind a load balancer.
In this case, you want to configure multiple connectors, each with a different name, and then reference the connector name in the web application virtual host configuration:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war">/opt/webapps/domain.war</Set>
<Set name="virtualHosts">
<Array type="java.lang.String">
<Item>@port8080</Item>
</Array>
</Set>
</Configure>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war">/opt/webapps/hobby.war</Set>
<Set name="virtualHosts">
<Array type="java.lang.String">
<Item>@port9090</Item>
</Array>
</Set>
</Configure>
Web application Likewise, web application See this section for further information about how to configure connectors. |
Configuring *.war
File Extraction
By default, *.war
files are uncompressed and its content extracted in a temporary directory.
The web application resources are served by Jetty from the files extracted in the temporary directory, not from the files within the *.war
file, for performance reasons.
If you do not want Jetty to extract the *.war
files, you can disable this feature, for example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Set name="contextPath">/mywebapp</Set>
<Set name="war">/opt/webapps/mywebapp.war</Set>
<Set name="extractWAR">false</Set>
</Configure>
Overriding web.xml
You can configure an additional web.xml
that complements the web.xml
file that is present in the web application *.war
file.
This additional web.xml
is processed after the *.war
file web.xml
.
This allows you to add host specific configuration or server specific configuration without having to extract the web application web.xml
, modify it, and repackage it in the *.war
file.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://jetty.org/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
<Set name="contextPath">/mywebapp</Set>
<Set name="war">/opt/webapps/mywebapp.war</Set>
<Set name="overrideDescriptor">/opt/webapps/mywebapp-web.xml</Set>
</Configure>
The format of the additional web.xml
is exactly the same as a standard web.xml
file, for example:
<?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="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<servlet>
<servlet-name>my-servlet</servlet-name>
<init-param>
<param-name>host</param-name>
<param-value>192.168.0.13</param-value>
</init-param>
</servlet>
</web-app>
In the example above, you configured the my-servlet
Servlet (defined in the web application web.xml
), adding a host specific init-param
with the IP address of the host.