blob: 7cfe78ac0b53adfbe717d4fce5104c121ecaf306 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.10">
<title>Eclipse Jetty: Operations Guide</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<link rel="stylesheet" href="./asciidoctor.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body class="article toc2 toc-left">
<div id="header">
<h1>Eclipse Jetty: Operations Guide</h1>
<div class="details">
<span id="author" class="author">Jetty Developers</span><br>
<span id="email" class="email"><a href="mailto:jetty-dev@eclipse.org">jetty-dev@eclipse.org</a></span><br>
<span id="revnumber">version 11.0.0-SNAPSHOT,</span>
<span id="revdate">2020-10-04</span>
</div>
<div id="toc" class="toc2">
<div id="toctitle">Operations Guide</div>
<ul class="sectlevel1">
<li><a href="#og-intro">Eclipse Jetty Operations Guide</a>
<ul class="sectlevel2">
<li><a href="#og-introduction">Introduction</a></li>
<li><a href="#og-eclipse-jetty-features">Eclipse Jetty Features</a></li>
<li><a href="#og-eclipse-jetty-how-tos">Eclipse Jetty How-Tos</a></li>
<li><a href="#og-begin">Introduction to Eclipse Jetty</a>
<ul class="sectlevel3">
<li><a href="#og-quick-jetty-setup">Quick Jetty Setup</a></li>
<li><a href="#og-begin-download">Downloading Eclipse Jetty</a></li>
<li><a href="#og-begin-install">Installing Eclipse Jetty</a></li>
<li><a href="#og-begin-arch">Eclipse Jetty Architecture Overview</a>
<ul class="sectlevel4">
<li><a href="#og-begin-arch-modules">Eclipse Jetty Architecture: Modules</a></li>
<li><a href="#og-begin-arch-jetty-base">Eclipse Jetty Architecture: <code>$JETTY_BASE</code></a></li>
<li><a href="#base-vs-home-resolution">Eclipse Jetty Architecture: <code>$JETTY_HOME</code> and <code>$JETTY_BASE</code> Configuration Resolution</a></li>
</ul>
</li>
<li><a href="#og-begin-start">Starting Eclipse Jetty</a></li>
<li><a href="#og-begin-deploy">Deploying Web Applications to Eclipse Jetty</a>
<ul class="sectlevel4">
<li><a href="#og-begin-deploy-war">Deploying Standard *.war Web Applications</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-start-details">Starting Eclipse Jetty: Details</a></li>
<li><a href="#og-start-jar">Using start.jar</a>
<ul class="sectlevel3">
<li><a href="#executing-startjar">Executing start.jar</a></li>
<li><a href="#og-start-jar-command-line-options">start.jar Command Line Options</a>
<ul class="sectlevel4">
<li><a href="#og-command-line-options">Command Line Options</a></li>
<li><a href="#og-debug-and-start-logging">Debug and Start Logging</a></li>
<li><a href="#og-module-management">Module Management</a></li>
<li><a href="#og-startup-shutdown-command-line">Startup / Shutdown Command Line</a></li>
<li><a href="#og-advanced-commands">Advanced Commands</a></li>
</ul>
</li>
<li><a href="#og-shaded-start-jar">Shaded Start.jar</a></li>
<li><a href="#og-start-jar-without-exec-or-forking">Start.jar without exec or forking.</a></li>
</ul>
</li>
<li><a href="#og-deploy">Customizing Web Application Deployment</a>
<ul class="sectlevel3">
<li><a href="#og-deploy-hot-static">Hot vs Static Deployment</a></li>
<li><a href="#og-deploy-rules">Deployment Rules</a></li>
<li><a href="#og-deploy-jetty">Deploying Jetty Context XML Files</a></li>
<li><a href="#og-deploy-jndi">Configuring JNDI Entries</a></li>
<li><a href="#og-deploy-virtual-hosts">Configuring Virtual Hosts</a>
<ul class="sectlevel4">
<li><a href="#og-deploy-virtual-hosts-names">Virtual Host Names</a></li>
<li><a href="#og-deploy-virtual-hosts-config">Virtual Hosts Configuration</a></li>
<li><a href="#og-deploy-virtual-hosts-same-context">Same Context Path, Different Virtual Hosts</a></li>
<li><a href="#og-deploy-virtual-hosts-port">Different Port, Different Web Application</a></li>
</ul>
</li>
<li><a href="#og-deploy-extract-war">Configuring <code>*.war</code> File Extraction</a></li>
<li><a href="#og-deploy-jetty-override-web-xml">Overriding <code>web.xml</code></a></li>
<li><a href="#og-deploy-init-params">Configuring <code>init-param</code>s</a></li>
</ul>
</li>
<li><a href="#og-protocols">Configuring Eclipse Jetty Connectors and Protocols</a>
<ul class="sectlevel3">
<li><a href="#og-protocols-http">Configuring Clear-Text HTTP/1.1</a></li>
<li><a href="#og-protocols-https">Configuring Secure HTTP/1.1</a></li>
<li><a href="#og-protocols-http2">Configuring HTTP/2</a></li>
<li><a href="#og-secure-vs-clear-text-http2">Secure vs Clear-Text HTTP/2</a></li>
<li><a href="#og-protocols-http2s">Configuring Secure HTTP/2</a></li>
<li><a href="#og-protocols-http2c">Configuring Clear-Text HTTP/2</a></li>
<li><a href="#og-protocols-ssl">Configuring Secure Protocols</a></li>
<li><a href="#og-modules">Jetty Modules</a></li>
<li><a href="#og-module-bytebufferpool">Module <code>bytebufferpool</code></a></li>
<li><a href="#og-module-deploy">Module <code>deploy</code></a></li>
<li><a href="#og-module-http">Module <code>http</code></a>
<ul class="sectlevel4">
<li><a href="#og-module-http-acceptors">Configuration of Acceptors</a></li>
<li><a href="#og-module-http-selectors">Configuration of Selectors</a></li>
</ul>
</li>
<li><a href="#og-module-server">Module <code>server</code></a></li>
<li><a href="#og-module-threadpool">Module <code>threadpool</code></a></li>
</ul>
</li>
<li><a href="#og-sessions">HTTP Session Management</a>
<ul class="sectlevel3">
<li><a href="#og-session-overview">HTTP Session Overview</a>
<ul class="sectlevel4">
<li><a href="#og-terminology">Terminology</a></li>
<li><a href="#og-session-modules">Session Modules</a></li>
</ul>
</li>
<li><a href="#og-session-base">The Base Session Module</a>
<ul class="sectlevel4">
<li><a href="#og-configuration">Configuration</a></li>
<li><a href="#og-session-base-scavenge">Session Scavenging</a></li>
</ul>
</li>
<li><a href="#og-session-cache">Modules for HTTP Session Caching</a>
<ul class="sectlevel4">
<li><a href="#og-session-cache-hash">Caching in Memory</a></li>
<li><a href="#og-session-cache-null">No Caching</a></li>
</ul>
</li>
<li><a href="#og-session-filesystem">Modules for Persistent HTTP Sessions: File System</a>
<ul class="sectlevel4">
<li><a href="#og-configuration-4">Configuration</a></li>
</ul>
</li>
<li><a href="#og-session-jdbc">Modules for Persistent HTTP Sessions: JDBC</a>
<ul class="sectlevel4">
<li><a href="#og-configuration-5">Configuration</a></li>
</ul>
</li>
<li><a href="#og-session-mongo">Modules for Persistent HTTP Sessions: MongoDB</a>
<ul class="sectlevel4">
<li><a href="#og-configuration-6">Configuration</a></li>
</ul>
</li>
<li><a href="#og-session-infinispan">Modules for Persistent HTTP Sessions: Infinispan</a>
<ul class="sectlevel4">
<li><a href="#og-session-infinispan-remote">Remote Infinispan Session Module</a></li>
<li><a href="#og-session-infinispan-remote-query">Remote Infinispan Query Module</a></li>
<li><a href="#og-session-infinispan-embedded">Embedded Infinispan Session Module</a></li>
<li><a href="#og-session-infinispan-embedded-query">Embedded Infinispan Query Module</a></li>
<li><a href="#og-converting-session-format-for-jetty-9-4-13">Converting Session Format for Jetty-9.4.13</a></li>
</ul>
</li>
<li><a href="#og-session-hazelcast">Modules for Persistent HTTP Sessions: Hazelcast</a>
<ul class="sectlevel4">
<li><a href="#og-session-hazelcast-remote">Remote Hazelcast Clustering</a></li>
<li><a href="#og-session-hazelcast-embedded">Embedded Hazelcast Clustering</a></li>
</ul>
</li>
<li><a href="#og-session-gcloud">Modules for Persistent HTTP Sessions: Google Cloud DataStore</a>
<ul class="sectlevel4">
<li><a href="#og-preparation">Preparation</a></li>
<li><a href="#og-communicating-with-gclouddatastore">Communicating with GCloudDataStore</a></li>
<li><a href="#og-configuring-indexes-for-session-data">Configuring Indexes for Session Data</a></li>
<li><a href="#og-communicating-with-the-gclouddatastore-emulator">Communicating with the GCloudDataStore Emulator</a></li>
<li><a href="#og-enabling-the-google-cloud-datastore-module">Enabling the Google Cloud DataStore Module</a></li>
</ul>
</li>
<li><a href="#og-configuration-11">Configuration</a></li>
<li><a href="#og-session-memcached">Modules for Persistent HTTP Sessions: The L2 Session Data Cache</a>
<ul class="sectlevel4">
<li><a href="#og-memcachedsessiondatamap">MemcachedSessionDataMap</a></li>
</ul>
</li>
<li><a href="#og-session-usecases">Session Scenarios</a>
<ul class="sectlevel4">
<li><a href="#og-minimizing-support-for-sessions">Minimizing Support for Sessions</a></li>
<li><a href="#og-clustering-with-a-sticky-load-balancer">Clustering with a Sticky Load Balancer</a></li>
<li><a href="#og-clustering-without-a-sticky-load-balancer">Clustering Without a Sticky Load Balancer</a></li>
<li><a href="#og-handling-corrupted-or-unreadable-session-data">Handling Corrupted or Unreadable Session Data</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-xml">Jetty XML</a>
<ul class="sectlevel3">
<li><a href="#og-xml-syntax">Jetty XML Syntax</a>
<ul class="sectlevel4">
<li><a href="#og-xml-syntax-configure"><code>&lt;Configure&gt;</code></a></li>
<li><a href="#og-xml-syntax-arg"><code>&lt;Arg&gt;</code></a></li>
<li><a href="#og-xml-syntax-new"><code>&lt;New&gt;</code></a></li>
<li><a href="#og-xml-syntax-call"><code>&lt;Call&gt;</code></a></li>
<li><a href="#og-xml-syntax-get"><code>&lt;Get&gt;</code></a></li>
<li><a href="#og-xml-syntax-set"><code>&lt;Set&gt;</code></a></li>
<li><a href="#og-xml-syntax-map"><code>&lt;Map&gt;</code> and <code>&lt;Entry&gt;</code></a></li>
<li><a href="#og-xml-syntax-put"><code>&lt;Put&gt;</code></a></li>
<li><a href="#og-xml-syntax-array"><code>&lt;Array&gt;</code> and <code>&lt;Item&gt;</code></a></li>
<li><a href="#og-xml-syntax-ref"><code>&lt;Ref&gt;</code></a></li>
<li><a href="#og-xml-syntax-property"><code>&lt;Property&gt;</code></a></li>
<li><a href="#og-xml-syntax-system-property"><code>&lt;SystemProperty&gt;</code></a></li>
<li><a href="#og-xml-syntax-env"><code>&lt;Env&gt;</code></a></li>
<li><a href="#og-xml-syntax-types">Type Coercion</a></li>
<li><a href="#og-xml-syntax-scope">Scopes</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div class="sect1">
<h2 id="og-intro"><a class="anchor" href="#og-intro"></a><a class="link" href="#og-intro">Eclipse Jetty Operations Guide</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The Eclipse Jetty Operations Guide targets sysops, devops, and developers who want to install Eclipse Jetty as a standalone server to deploy web applications.</p>
</div>
<div class="sect2">
<h3 id="og-introduction"><a class="anchor" href="#og-introduction"></a><a class="link" href="#og-introduction">Introduction</a></h3>
<div class="paragraph">
<p>If you are new to Eclipse Jetty, read <a href="#og-begin">here</a> to download, install, start and deploy web applications to Jetty.</p>
</div>
</div>
<div class="sect2">
<h3 id="og-eclipse-jetty-features"><a class="anchor" href="#og-eclipse-jetty-features"></a><a class="link" href="#og-eclipse-jetty-features">Eclipse Jetty Features</a></h3>
<div class="paragraph">
<p>If you know Eclipse Jetty already, jump to a feature:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#og-sessions">HTTP Session Caching and Clustering</a></p>
</li>
<li>
<p><a href="#og-protocols-http2">HTTP/2 Support</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>TODO</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Jetty Overview</p>
</li>
<li>
<p>Jetty Modules</p>
</li>
<li>
<p>Rewrite Modules</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="og-eclipse-jetty-how-tos"><a class="anchor" href="#og-eclipse-jetty-how-tos"></a><a class="link" href="#og-eclipse-jetty-how-tos">Eclipse Jetty How-Tos</a></h3>
<div class="ulist">
<ul>
<li>
<p><a href="#og-protocols-http">Configure Clear-Text HTTP/1.1</a></p>
</li>
<li>
<p><a href="#og-protocols-https">Configure Secure HTTP/1.1 (https)</a></p>
</li>
<li>
<p><a href="#og-protocols-http2c">Configure Clear-Text HTTP/2</a></p>
</li>
<li>
<p><a href="#og-protocols-http2s">Configure Secure HTTP/2</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>TODO</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Jetty Behind a Load Balancer</p>
<div class="ulist">
<ul>
<li>
<p>Forward Header Customizer</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="og-begin"><a class="anchor" href="#og-begin"></a><a class="link" href="#og-begin">Introduction to Eclipse Jetty</a></h3>
<div class="paragraph">
<p>This section will get you started with Eclipse Jetty.</p>
</div>
<div class="sect3">
<h4 id="og-quick-jetty-setup"><a class="anchor" href="#og-quick-jetty-setup"></a><a class="link" href="#og-quick-jetty-setup">Quick Jetty Setup</a></h4>
<div class="paragraph">
<p>Jetty is distributed in an artifact that expands in a directory called <code>$JETTY_HOME</code>, which should not be modified.</p>
</div>
<div class="paragraph">
<p>Configuration for Jetty is typically done in one (or more) other directories called <code>$JETTY_BASE</code>.</p>
</div>
<div class="paragraph">
<p>The following commands can be used to setup a <code>$JETTY_BASE</code> directory that supports deployment of <code>*.war</code> files and a clear-text HTTP connector:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ export JETTY_HOME=/path/to/jetty-home
$ mkdir /path/to/jetty-base
$ cd /path/to/jetty-base
$ java -jar $JETTY_HOME/start.jar --add-module=server,http,deploy</pre>
</div>
</div>
<div class="paragraph">
<p>This will create a <code>$JETTY_BASE/start.d/</code> directory and other directories that contain the configuration of the server, including the <code>$JETTY_BASE/webapps/</code> directory, in which standard <code>*.war</code> files can be deployed.</p>
</div>
<div class="paragraph">
<p>To deploy Jetty&#8217;s demo web applications, run this command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=demo</pre>
</div>
</div>
<div class="paragraph">
<p>Now you can start the Jetty server with:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar</pre>
</div>
</div>
<div class="paragraph">
<p>Point your browser at <code>http://localhost:8080</code> to see the web applications deployed in Jetty.</p>
</div>
<div class="paragraph">
<p>The Jetty server can be stopped with <code>ctrl-c</code> in the terminal window.</p>
</div>
<div class="paragraph">
<p>The following sections will guide you in details about downloading, installing and starting Jetty, as well as deploying your web applications to Jetty.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-begin-download"><a class="anchor" href="#og-begin-download"></a><a class="link" href="#og-begin-download">Downloading Eclipse Jetty</a></h4>
<div class="paragraph">
<p>The Eclipse Jetty distribution is available for download from <a href="https://www.eclipse.org/jetty/download.html" class="bare">https://www.eclipse.org/jetty/download.html</a></p>
</div>
<div class="paragraph">
<p>The Eclipse Jetty distribution is available in both <code>zip</code> and <code>gzip</code> formats; download the one most appropriate for your system, typically <code>zip</code> for Windows and <code>gzip</code> for other operative systems.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-begin-install"><a class="anchor" href="#og-begin-install"></a><a class="link" href="#og-begin-install">Installing Eclipse Jetty</a></h4>
<div class="paragraph">
<p>After the download, unpacking the Eclipse Jetty distribution will extract the files into a directory called <code>jetty-distribution-VERSION</code>, where <code>VERSION</code> is the version that you downloaded, for example <code>10.0.0</code>, so that the directory is called <code>jetty-distribution-10.0.0</code>.</p>
</div>
<div class="paragraph">
<p>Unpack the Eclipse Jetty distribution compressed file in a convenient location, for example under <code>/opt</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
For Windows users, you should unpack Jetty to a path that does not contain spaces.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The rest of the instructions in this documentation will refer to this location as <code>$JETTY_HOME</code>, or <code>${jetty.home}</code>.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
It is important that <strong>only</strong> stable release versions are used in production environments.
Versions that have been deprecated or are released as Milestones (M), Alpha, Beta or Release Candidates (RC) are <strong>not</strong> suitable for production as they may contain security flaws or incomplete/non-functioning feature sets.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>If you are new to Jetty, read the <a href="#og-begin-arch">Jetty architecture short section</a> to become familiar with the terms used in this document.
Otherwise, you can jump to the <a href="#og-begin-start">start Jetty section</a>.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-begin-arch"><a class="anchor" href="#og-begin-arch"></a><a class="link" href="#og-begin-arch">Eclipse Jetty Architecture Overview</a></h4>
<div class="paragraph">
<p>There are two main concepts on which the Eclipse Jetty standalone server is based:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>the <a href="#og-begin-arch-modules">Jetty <em>module</em> system</a>, that provides the Jetty features</p>
</li>
<li>
<p>the <a href="#og-begin-arch-jetty-base"><code>$JETTY_BASE</code> directory</a>, that provides a place where you configure the modules, and therefore the features, you need for your web applications</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>After installing Jetty, you want to setup a <a href="#og-begin-arch-jetty-base"><code>$JETTY_BASE</code> directory</a> where you configure <a href="#og-begin-arch-modules">Jetty modules</a>.</p>
</div>
<div class="sect4">
<h5 id="og-begin-arch-modules"><a class="anchor" href="#og-begin-arch-modules"></a><a class="link" href="#og-begin-arch-modules">Eclipse Jetty Architecture: Modules</a></h5>
<div class="paragraph">
<p>The Jetty standalone server is made of components that are assembled together, configured and started to provide different features.</p>
</div>
<div class="paragraph">
<p>A Jetty <em>module</em> is made of one or more components that work together to provide typically one feature, although they may provide more than one feature.</p>
</div>
<div class="paragraph">
<p>A Jetty module is nothing more than Jetty components assembled together like you would do using Java APIs, just done in a declarative way using configuration files rather than using Java APIs.
What you can do in Java code to assemble Jetty components, it can be done using Jetty modules.</p>
</div>
<div class="paragraph">
<p>A Jetty module may be dependent on other Jetty modules: for example, the <code>http</code> Jetty module depends on the <code>server</code> Jetty module, that in turn depends on the <code>threadpool</code> and <code>logging</code> Jetty modules.</p>
</div>
<div class="paragraph">
<p>Every feature in a Jetty server is enabled by enabling correspondent Jetty modules.</p>
</div>
<div class="paragraph">
<p>For example, if you enable only the <code>http</code> Jetty module, then your Jetty standalone server will only be able to listen to a network port for clear-text HTTP requests.
It will not be able to process secure HTTP (i.e. <code>https</code>) requests, it will not be able to process WebSocket, or HTTP/2 or any other protocol because the correspondent modules have not been enabled.</p>
</div>
<div class="paragraph">
<p>You can even start a Jetty server <em>without</em> listening on a network port&#8201;&#8212;&#8201;for example because you have enabled a custom module you wrote that provides the features you need.</p>
</div>
<div class="paragraph">
<p>This allows the Jetty standalone server to be as small as necessary: modules that are not enabled are not loaded, don&#8217;t waste memory, and you don&#8217;t risk that client use a module that you did not know was even there.</p>
</div>
<div class="paragraph">
<p>For more detailed information about the Jetty module system, see <a href="#og-modules">this section</a>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-begin-arch-jetty-base"><a class="anchor" href="#og-begin-arch-jetty-base"></a><a class="link" href="#og-begin-arch-jetty-base">Eclipse Jetty Architecture: <code>$JETTY_BASE</code></a></h5>
<div class="paragraph">
<p>Instead of managing multiple Jetty implementations out of several different distribution locations, it is possible to maintain a separation between the binary installation of the standalone Jetty (known as <code>${jetty.home}</code>), and the customizations for your specific environment(s) (known as <code>${jetty.base}</code>).
In addition to easy management of multiple server instances, is allows for quick, drop-in upgrades of Jetty.
There should always only be <strong>one</strong> Jetty Home (per version of Jetty), but there can be multiple Jetty Base directories that reference it.</p>
</div>
<div class="paragraph">
<p>This separation between <code>$JETTY_HOME</code> and <code>$JETTY_BASE</code> allows upgrades without affecting your web applications.
<code>$JETTY_HOME</code> contains the Jetty runtime and libraries and the default configuration, while a <code>$JETTY_BASE</code> contains your web applications and any override of the default configuration.</p>
</div>
<div class="paragraph">
<p>For example, with the <code>$JETTY_HOME</code> installation the default value for the network port for clear-text HTTP is <code>8080</code>.
However, you want that port to be <code>6060</code>, for example because you are behind a load balancer that is configured to forward to the backend on port <code>6060</code>.</p>
</div>
<div class="paragraph">
<p>Instead, you want to configure the clear-text HTTP port in your <code>$JETTY_BASE</code>.
When you upgrade Jetty, you will upgrade only files in <code>$JETTY_HOME</code>, and all the configuration in <code>$JETTY_BASE</code> will remain unchanged.</p>
</div>
<div class="paragraph">
<p>Installing the Jetty runtime and libraries in <code>$JETTY_HOME</code> also allows you to leverage file system permissions: <code>$JETTY_HOME</code> may be owned by an administrator user (so that only administrators can upgrade it), while <code>$JETTY_BASE</code> directories may be owned by a less privileged user.</p>
</div>
<div class="paragraph">
<p>If you had changed the default configuration in <code>$JETTY_HOME</code>, when you upgrade Jetty, say from version <code>10.0.0</code> to version <code>10.0.1</code>, your change would be lost.
Maintaining all the changes in <code>$JETTY_HOME</code>, and having to reconfigure these with each upgrade results in a massive commitment of time and effort.</p>
</div>
<div class="paragraph">
<p>To recap:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>$JETTY_BASE</code></dt>
<dd>
<div class="ulist">
<ul>
<li>
<p>This is the location for your configurations and customizations to the Jetty distribution.</p>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1"><code>$JETTY_HOME</code></dt>
<dd>
<div class="ulist">
<ul>
<li>
<p>This is the location for the Jetty distribution binaries, default XML IoC configurations, and default module definitions.</p>
</li>
</ul>
</div>
</dd>
</dl>
</div>
<div class="quoteblock">
<blockquote>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
Jetty Home should always be treated as a standard of truth.
All configuration modifications, changes and additions should <strong>always</strong> be made in the appropriate Jetty Base directory.
</td>
</tr>
</table>
</div>
</blockquote>
</div>
</div>
<div class="sect4">
<h5 id="base-vs-home-resolution"><a class="anchor" href="#base-vs-home-resolution"></a><a class="link" href="#base-vs-home-resolution">Eclipse Jetty Architecture: <code>$JETTY_HOME</code> and <code>$JETTY_BASE</code> Configuration Resolution</a></h5>
<div class="paragraph">
<p>Potential configuration is resolved from these 2 directory locations.
When Jetty starts up in processes configuration from them as follows:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Check Jetty Base First</dt>
<dd>
<p>If the referenced configuration exists, relative to the defined Jetty base, it is used.</p>
</dd>
<dt class="hdlist1">Check Jetty Home Second</dt>
<dd>
<p>If the referenced configuration exists, relative to the defined Jetty home, it is used.</p>
</dd>
<dt class="hdlist1">Use java.io.File(String pathname) Logic</dt>
<dd>
<p>Lastly, use the reference as a <code>java.io.File(String pathname)</code> reference, following the default resolution rules outlined by that constructor.In brief, the reference will be used as-is, be it relative (to current working directory, aka $\{user.dir}) or absolute path, or even network reference (such as on Windows and use of UNC paths).</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-begin-start"><a class="anchor" href="#og-begin-start"></a><a class="link" href="#og-begin-start">Starting Eclipse Jetty</a></h4>
<div class="paragraph">
<p>Eclipse Jetty as a standalone server has no graphical user interface, so configuring and running the server is done from the command line.</p>
</div>
<div class="paragraph">
<p>Recall from the <a href="#og-begin-arch">Eclipse Jetty standalone server architecture section</a> that Jetty is based on <a href="#og-modules">modules</a>, that provides features, and on <a href="#og-begin-arch-jetty-base"><code>$JETTY_BASE</code></a>, the place where you configure which module (and therefore which feature) you want to enable, and where you configure module parameters.</p>
</div>
<div class="paragraph">
<p>Jetty is started by executing <code>$JETTY_HOME/start.jar</code>, but first we need to create a <code>$JETTY_BASE</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ JETTY_BASE=/path/to/jetty.base
$ cd $JETTY_BASE
$ java -jar $JETTY_HOME/start.jar</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>ERROR : Nothing to start, exiting ...
Usage: java -jar $JETTY_HOME/start.jar [options] [properties] [configs]
java -jar $JETTY_HOME/start.jar --help # for more information</pre>
</div>
</div>
<div class="paragraph">
<p>The error is normal, since the <code>$JETTY_BASE</code> you just created is empty and therefore there is no configuration to use to assemble the Jetty server.</p>
</div>
<div class="paragraph">
<p>However, it shows that <code>start.jar</code> takes parameters, whose details can be found in <a href="#og-start-jar">this section</a>.</p>
</div>
<div class="paragraph">
<p>You can explore what modules are available out of the box via:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --list-modules=*</pre>
</div>
</div>
<div class="paragraph">
<p>Try to enable the <code>http</code> module (see also <a href="#og-protocols-http">this section</a> for additional information):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=http</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>INFO : mkdir ${jetty.base}/start.d
INFO : server transitively enabled, ini template available with --add-module=server
INFO : logging-jetty transitively enabled
INFO : http initialized in ${jetty.base}/start.d/http.ini
INFO : resources transitively enabled
INFO : threadpool transitively enabled, ini template available with --add-module=threadpool
INFO : logging/slf4j dynamic dependency of logging-jetty
INFO : bytebufferpool transitively enabled, ini template available with --add-module=bytebufferpool
INFO : mkdir ${jetty.base}/resources
INFO : copy ${jetty.home}/modules/logging/jetty/resources/jetty-logging.properties to ${jetty.base}/resources/jetty-logging.properties
INFO : Base directory was modified</pre>
</div>
</div>
<div class="paragraph">
<p>Now you can start Jetty:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>2020-09-11 15:35:17.451:INFO :oejs.Server:main: jetty-10.0.0-SNAPSHOT; built: 2020-09-10T11:01:33.608Z; git: b10a14ebf9b200da388f4f9a2036bd8117ee0b11; jvm 11.0.8+10
2020-09-11 15:35:17.485:INFO :oejs.AbstractConnector:main: Started ServerConnector@2d52216b{HTTP/1.1, <mark>(http/1.1)}{0.0.0.0:8080}</mark>
2020-09-11 15:35:17.496:INFO :oejs.Server:main: Started Server@44821a96{STARTING}[10.0.0-SNAPSHOT,sto=5000] @553ms</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how Jetty is listening on port <code>8080</code> for clear-text HTTP/1.1 connections.</p>
</div>
<div class="paragraph">
<p>After having enabled the <code>http</code> module, the <code>$JETTY_BASE</code> directory looks like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>JETTY_BASE
├── resources
│ └── jetty-logging.properties <i class="conum" data-value="1"></i><b>(1)</b>
└── start.d <i class="conum" data-value="2"></i><b>(2)</b>
└── http.ini <i class="conum" data-value="3"></i><b>(3)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>The <code>resources/jetty-logging.properties</code> file has been created because the <code>http</code> modules depends on the <code>server</code> module, which in turn depends on the <code>logging</code> module; the <code>logging</code> module created this file that can be configured to control the server logging level.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The <code>start.d/</code> directory contains the configuration files for the modules.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>The <code>start.d/http.ini</code> file is the <code>http</code> module configuration file, where you can specify values for the <code>http</code> module properties.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>In the <code>http.ini</code> file you can find the following content (among other content):</p>
</div>
<div class="listingblock">
<div class="title">http.ini</div>
<div class="content">
<pre class="highlight"><code>--module=http <i class="conum" data-value="1"></i><b>(1)</b>
# jetty.http.port=8080 <i class="conum" data-value="2"></i><b>(2)</b>
...</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>This line enables the <code>http</code> module and should not be modified.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>This line is commented out and specifies the default value for the module property <code>jetty.http.port</code>, which is the network port that listens for clear-text HTTP connections.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>You can change the module property <code>jetty.http.port</code> value directly from the command line:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar jetty.http.port=9999</pre>
</div>
</div>
<div class="paragraph">
<p>To make this change persistent, you can edit the <code>http.ini</code> file, uncomment the module property <code>jetty.http.port</code> and change its value to <code>9999</code>:</p>
</div>
<div class="listingblock">
<div class="title">http.ini</div>
<div class="content">
<pre>--module=http
jetty.http.port=9999
...</pre>
</div>
</div>
<div class="paragraph">
<p>If you restart Jetty, the new value will be used:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>2020-09-11 15:35:17.451:INFO :oejs.Server:main: jetty-10.0.0-SNAPSHOT; built: 2020-09-10T11:01:33.608Z; git: b10a14ebf9b200da388f4f9a2036bd8117ee0b11; jvm 11.0.8+10
2020-09-11 15:35:17.485:INFO :oejs.AbstractConnector:main: Started ServerConnector@2d52216b{HTTP/1.1, <mark>(http/1.1)}{0.0.0.0:9999}</mark>
2020-09-11 15:35:17.496:INFO :oejs.Server:main: Started Server@44821a96{STARTING}[10.0.0-SNAPSHOT,sto=5000] @553ms</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how Jetty is now listening on port <code>9999</code> for clear-text HTTP/1.1 connections.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
If you want to enable support for different protocols such as secure HTTP/1.1 or HTTP/2, or configured Jetty behind a load balancer, read <a href="#og-protocols">this section</a>.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The Jetty server is now up and running, but it has no web applications deployed, so it just replies with <code>404 Not Found</code> to every request.
It is time to <a href="#og-begin-deploy">deploy your web applications</a> to Jetty.</p>
</div>
<div class="paragraph">
<p>For more detailed information about the Jetty start system, you can read the <a href="#og-start-details">Jetty start system</a> section.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-begin-deploy"><a class="anchor" href="#og-begin-deploy"></a><a class="link" href="#og-begin-deploy">Deploying Web Applications to Eclipse Jetty</a></h4>
<div class="paragraph">
<p>For the purpose of deploying web applications to Jetty, there are two types of resources that can be deployed:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Standard Web Application Archives, in the form of <code>*.war</code> files or <code>*.war</code> directories, defined by the Servlet specification.
Their deployment is described in <a href="#og-begin-deploy-war">this section</a>.</p>
</li>
<li>
<p>Jetty context XML files, that allow you to customize the deployment of standard web applications, and also allow you use Jetty components, and possibly custom components written by you, to assemble your web applications.
Their deployment is described in <a href="#og-deploy">this section</a>.</p>
</li>
</ul>
</div>
<div class="sect4">
<h5 id="og-begin-deploy-war"><a class="anchor" href="#og-begin-deploy-war"></a><a class="link" href="#og-begin-deploy-war">Deploying Standard *.war Web Applications</a></h5>
<div class="paragraph">
<p>A standard Servlet web application is packaged in either a <code>*.war</code> file or in a directory with the structure of a <code>*.war</code> file.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Recall that the structure of a <code>*.war</code> file is as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>mywebapp.war
├── index.html <i class="conum" data-value="1"></i><b>(1)</b>
└── WEB-INF <i class="conum" data-value="2"></i><b>(2)</b>
├── classes/ <i class="conum" data-value="3"></i><b>(3)</b>
├── lib/ <i class="conum" data-value="4"></i><b>(4)</b>
└── web.xml <i class="conum" data-value="5"></i><b>(5)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Publicly accessible resources such as <code>*.html</code>, <code>*.jsp</code>, <code>*.css</code>, <code>*.js</code> files, etc. are placed in <code>*.war</code> or in sub-directories of the <code>*.war</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td><code>WEB-INF</code> is a special directory used to store anything related to the web application that must not be publicly accessible, but may be accessed by other resources.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td><code>WEB-INF/classes</code> stores the web application compiled <code>*.class</code> files</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td><code>WEB-INF/classes</code> stores the web application <code>*.jar</code> files</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td><code>WEB-INF/web.xml</code> is the web application deployment descriptor defines the components and the configuration of your web application.</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>To deploy a standard web application, you need to enable the <code>deploy</code> module (see the <code>deploy</code> module complete definition <a href="#og-module-deploy">here</a>).</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=deploy</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>INFO : webapp transitively enabled, ini template available with --add-module=webapp
INFO : security transitively enabled
INFO : servlet transitively enabled
INFO : deploy initialized in ${jetty.base}/start.d/deploy.ini
INFO : mkdir ${jetty.base}/webapps
INFO : Base directory was modified</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>deploy</code> module creates the <code>$JETTY_BASE/webapps</code> directory, the directory where <code>*.war</code> files or <code>*.war</code> directories should be copied so that Jetty can deploy them.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The <code>deploy</code> module only provides the feature of deploying web applications.</p>
</div>
<div class="paragraph">
<p>Whether these web applications are served via clear-text HTTP/1.1, or secure HTTP/1.1, or secure HTTP/2 (or even all of these protocols) depends on whether the correspondent Jetty modules have been enabled.
Refer to the <a href="#og-protocols">section about protocols</a> for further information.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now you need to copy a web application to the <code>$JETTY_BASE/webapps</code> directory:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>curl https://repo1.maven.org/maven2/org/eclipse/jetty/test-jetty-webapp/10.0.0/test-jetty-webapp-10.0.0.war --output $JETTY_BASE/webapps/test.war</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>$JETTY_BASE</code> directory is now:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$JETTY_BASE
├── resources
│ └── jetty-logging.properties
├── start.d
│ ├── deploy.ini
│ └── http.ini
└── webapps
└── test.war</pre>
</div>
</div>
<div class="paragraph">
<p>Now start Jetty:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>2020-09-16 09:53:38.182:INFO :oejs.Server:main: jetty-10.0.0-SNAPSHOT; built: 2020-09-16T07:47:47.334Z; git: d45455b32d96f516d39e03b53e91502a34b04f37; jvm 15+36-1562
2020-09-16 09:53:38.205:INFO :oejdp.ScanningAppProvider:main: Deployment monitor [file:///tmp/jetty.base/webapps/] at interval 1
2020-09-16 09:53:38.293:WARN :oejshC.test:main: The async-rest webapp is deployed. DO NOT USE IN PRODUCTION!
2020-09-16 09:53:38.298:INFO :oejw.StandardDescriptorProcessor:main: NO JSP Support for /test, did not find org.eclipse.jetty.jsp.JettyJspServlet
2020-09-16 09:53:38.306:INFO :oejss.DefaultSessionIdManager:main: DefaultSessionIdManager workerName=node0
2020-09-16 09:53:38.306:INFO :oejss.DefaultSessionIdManager:main: No SessionScavenger set, using defaults
2020-09-16 09:53:38.307:INFO :oejss.HouseKeeper:main: node0 Scavenging every 660000ms
2020-09-16 09:53:38.331:INFO :oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@45b4c3a9{Async REST Webservice Example,/test,[file:///tmp/jetty-0_0_0_0-8080-test_war-_test-any-15202033063643714058.dir/webapp/, jar:file:///tmp/jetty-0_0_0_0-8080-test_war-_test-any-15202033063643714058.dir/webapp/WEB-INF/lib/example-async-rest-jar-11.0.0-SNAPSHOT.jar!/META-INF/resources],AVAILABLE}{/tmp/jetty.base/webapps/test.war}
2020-09-16 09:53:38.338:INFO :oejs.AbstractConnector:main: Started ServerConnector@543295b0{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2020-09-16 09:53:38.347:INFO :oejs.Server:main: Started Server@5ffead27{STARTING}[10.0.0-SNAPSHOT,sto=5000] @593ms</pre>
</div>
</div>
<div class="paragraph">
<p>Now you can access the web application by pointing your browser to <code>http://localhost:8080/test</code>.</p>
</div>
<div class="paragraph">
<p>If you want to customize the deployment of your web application, for example by specifying a <code>contextPath</code> different from the file/directory name, or by specifying JNDI entries, or by specifying virtual hosts, etc. read <a href="#og-deploy">this section</a>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-start-details"><a class="anchor" href="#og-start-details"></a><a class="link" href="#og-start-details">Starting Eclipse Jetty: Details</a></h3>
</div>
<div class="sect2">
<h3 id="og-start-jar"><a class="anchor" href="#og-start-jar"></a><a class="link" href="#og-start-jar">Using start.jar</a></h3>
<div class="paragraph">
<p>TODO: review in light of Jetty 10</p>
</div>
<div class="paragraph">
<p>The most basic way of starting the Jetty standalone server is to execute the <code>start.jar</code>, which is a bootstrap for starting Jetty with the configuration you want.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[jetty-distribution-{VERSION}]$ java -jar start.jar
2013-09-23 11:27:06.654:INFO:oejs.Server:main: jetty-{VERSION}
...</pre>
</div>
</div>
<div class="paragraph">
<p>Jetty is a highly modularized web server container.
Very little is mandatory and required, and most components are optional; you enable or disable them according to the needs of your environment.</p>
</div>
<div class="paragraph">
<p>At its most basic, you configure Jetty from two elements:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>A set of libraries and directories that make up the server classpath.</p>
</li>
<li>
<p>A set of Jetty XML configuration files (IoC style) that establish how to build the Jetty server and its components.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Instead of editing these directly, Jetty 9.1 introduced more options on how to configure Jetty (these are merely syntactic sugar that eventually resolve into the two basic configuration components).</p>
</div>
<div class="paragraph">
<p>Jetty Startup Features include:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A separation of the Jetty distribution binaries in <code>${jetty.home}</code> and the environment specific configurations (and binaries) found in <code>${jetty.base}</code> (detailed in <a href="#startup-jetty-base-and-jetty-home">Managing Jetty Base and Jetty Home.</a>)</p>
</li>
<li>
<p>You can enable a set of libraries and XML configuration files via the newly introduced <a href="#startup-modules">module system.</a></p>
</li>
<li>
<p>All of the pre-built XML configuration files shipped in Jetty are now parameterized with properties that you can specify in your <code>${jetty.base}/start.ini</code> (demonstrated in <a href="#quick-start-configure">Quick Start Configuration</a>).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>These are powerful new features, made to support a variety of styles of configuring Jetty, from a simple property based configuration, to handling multiple installations on a server, to customized stacks of technology on top of Jetty, and even the classic, custom XML configurations of old.</p>
</div>
<div class="paragraph">
<p>For example, if you use the <code>${jetty.base}</code> concepts properly, you can upgrade the Jetty distribution without having to remake your entire tree of modifications to Jetty.
Simply separate out your specific modifications to the <code>${jetty.base}</code>, and in the future, just upgrade your <code>${jetty.home}</code> directory with a new Jetty distribution.</p>
</div>
<div class="sect3">
<h4 id="executing-startjar"><a class="anchor" href="#executing-startjar"></a><a class="link" href="#executing-startjar">Executing start.jar</a></h4>
<div class="paragraph">
<p>When executed <code>start.jar</code> performs the following actions:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Loads and parses all INIs found in <code>${jetty.base}/start.d/*.ini</code> as command line arguments.</p>
</li>
<li>
<p>Loads and parses <code>${jetty.base}/start.ini</code> as command line arguments.</p>
<div class="ulist">
<ul>
<li>
<p>Please see <a href="#start-vs-startd">Start.ini vs. Start.d</a> for more information on the difference between these.</p>
</li>
</ul>
</div>
</li>
<li>
<p>Parses actual command line arguments used to execute <code>start.jar</code> itself.</p>
</li>
<li>
<p>Resolves any XML configuration files, modules, and libraries using base vs. home resolution steps:</p>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Checks whether file exists as relative reference to <code>${jetty.base}.</code></p>
</li>
<li>
<p>Checks whether file exists as relative reference to <code>${jetty.home}.</code></p>
</li>
<li>
<p>Uses default behavior of <code>java.io.File</code> (Relative to <code>System.getProperty</code> ("user.dir") and then as absolute file system path).</p>
</li>
</ol>
</div>
</li>
<li>
<p>Loads any dependent modules (merges XXNK, library, and properties results with active command line).</p>
</li>
<li>
<p>Builds out server classpath.</p>
</li>
<li>
<p>Determines run mode as one of:</p>
<div class="ulist">
<ul>
<li>
<p>Shows informational command line options and exit.</p>
</li>
<li>
<p>Executes Jetty normally, waits for Jetty to stop.</p>
</li>
<li>
<p>Executes a forked JVM to run Jetty in, waits for forked JVM to exit.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="og-start-jar-command-line-options"><a class="anchor" href="#og-start-jar-command-line-options"></a><a class="link" href="#og-start-jar-command-line-options">start.jar Command Line Options</a></h4>
<div class="sect4">
<h5 id="og-command-line-options"><a class="anchor" href="#og-command-line-options"></a><a class="link" href="#og-command-line-options">Command Line Options</a></h5>
<div class="dlist">
<dl>
<dt class="hdlist1">--help</dt>
<dd>
<p>Obtains the current list of command line options and some basic usage help.</p>
</dd>
<dt class="hdlist1">--version</dt>
<dd>
<p>Shows the list of server classpath entries, and prints version information found for each entry.</p>
</dd>
<dt class="hdlist1">--list-classpath</dt>
<dd>
<p>Similar to --version, shows the server classpath.</p>
</dd>
<dt class="hdlist1">--list-config</dt>
<dd>
<p>Lists the resolved configuration that will start Jetty.</p>
<div class="ulist">
<ul>
<li>
<p>Java environment</p>
</li>
<li>
<p>Jetty environment</p>
</li>
<li>
<p>JVM arguments</p>
</li>
<li>
<p>Properties</p>
</li>
<li>
<p>Server classpath</p>
</li>
<li>
<p>Server XML configuration files</p>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1">--dry-run</dt>
<dd>
<p>Print the command line that the start.jar generates, then exit. This may be used to generate command lines when the start.ini includes -X or -D arguments:</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar start.jar --dry-run &gt; jetty.sh
$ . jetty.sh</pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">--dry-run=&lt;parts&gt;</dt>
<dd>
<p>Print specific parts of the command line. The parts are a comma separated list of:</p>
<div class="ulist">
<ul>
<li>
<p>"java" - the JVM to run</p>
</li>
<li>
<p>"opts" - the JVM options (eg -D and -X flags)</p>
</li>
<li>
<p>"path" - the JVM class path or JPMS modules options</p>
</li>
<li>
<p>"main" - the main class to run</p>
</li>
<li>
<p>"args" - the arguments passed to the main class</p>
</li>
</ul>
</div>
</dd>
</dl>
</div>
<div class="paragraph">
<p>It is possible to decompose the start command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ OPTS=$(java -jar start.jar --dry-run=opts,path)
$ MAIN=$(java -jar start.jar --dry-run=main)
$ ARGS=$(java -jar start.jar --dry-run=args)
$ java $OPTS -Dextra=opt $MAIN $ARGS extra=arg</pre>
</div>
</div>
<div class="paragraph">
<p>Alternatively to create an args file for java:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar start.jar --dry-run=opts,path,main,args &gt; /tmp/args
$ java @/tmp/args</pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">--exec</dt>
<dd>
<p>Forces the start to use a forked instance of java to run Jetty.
Some modules include <code>--exec</code> in order to set java command line options.
Some start options, such as <code>--jpms</code> also imply <code>--exec</code></p>
</dd>
<dt class="hdlist1">--exec-properties=&lt;filename&gt;</dt>
<dd>
<p>Assign a fixed name to the file used to transfer properties to the sub process.
This allows the generated properties file to be saved and reused.
Without this option, a temporary file is used.</p>
</dd>
<dt class="hdlist1">--commands=&lt;filename&gt;</dt>
<dd>
<p>Instructs <code>start.jar</code> to use each line of the specified file as arguments on the command line.</p>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-debug-and-start-logging"><a class="anchor" href="#og-debug-and-start-logging"></a><a class="link" href="#og-debug-and-start-logging">Debug and Start Logging</a></h5>
<div class="dlist">
<dl>
<dt class="hdlist1">--debug</dt>
<dd>
<p>Enables debugging output of the startup procedure.</p>
<div class="paragraph">
<p><strong>Note</strong>: This does not set up debug logging for Jetty itself.
For information on logging, please see the section on <a href="#configuring-jetty-logging">Configuring Jetty Logging.</a>]</p>
</div>
</dd>
<dt class="hdlist1">--start-log-file=&lt;filename&gt;</dt>
<dd>
<p>Sends all startup output to the filename specified.
Filename is relative to <code>${jetty.base}</code>.
This is useful for capturing startup issues where the Jetty-specific logger has not yet kicked in due to a possible startup configuration error.</p>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-module-management"><a class="anchor" href="#og-module-management"></a><a class="link" href="#og-module-management">Module Management</a></h5>
<div class="dlist">
<dl>
<dt class="hdlist1">--list-modules</dt>
<dd>
<p>Lists all the modules defined by the system.
Looks for module files using the <a href="#startup-base-and-home">normal <code>${jetty.base}</code> and <code>${jetty.home}</code> resolution logic</a>.
Also lists enabled state based on information present on the command line, and all active startup INI files.</p>
</dd>
<dt class="hdlist1">--list-modules=&lt;tag&gt;(,&lt;tag&gt;)*</dt>
<dd>
<p>List modules by <a href="#startup-modules">tag.</a>
Use '*' for all tags.
Prefix a tag with '-' to exclude the tag.
The special tag "internal" is always excluded unless it is explicitly included.</p>
</dd>
<dt class="hdlist1">--list-all-modules</dt>
<dd>
<p>List all modules.</p>
</dd>
<dt class="hdlist1">--module=&lt;name&gt;,(&lt;name&gt;)*</dt>
<dd>
<p>Enables one or more modules by name (use <code>--list-modules</code> to see the list of available modules).
This enables all transitive (dependent) modules from the module system as well.
If you use this from the shell command line, it is considered a temporary effect, useful for testing out a scenario.
If you want this module to always be enabled, add this command to your <code>${jetty.base}/start.ini.</code></p>
</dd>
<dt class="hdlist1">--add-to-start=&lt;name&gt;,(&lt;name&gt;)*</dt>
<dd>
<p>Enables a module by appending lines to the <code>${jetty.base}/start.ini</code> file.
The lines that are added are provided by the module-defined INI templates.
Note: Transitive modules are also appended.
If a module contains an .ini template with properties, you can also edit these properties when activating the module.
To do this, simply list the property and its value after the <code>-add-to-start</code> command, such as in the following example:</p>
<div class="listingblock">
<div class="content">
<pre>$ java -jar start.jar --add-to-start=http jetty.http.port=8379 jetty.http.host=1.2.3.4</pre>
</div>
</div>
<div class="paragraph">
<p>Doing this will uncomment the property in the associated .ini file and set it to the value specified.</p>
</div>
</dd>
<dt class="hdlist1">--update-ini</dt>
<dd>
<p>Used to update a specified property or properties that exist in an existing .ini file.
Jetty scans the command line, <code>${jetty.base}</code> and <code>${jetty.home}</code> for .ini files that have the specified property and update it accordingly.</p>
<div class="listingblock">
<div class="content">
<pre>[my-base]$ java -jar /path/to/jetty-home/start.jar --update-ini jetty.http.port=8417
ConfigSource &lt;command-line&gt;
ConfigSource ${jetty.base}
INFO : http property updated jetty.http.port=8417
INFO : http updated ${jetty.base}/start.d/http.ini
ConfigSource ${jetty.home}</pre>
</div>
</div>
</dd>
<dt class="hdlist1">--create-startd</dt>
<dd>
<p>Creates a <code>${jetty.base}/start.d/</code> directory.
If a <code>${jetty.base}/start.ini</code> file already exists, it is copied to the <code>${jetty.base}/start.d</code> directory.</p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>With respect to <code>start.ini</code> and <code>start.d/<strong>.ini</code> files, only *one</strong> of these methods should be implemented.
Mixing a <code>start.ini</code> with module specific ini files in the <code>{$jetty.base}/start.d</code> directory can lead to server issues unless great care is taken.
Please see <a href="#start-vs-startd">Start.ini vs. Start.d</a> for more information.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">--write-module-graph=&lt;filename&gt;</dt>
<dd>
<p>Advanced feature: Creates a graphviz <a href="http://graphviz.org/content/dot-language">dot file</a> of the module graph as it exists for the active <code>${jetty.base}</code>.</p>
<div class="listingblock">
<div class="content">
<pre># generate module.dot
$ java -jar start.jar --module=websocket --write-module-graph=modules.dot
# post process to a PNG file
$ dot -Tpng -o modules.png modules.dot</pre>
</div>
</div>
<div class="paragraph">
<p>See <a href="http://graphviz.org/">graphviz.org</a> for details on <a href="http://graphviz.org/content/command-line-invocation">how to post-process this dotty file</a> into the output best suited for your needs.</p>
</div>
</dd>
<dt class="hdlist1">--create-files</dt>
<dd>
<p>Create any missing files that are required by initialized modules.
This may download a file from the network if the module provides a URL.</p>
</dd>
<dt class="hdlist1">--skip-file-validation=&lt;modulename&gt;(,&lt;modulename)*</dt>
<dd>
<p>Disable the [files] section validation of content in the <code>${jetty.base}</code> directory for a specific module.
Useful for modules that have downloadable content that is being overridden with alternatives in the <code>${jetty.base}`</code> directory.</p>
</dd>
</dl>
</div>
<div class="quoteblock">
<blockquote>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
This advanced option is for administrators that fully understand the configuration of their <code>${jetty.base}</code> and are willing to forego some of the safety checks built into the jetty-start mechanism.
</td>
</tr>
</table>
</div>
</blockquote>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">--approve-all-licenses</dt>
<dd>
<p>Approve all license questions.
Useful for enabling modules from a script that does not require user interaction.</p>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-startup-shutdown-command-line"><a class="anchor" href="#og-startup-shutdown-command-line"></a><a class="link" href="#og-startup-shutdown-command-line">Startup / Shutdown Command Line</a></h5>
<div class="dlist">
<dl>
<dt class="hdlist1">--stop</dt>
<dd>
<p>Sends a stop signal to the running Jetty instance.</p>
<div class="paragraph">
<p>Note: The server must have been started with various stop properties for this to work.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">STOP.PORT=&lt;number&gt;</dt>
<dd>
<p>The port to use to stop the running Jetty server.
This is an internal port, opened on localhost, used solely for stopping the running Jetty server.
Choose a port that you do not use to serve web traffic.</p>
<div class="paragraph">
<p>Required for <code>--stop</code> to function.</p>
</div>
</dd>
<dt class="hdlist1">STOP.KEY=&lt;alphanumeric&gt;</dt>
<dd>
<p>The passphrase defined to stop the server.</p>
<div class="paragraph">
<p>Required for <code>--stop</code> to function.</p>
</div>
</dd>
<dt class="hdlist1">STOP.WAIT=&lt;number&gt;</dt>
<dd>
<p>The time (in seconds) to wait for confirmation that the running Jetty server has stopped.
If not specified, the stopper waits indefinitely for the server to stop.</p>
<div class="paragraph">
<p>If the time specified elapses, without a confirmation of server stop, then the <code>--stop</code> command exits with a non-zero return code.</p>
</div>
</dd>
</dl>
</div>
</dd>
</dl>
</div>
<div class="paragraph">
<p>You can configure a port number for Jetty to listen on for a stop command, so you are able to stop it from a different terminal.
This requires the use of a "secret" key, to prevent malicious or accidental termination.
Use the <code>STOP.PORT</code> and <code>STOP.KEY</code> (or <code>-DSTOP.PORT=</code> and <code>-DSTOP.KEY=</code>, respectively, which will set these as system parameters) parameters as arguments to the <code>start.jar</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>&gt; java -jar ${JETTY_HOME}/start.jar STOP.PORT=1234 STOP.KEY=secretpassword</pre>
</div>
</div>
<div class="paragraph">
<p>Then, to stop Jetty from a different terminal, you need to supply this port and key information.
You can either use a copy of the Jetty distribution, the <a href="#jetty-maven-plugin">jetty-maven-plugin</a>, the <a href="#jetty-ant">jetty-ant plugin</a>, or a custom class to accomplish this.
Here&#8217;s how to use the Jetty distribution, leveraging <code>start.jar</code>, to perform a stop:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>&gt; java -jar start.jar STOP.PORT=8181 STOP.KEY=abc123 --stop</pre>
</div>
</div>
<div class="quoteblock">
<blockquote>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
To perform a graceful shutdown of Jetty, the <code>stats</code> <a href="#startup-modules">module</a> <strong>must</strong> be enabled.
</td>
</tr>
</table>
</div>
</blockquote>
</div>
</div>
<div class="sect4">
<h5 id="og-advanced-commands"><a class="anchor" href="#og-advanced-commands"></a><a class="link" href="#og-advanced-commands">Advanced Commands</a></h5>
<div class="dlist">
<dl>
<dt class="hdlist1">--lib=&lt;classpath&gt;</dt>
<dd>
<p>Add arbitrary classpath entries to the the server classpath.</p>
</dd>
<dt class="hdlist1">--include-jetty-dir=&lt;path&gt;</dt>
<dd>
<p>Include an extra Jetty directory to use as a source for configuration details.
This directory behaves similarly to <code>${jetty.base}</code> but sits at a layer between <code>${jetty.base}</code> and <code>${jetty.home}</code>.
This allows for some complex hierarchies of configuration details.</p>
</dd>
<dt class="hdlist1">--download=&lt;http-uri&gt;|&lt;location&gt;</dt>
<dd>
<p>If the file does not exist at the given location, download it from the given http URI.
Note: location is always relative to <code>${jetty.base}</code>.
You might need to escape the slash "\|" to use this on some environments.</p>
</dd>
<dt class="hdlist1">maven.repo.uri=[url]</dt>
<dd>
<p>The url to use to download Maven dependencies.
Default is <a href="https://repo1.maven.org/maven2/" class="bare">https://repo1.maven.org/maven2/</a>.</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-shaded-start-jar"><a class="anchor" href="#og-shaded-start-jar"></a><a class="link" href="#og-shaded-start-jar">Shaded Start.jar</a></h4>
<div class="paragraph">
<p>If you have a need for a shaded version of <code>start.jar</code> (such as for Gradle), you can achieve this via a Maven dependency.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
&lt;groupId&gt;org.eclipse.jetty&lt;/groupId&gt;
&lt;artifactId&gt;jetty-start&lt;/artifactId&gt;
&lt;version&gt;{VERSION}&lt;/version&gt;
&lt;classifier&gt;shaded&lt;/classifier&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-start-jar-without-exec-or-forking"><a class="anchor" href="#og-start-jar-without-exec-or-forking"></a><a class="link" href="#og-start-jar-without-exec-or-forking">Start.jar without exec or forking.</a></h4>
<div class="paragraph">
<p>Some Jetty modules include the <code>--exec</code> option so that java command line options can be set.
Also some <code>start.jar</code> options (eg. <code>--jpms</code>) include an implicit <code>--exec</code>.
To start jetty without forking a new JVM instance from the start JVM, the <code>--dry-run</code> option can be used to generate a command line:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ CMD=$(java -jar start.jar --dry-run)
$ $CMD</pre>
</div>
</div>
<div class="paragraph">
<p>It is possible to decompose the start command so that it can be modified:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ OPTS=$(java -jar start.jar --dry-run=opts,path)
$ MAIN=$(java -jar start.jar --dry-run=main)
$ ARGS=$(java -jar start.jar --dry-run=args)
$ java $OPTS -Dextra=opt $MAIN $ARGS extra=arg</pre>
</div>
</div>
<div class="paragraph">
<p>Alternatively to create an args file for java:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar start.jar --dry-run=opts,path,main,args &gt; /tmp/args
$ java @/tmp/args</pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-deploy"><a class="anchor" href="#og-deploy"></a><a class="link" href="#og-deploy">Customizing Web Application Deployment</a></h3>
<div class="paragraph">
<p>Most of the times you want to be able to customize the deployment of your web applications, for example by changing the <code>contextPath</code>, or by adding JNDI entries, or by configuring virtual hosts, etc.</p>
</div>
<div class="paragraph">
<p>The customization is performed by the <a href="#og-module-deploy"><code>deploy</code> module</a> by processing <a href="#og-deploy-jetty">Jetty context XML files</a>.</p>
</div>
<div class="paragraph">
<p>The <code>deploy</code> module contains the <code>DeploymentManager</code> component that scans the <code>$JETTY_BASE/webapps</code> directory for changes, following the deployment rules described in <a href="#og-deploy-rules">this section</a>.</p>
</div>
<div class="sect3">
<h4 id="og-deploy-hot-static"><a class="anchor" href="#og-deploy-hot-static"></a><a class="link" href="#og-deploy-hot-static">Hot vs Static Deployment</a></h4>
<div class="paragraph">
<p>The <code>DeploymentManager</code> scans the <code>$JETTY_BASE/webapps</code> directory for changes every <code>N</code> seconds, where <code>N</code> is configured via the <code>jetty.deploy.scanInterval</code> property.</p>
</div>
<div class="paragraph">
<p>By default, the scan interval is <code>1</code> second, which means that <em>hot</em> deployment is enabled: if a file is added/changed/removed from the <code>$JETTY_BASE/webapps</code> directory, the <code>DeploymentManager</code> will notice the change and respectively deploy/redeploy/undeploy the web application.</p>
</div>
<div class="paragraph">
<p>Setting the scan interval to <code>0</code> means that <em>static</em> deployment is enabled, and the <code>DeploymentManager</code> will not scan the <code>$JETTY_BASE/webapps</code> directory for changes.
This means that to deploy/redeploy/undeploy a web application you will need to stop and restart Jetty.</p>
</div>
<div class="paragraph">
<p>The following command line disables <em>hot</em> deployment by specifying the <code>jetty.deploy.scanInterval</code> property on the command line, and therefore only for this particular run:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar jetty.deploy.scanInterval=0</pre>
</div>
</div>
<div class="paragraph">
<p>To make <em>static</em> deployment persistent, you need to edit the <code>deploy</code> module configuration file, <code>$JETTY_BASE/start.d/deploy.ini</code>, uncomment the module property <code>jetty.deploy.scanInterval</code> and change its value to <code>0</code>:</p>
</div>
<div class="listingblock">
<div class="title">deploy.ini</div>
<div class="content">
<pre class="highlight"><code>--module=deploy
<mark>jetty.deploy.scanInterval=0</mark>
...</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-deploy-rules"><a class="anchor" href="#og-deploy-rules"></a><a class="link" href="#og-deploy-rules">Deployment Rules</a></h4>
<div class="paragraph">
<p><em>Adding</em> a <code>*.war</code> file, a <code>*.war</code> directory, a Jetty context XML file or a normal directory to <code>$JETTY_BASE/webapps</code> causes the <code>DeploymentManager</code> to deploy the new web application.</p>
</div>
<div class="paragraph">
<p><em>Updating</em> a <code>*.war</code> file or a Jetty context XML file causes the <code>DeploymentManager</code> to redeploy the web application, which means that the Jetty context component representing the web application is stopped, then reconfigured, and then restarted.</p>
</div>
<div class="paragraph">
<p><em>Removing</em> a <code>*.war</code> file, a <code>*.war</code> directory, a Jetty context XML file or a normal directory from <code>$JETTY_BASE/webapps</code> causes the <code>DeploymentManager</code> to undeploy the web application, which means that the Jetty context component representing the web application is stopped and removed from the Jetty server.</p>
</div>
<div class="paragraph">
<p>When a file or directory is added to <code>$JETTY_BASE/webapps</code>, the <code>DeploymentManager</code> derives the web application <code>contextPath</code> from the file or directory name, with the following rules:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If the directory name is, for example, <code>mywebapp/</code>, it is deployed as a standard web application if it contains a <code>WEB-INF/</code> subdirectory, otherwise it is deployed as a web application of static content.
The <code>contextPath</code> would be <code>/mywebapp</code> (that is, the web application is reachable at <code>http://localhost:8080/mywebapp/</code>).</p>
</li>
<li>
<p>If the directory name is <code>ROOT</code>, case insensitive, the <code>contextPath</code> is <code>/</code> (that is, the web application is reachable at <code>http://localhost:8080/</code>).</p>
</li>
<li>
<p>If the directory name ends with <code>.d</code>, for example <code>config.d/</code>, it is ignored, although it may be referenced to configure other web applications (for example to store common files).</p>
</li>
<li>
<p>If the <code>*.war</code> file name is, for example, <code>mywebapp.war</code>, it is deployed as a standard web application with the context path <code>/mywebapp</code> (that is, the web application is reachable at <code>http://localhost:8080/mywebapp/</code>).</p>
</li>
<li>
<p>If the file name is <code>ROOT.war</code>, case insensitive, the <code>contextPath</code> is <code>/</code> (that is, the web application is reachable at <code>http://localhost:8080/</code>).</p>
</li>
<li>
<p>If both the <code>mywebapp.war</code> file and the <code>mywebapp/</code> directory exist, only the file is deployed.
This allows the directory with the same name to be the <code>*.war</code> file unpack location and avoid that the web application is deployed twice.</p>
</li>
<li>
<p>A <a href="#og-deploy-jetty">Jetty context XML file</a> named <code>mywebapp.xml</code> is deployed as a web application by processing the directives contained in the XML file itself, which must set the <code>contextPath</code>.</p>
</li>
<li>
<p>If both <code>mywebapp.xml</code> and <code>mywebapp.war</code> exist, only the XML file is deployed.
This allows the XML file to reference the <code>*.war</code> file and avoid that the web application is deployed twice.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="og-deploy-jetty"><a class="anchor" href="#og-deploy-jetty"></a><a class="link" href="#og-deploy-jetty">Deploying Jetty Context XML Files</a></h4>
<div class="paragraph">
<p>A Jetty context XML file is a <a href="#og-xml">Jetty XML file</a> that allows you to customize the deployment of web applications.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Recall that the <code>DeploymentManager</code> component of the Jetty <code>deploy</code> module <a href="#og-deploy-rules">gives priority</a> to Jetty context XML files over <code>*.war</code> files or directories.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>To deploy a web application using a Jetty context XML file, simply place the file in the <code>$JETTY_BASE/webapps</code> directory.</p>
</div>
<div class="paragraph">
<p>A simple Jetty context XML file, for example named <code>wiki.xml</code> is the following:</p>
</div>
<div class="listingblock">
<div class="title">wiki.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt; <i class="conum" data-value="1"></i><b>(1)</b>
&lt;Set name="contextPath"&gt;/wiki&lt;/Set&gt; <i class="conum" data-value="2"></i><b>(2)</b>
&lt;Set name="war"&gt;/opt/myapps/myapp.war&lt;/Set&gt; <i class="conum" data-value="3"></i><b>(3)</b>
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Configures a <a href="http://www.eclipse.org/jetty/javadoc/11.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html"><code>WebAppContext</code></a>, which is the Jetty component that represents a standard Servlet web application.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Specifies the web application <code>contextPath</code>, which may be different from the <code>*.war</code> file name.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Specifies the file system path of the <code>*.war</code> file.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The <code>$JETTY_BASE</code> directory would look like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$JETTY_BASE
├── resources
│ └── jetty-logging.properties
├── start.d
│ ├── deploy.ini
│ └── http.ini
└── webapps
└── wiki.xml</pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
The <code>*.war</code> file may be placed anywhere in the file system and does not need to be placed in the <code>$JETTY_BASE/webapps</code> directory.
</td>
</tr>
</table>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
If you place both the Jetty context XML file <em>and</em> the <code>*.war</code> file in the <code>$JETTY_BASE/webapps</code> directory, remember that they must have the same file name, for example <code>wiki.xml</code> and <code>wiki.war</code>, so that the <code>DeploymentManager</code> deploys the web application only once using the Jetty context XML file (and not the <code>*.war</code> file).
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>You can use the features of <a href="#og-xml">Jetty XML files</a> to avoid to hard-code file system paths or other configurations in your Jetty context XML files, for example by using system properties:</p>
</div>
<div class="listingblock">
<div class="title">wiki.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;/wiki&lt;/Set&gt;
&lt;Set name="war"&gt;&lt;SystemProperty name="myapps.dir"/&gt;/myapp.war&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how the <code>*.war</code> file path is now obtained by resolving the system property <code>myapps.dir</code> that you can specify on the command line when you start Jetty:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar -Dmyapps.dir=/opt/myapps</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-deploy-jndi"><a class="anchor" href="#og-deploy-jndi"></a><a class="link" href="#og-deploy-jndi">Configuring JNDI Entries</a></h4>
<div class="paragraph">
<p>A web application may <em>reference</em> a JNDI entry, such as a JDBC <code>DataSource</code> from the web application <code>web.xml</code> file.
The JNDI entry must be <em>defined</em> in the Jetty context XML file, for example:</p>
</div>
<div class="listingblock">
<div class="title">mywebapp.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;/mywebapp&lt;/Set&gt;
&lt;Set name="war"&gt;/opt/webapps/mywebapp.war&lt;/Set&gt;
<mark>&nbsp;&nbsp;&lt;New class="org.eclipse.jetty.plus.jndi.Resource"&gt;
&lt;Arg /&gt;
&lt;Arg&gt;jdbc/myds&lt;/Arg&gt;
&lt;Arg&gt;
&lt;New class="com.mysql.cj.jdbc.MysqlConnectionPoolDataSource"&gt;
&lt;Set name="url"&gt;jdbc:mysql://localhost:3306/databasename&lt;/Set&gt;
&lt;Set name="user"&gt;user&lt;/Set&gt;
&lt;Set name="password"&gt;password&lt;/Set&gt;
&lt;/New&gt;
&lt;/Arg&gt;
&lt;/New&gt;</mark>
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Class <code>com.mysql.cj.jdbc.MysqlConnectionPoolDataSource</code> is present in the MySQL JDBC driver file, <code>mysql-connector-java-&lt;version&gt;.jar</code>, which must be available to the web application.</p>
</div>
<div class="paragraph">
<p>File <code>mysql-connector-java-&lt;version&gt;.jar</code> must be either present in <code>WEB-INF/lib</code>, or in the Jetty server class-path.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="og-deploy-virtual-hosts"><a class="anchor" href="#og-deploy-virtual-hosts"></a><a class="link" href="#og-deploy-virtual-hosts">Configuring Virtual Hosts</a></h4>
<div class="paragraph">
<p>A <em>virtual host</em> 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.</p>
</div>
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>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 <code>http://domain.biz/</code>, and the second web application available at <code>http://hobby.net/</code>.</p>
</div>
<div class="paragraph">
<p>Another typical case is when you want to use different subdomains for different web application, for example a project website is at <code>http://project.org/</code> and the project documentation is at <code>http://docs.project.org</code>.</p>
</div>
<div class="paragraph">
<p>Virtual hosts can be used with any context that is a subclass of <a href="http://www.eclipse.org/jetty/javadoc/11.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/ContextHandler.html">ContextHandler</a>.</p>
</div>
<div class="sect4">
<h5 id="og-deploy-virtual-hosts-names"><a class="anchor" href="#og-deploy-virtual-hosts-names"></a><a class="link" href="#og-deploy-virtual-hosts-names">Virtual Host Names</a></h5>
<div class="paragraph">
<p>Jetty supports the following variants to be specified as virtual host names:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>www.hostname.com</code></dt>
<dd>
<p>A fully qualified domain name. It is important to list all variants as a site may receive traffic for both <code>www.hostname.com</code> and <code>hostname.com</code>.</p>
</dd>
<dt class="hdlist1"><code>*.hostname.com</code></dt>
<dd>
<p>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.</p>
</dd>
<dt class="hdlist1"><code>10.0.0.2</code></dt>
<dd>
<p>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.</p>
</dd>
<dt class="hdlist1"><code>@ConnectorName</code></dt>
<dd>
<p>A Jetty <code>ServerConnector</code> name to indicate that a web application should handle requests received on the <code>ServerConnector</code> with that name, and therefore received on a specific IP port.
A <code>ServerConnector</code> name can be set via <a href="http://www.eclipse.org/jetty/javadoc/11.0.0-SNAPSHOT/org/eclipse/jetty/server/AbstractConnector.html#setName(java.lang.String)" class="bare">http://www.eclipse.org/jetty/javadoc/11.0.0-SNAPSHOT/org/eclipse/jetty/server/AbstractConnector.html#setName(java.lang.String)</a>.</p>
</dd>
<dt class="hdlist1"><code>www.√integral.com</code></dt>
<dd>
<p>Non-ASCII and <a href="https://en.wikipedia.org/wiki/Internationalized_domain_name">IDN</a> domain names can be set as virtual hosts using <a href="https://en.wikipedia.org/wiki/Punycode">Puny Code</a> equivalents that may be obtained from a <a href="https://www.punycoder.com/">Punycode/IDN converters</a>.
For example if the non-ASCII domain name <code>www.√integral.com</code> is given to a browser, then the browser will make a request that uses the domain name <code>www.xn&#8212;&#8203;integral-7g7d.com</code>, which is the name that should be added as the virtual host name.</p>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-deploy-virtual-hosts-config"><a class="anchor" href="#og-deploy-virtual-hosts-config"></a><a class="link" href="#og-deploy-virtual-hosts-config">Virtual Hosts Configuration</a></h5>
<div class="paragraph">
<p>If you have a web application <code>mywebapp.war</code> you can configure its virtual hosts in this way:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;/mywebapp&lt;/Set&gt;
&lt;Set name="war"&gt;/opt/webapps/mywebapp.war&lt;/Set&gt;
&lt;Set name="virtualHosts"&gt;
&lt;Array type="java.lang.String"&gt;
&lt;Item&gt;mywebapp.com&lt;/Item&gt;
&lt;Item&gt;www.mywebapp.com&lt;/Item&gt;
&lt;Item&gt;mywebapp.net&lt;/Item&gt;
&lt;Item&gt;www.mywebapp.net&lt;/Item&gt;
&lt;/Array&gt;
&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Your web application will be available at:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>http://mywebapp.com/mywebapp</code></p>
</li>
<li>
<p><code>http://www.mywebapp.com/mywebapp</code></p>
</li>
<li>
<p><code>http://mywebapp.net/mywebapp</code></p>
</li>
<li>
<p><code>http://www.mywebapp.net/mywebapp</code></p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You configured the <code>contextPath</code> of your web application to <code>/mywebapp</code>.</p>
</div>
<div class="paragraph">
<p>As such, a request to <code>http://mywebapp.com/other</code> will not match your web application because the <code>contextPath</code> does not match.</p>
</div>
<div class="paragraph">
<p>Likewise, a request to <code>http://other.com/mywebapp</code> will not match your web application because the virtual host does not match.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="og-deploy-virtual-hosts-same-context"><a class="anchor" href="#og-deploy-virtual-hosts-same-context"></a><a class="link" href="#og-deploy-virtual-hosts-same-context">Same Context Path, Different Virtual Hosts</a></h5>
<div class="paragraph">
<p>If you want to deploy different web applications to the same context path, typically the root context path <code>/</code>, you must use virtual hosts to differentiate among web applications.</p>
</div>
<div class="paragraph">
<p>You have <code>domain.war</code> that you want to deploy at <code>http://domain.biz/</code> and <code>hobby.war</code> that you want to deploy at <code>http://hobby.net</code>.</p>
</div>
<div class="paragraph">
<p>To achieve this, you simply use the same context path of <code>/</code> for each of your webapps, while specifying different virtual hosts for each of your webapps:</p>
</div>
<div class="listingblock">
<div class="title">domain.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;/&lt;/Set&gt;
&lt;Set name="war"&gt;/opt/webapps/domain.war&lt;/Set&gt;
&lt;Set name="virtualHosts"&gt;
&lt;Array type="java.lang.String"&gt;
&lt;Item&gt;domain.biz&lt;/Item&gt;
&lt;/Array&gt;
&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">hobby.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;/&lt;/Set&gt;
&lt;Set name="war"&gt;/opt/webapps/hobby.war&lt;/Set&gt;
&lt;Set name="virtualHosts"&gt;
&lt;Array type="java.lang.String"&gt;
&lt;Item&gt;hobby.net&lt;/Item&gt;
&lt;/Array&gt;
&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-deploy-virtual-hosts-port"><a class="anchor" href="#og-deploy-virtual-hosts-port"></a><a class="link" href="#og-deploy-virtual-hosts-port">Different Port, Different Web Application</a></h5>
<div class="paragraph">
<p>Sometimes it is required to serve different web applications from different IP ports, and therefore from different <code>ServerConnector</code>s.</p>
</div>
<div class="paragraph">
<p>For example, you want requests to <code>http://localhost:8080/</code> to be served by one web application, but requests to <code>http://localhost:9090/</code> to be served by another web application.</p>
</div>
<div class="paragraph">
<p>This configuration may be useful when Jetty sits behind a load balancer.</p>
</div>
<div class="paragraph">
<p>In this case, you want to <a href="#og-protocols">configure multiple connectors</a>, each with a different name, and then reference the connector name in the web application virtual host configuration:</p>
</div>
<div class="listingblock">
<div class="title">domain.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;/&lt;/Set&gt;
&lt;Set name="war"&gt;/opt/webapps/domain.war&lt;/Set&gt;
&lt;Set name="virtualHosts"&gt;
&lt;Array type="java.lang.String"&gt;
&lt;Item&gt;@port8080&lt;/Item&gt;
&lt;/Array&gt;
&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">hobby.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;/&lt;/Set&gt;
&lt;Set name="war"&gt;/opt/webapps/hobby.war&lt;/Set&gt;
&lt;Set name="virtualHosts"&gt;
&lt;Array type="java.lang.String"&gt;
&lt;Item&gt;@port9090&lt;/Item&gt;
&lt;/Array&gt;
&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Web application <code>domain.war</code> has a virtual host of <code>@port8080</code>, where <code>port8080</code> is the name of a Jetty connector.</p>
</div>
<div class="paragraph">
<p>Likewise, web application <code>hobby.war</code> has a virtual host of <code>@port9090</code>, where <code>port9090</code> is the name of another Jetty connector.</p>
</div>
<div class="paragraph">
<p>See <a href="#og-protocols">this section</a> for further information about how to configure connectors.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-deploy-extract-war"><a class="anchor" href="#og-deploy-extract-war"></a><a class="link" href="#og-deploy-extract-war">Configuring <code>*.war</code> File Extraction</a></h4>
<div class="paragraph">
<p>By default, <code>*.war</code> 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 <code>*.war</code> file, for performance reasons.</p>
</div>
<div class="paragraph">
<p>If you do not want Jetty to extract the <code>*.war</code> files, you can disable this feature, for example:</p>
</div>
<div class="listingblock">
<div class="title">mywebapp.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;/mywebapp&lt;/Set&gt;
&lt;Set name="war"&gt;/opt/webapps/mywebapp.war&lt;/Set&gt;
&lt;Set name="extractWAR"&gt;false&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-deploy-jetty-override-web-xml"><a class="anchor" href="#og-deploy-jetty-override-web-xml"></a><a class="link" href="#og-deploy-jetty-override-web-xml">Overriding <code>web.xml</code></a></h4>
<div class="paragraph">
<p>You can configure an additional <code>web.xml</code> that complements the <code>web.xml</code> file that is present in the web application <code>*.war</code> file.
This additional <code>web.xml</code> is processed <em>after</em> the <code>*.war</code> file <code>web.xml</code>.
This allows you to add host specific configuration or server specific configuration without having to extract the web application <code>web.xml</code>, modify it, and repackage it in the <code>*.war</code> file.</p>
</div>
<div class="listingblock">
<div class="title">mywebapp.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;/mywebapp&lt;/Set&gt;
&lt;Set name="war"&gt;/opt/webapps/mywebapp.war&lt;/Set&gt;
&lt;Set name="overrideDescriptor"&gt;/opt/webapps/mywebapp-web.xml&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The format of the additional <code>web.xml</code> is exactly the same as a standard <code>web.xml</code> file, for example:</p>
</div>
<div class="listingblock">
<div class="title">mywebapp-web.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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_4_0.xsd"
version="4.0"&gt;
&lt;servlet&gt;
&lt;servlet-name&gt;my-servlet&lt;/servlet-name&gt;
&lt;init-param&gt;
&lt;param-name&gt;host&lt;/param-name&gt;
&lt;param-value&gt;192.168.0.13&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/servlet&gt;
&lt;/web-app&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>In the example above, you configured the <code>my-servlet</code> Servlet (defined in the web application <code>web.xml</code>), adding a host specific <code>init-param</code> with the IP address of the host.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-deploy-init-params"><a class="anchor" href="#og-deploy-init-params"></a><a class="link" href="#og-deploy-init-params">Configuring <code>init-param</code>s</a></h4>
<div class="paragraph">
<p>TODO</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-protocols"><a class="anchor" href="#og-protocols"></a><a class="link" href="#og-protocols">Configuring Eclipse Jetty Connectors and Protocols</a></h3>
<div class="paragraph">
<p>Connectors are the network components through which Jetty accepts incoming network connections.</p>
</div>
<div class="paragraph">
<p>Each connector listens on a network port and can be configured with <code>ConnectionFactory</code> components that <em>understand</em> one or more network protocols.</p>
</div>
<div class="paragraph">
<p>Understanding a protocol means that the connector is able to interpret incoming network bytes (for example, the bytes that represent an HTTP/1.1 request) and convert them into more abstract objects (for example an <code>HttpServletRequest</code> object) that are then processed by applications.
Conversely, an abstract object (for example an <code>HttpServletResponse</code>) is converted into the correspondent outgoing network bytes (the bytes that represent an HTTP/1.1 response).</p>
</div>
<div class="paragraph">
<p>Like other Jetty components, connectors are enabled and configured by enabling and configuring the correspondent Jetty module.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
Recall that you must always issue the commands to enable Jetty modules from within the <code>$JETTY_BASE</code> directory, and that the Jetty module configuration files are in the <code>$JETTY_BASE/start.d/</code> directory.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>You can obtain the list of connector-related modules in this way:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --list-modules=connector</pre>
</div>
</div>
<div class="sect3">
<h4 id="og-protocols-http"><a class="anchor" href="#og-protocols-http"></a><a class="link" href="#og-protocols-http">Configuring Clear-Text HTTP/1.1</a></h4>
<div class="paragraph">
<p>Clear text HTTP/1.1 is enabled with the <code>http</code> Jetty module with the following command (issued from within the <code>$JETTY_BASE</code> directory):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=http</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>INFO : mkdir ${jetty.base}/start.d
INFO : server transitively enabled, ini template available with --add-module=server
INFO : logging-jetty transitively enabled
INFO : http initialized in ${jetty.base}/start.d/http.ini
INFO : resources transitively enabled
INFO : threadpool transitively enabled, ini template available with --add-module=threadpool
INFO : logging/slf4j dynamic dependency of logging-jetty
INFO : bytebufferpool transitively enabled, ini template available with --add-module=bytebufferpool
INFO : mkdir ${jetty.base}/resources
INFO : copy ${jetty.home}/modules/logging/jetty/resources/jetty-logging.properties to ${jetty.base}/resources/jetty-logging.properties
INFO : Base directory was modified</pre>
</div>
</div>
<div class="paragraph">
<p>After having enabled the <code>http</code> module, the <code>$JETTY_BASE</code> directory looks like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>JETTY_BASE
├── resources
│ └── jetty-logging.properties
└── start.d
└── <mark>http.ini</mark></code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>http.ini</code> file is the file that you want to edit to configure network and protocol parameters&#8201;&#8212;&#8201;for more details see <a href="#og-module-http">this section</a>.</p>
</div>
<div class="paragraph">
<p>Note that the <code>http</code> Jetty module depends on the <code>server</code> Jetty module.</p>
</div>
<div class="paragraph">
<p>Some parameters that you may want to configure are in fact common HTTP parameters that are applied not only for clear-text HTTP/1.1, but also for secure HTTP/1.1 or for clear-text HTTP/2 or for encrypted HTTP/2, and these configuration parameters may be present in the <code>server</code> module configuration file.</p>
</div>
<div class="paragraph">
<p>You can force the creation of the <code>server.ini</code> file via:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=server</pre>
</div>
</div>
<div class="paragraph">
<p>Now the <code>$JETTY_BASE</code> directory looks like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>JETTY_BASE
├── resources
│ └── jetty-logging.properties
└── start.d
├── http.ini
└── server.ini</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now you can edit the <code>server.ini</code> file&#8201;&#8212;&#8201;for more details see <a href="#og-module-server">this section</a>.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-protocols-https"><a class="anchor" href="#og-protocols-https"></a><a class="link" href="#og-protocols-https">Configuring Secure HTTP/1.1</a></h4>
<div class="paragraph">
<p>Secure HTTP/1.1 is enabled with both the <code>ssl</code> and <code>https</code> Jetty modules with the following command (issued from within the <code>$JETTY_BASE</code> directory):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=ssl,https</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>INFO : mkdir ${jetty.base}/start.d
INFO : server transitively enabled, ini template available with --add-module=server
INFO : logging-jetty transitively enabled
INFO : resources transitively enabled
INFO : https initialized in ${jetty.base}/start.d/https.ini
INFO : ssl initialized in ${jetty.base}/start.d/ssl.ini
INFO : threadpool transitively enabled, ini template available with --add-module=threadpool
INFO : logging/slf4j transitive provider of logging/slf4j for logging-jetty
INFO : logging/slf4j dynamic dependency of logging-jetty
INFO : bytebufferpool transitively enabled, ini template available with --add-module=bytebufferpool
INFO : mkdir ${jetty.base}/resources
INFO : copy ${jetty.home}/modules/logging/jetty/resources/jetty-logging.properties to ${jetty.base}/resources/jetty-logging.properties
INFO : Base directory was modified</pre>
</div>
</div>
<div class="paragraph">
<p>The command above enables the <code>ssl</code> module, that provides the secure network connector, the keystore configuration and TLS configuration&#8201;&#8212;&#8201;for more details see <a href="#og-protocols-ssl">this section</a>.
Then, the <a href="#og-module-https"><code>https</code> module</a> adds HTTP/1.1 as the protocol secured by TLS.</p>
</div>
<div class="paragraph">
<p>The <code>$JETTY_BASE</code> directory looks like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>$JETTY_BASE
├── resources
│ └── jetty-logging.properties
└── start.d
├── https.ini
└── ssl.ini</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that the keystore file is missing, because you have to provide one with the cryptographic material you want (read <a href="#og-keystore">this section</a> to create your own keystore).
You need to configure these two properties by editing <code>ssl.ini</code>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>jetty.sslContext.keyStorePath</code></p>
</li>
<li>
<p><code>jetty.sslContext.keyStorePassword</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>As a quick example, you can enable the <a href="#og-module-test-keystore"><code>test-keystore</code> module</a>, that provides a keystore containing a self-signed certificate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=test-keystore</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>INFO : test-keystore initialized in ${jetty.base}/start.d/test-keystore.ini
INFO : mkdir ${jetty.base}/etc
INFO : copy ${jetty.home}/modules/test-keystore/test-keystore.p12 to ${jetty.base}/etc/test-keystore.p12
INFO : Base directory was modified</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>$JETTY_BASE</code> directory is now:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>├── etc
│ └── <mark>test-keystore.p12</mark>
├── resources
│ └── jetty-logging.properties
└── start.d
├── https.ini
├── ssl.ini
└── test-keystore.ini</code></pre>
</div>
</div>
<div class="paragraph">
<p>Starting Jetty yields:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>2020-09-22 08:40:49.482:INFO :oejs.Server:main: jetty-10.0.0-SNAPSHOT; built: 2020-09-21T14:44:05.094Z; git: 5c33f526e5b7426dd9644ece61b10184841bb8fa; jvm 15+36-1562
2020-09-22 08:40:49.709:INFO :oejus.SslContextFactory:main: x509=X509@14cd1699(mykey,h=[localhost],w=[]) for Server@73a1e9a9[provider=null,keyStore=file:///tmp/jetty.base/etc/test-keystore.p12,trustStore=file:///tmp/jetty.base/etc/test-keystore.p12]
2020-09-22 08:40:49.816:INFO :oejs.AbstractConnector:main: Started ServerConnector@2e1d27ba<mark>{SSL, (ssl, http/1.1)}{0.0.0.0:8443}</mark>
2020-09-22 08:40:49.828:INFO :oejs.Server:main: Started Server@2f177a4b{STARTING}[10.0.0-SNAPSHOT,sto=5000] @814ms</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how Jetty is listening on port <code>8443</code> for the secure HTTP/1.1 protocol.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>If you point your browser at <code>https://localhost:8443/</code> you will get a warning from the browser about a "potential security risk ahead", or that "your connection is not private", or similar message depending on the browser.</p>
</div>
<div class="paragraph">
<p>This is normal because the certificate contained in <code>test-keystore.p12</code> is self-signed&#8201;&#8212;&#8201;and as such not signed by a recognized certificate authority&#8201;&#8212;&#8201;and therefore browsers do not trust it.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="og-protocols-http2"><a class="anchor" href="#og-protocols-http2"></a><a class="link" href="#og-protocols-http2">Configuring HTTP/2</a></h4>
<div class="paragraph">
<p><a href="https://tools.ietf.org/html/rfc7540">HTTP/2</a> is the successor of the HTTP/1.1 protocol, but it is quite different from HTTP/1.1: where HTTP/1.1 is a duplex, text-based protocol, HTTP/2 is a multiplex, binary protocol.</p>
</div>
<div class="paragraph">
<p>Because of these fundamental differences, a client and a server need to <em>negotiate</em> what version of the HTTP protocol they speak, based on what versions each side supports.</p>
</div>
<div class="paragraph">
<p>To ensure maximum compatibility, and reduce the possibility that an intermediary that only understands HTTP/1.1 will close the connection when receiving unrecognized HTTP/2 bytes, HTTP/2 is typically deployed over secure connections, using the TLS protocol to wrap HTTP/2.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
Browsers only support secure HTTP/2.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The protocol negotiation is performed by the <a href="https://tools.ietf.org/html/rfc7301">ALPN TLS extension</a>: the client advertises the list of protocols it can speak, and the server communicates to the client the protocol chosen by the server.</p>
</div>
<div class="paragraph">
<p>For example, you can have a client that only supports HTTP/1.1 and a server that supports both HTTP/1.1 and HTTP/2:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="diag-e2488cc783b3434076c5a44ee7f19a2b.png" alt="diag e2488cc783b3434076c5a44ee7f19a2b" width="380" height="420">
</div>
</div>
<div class="paragraph">
<p>Nowadays, it&#8217;s common that both clients and servers support HTTP/2, so servers prefer HTTP/2 as the protocol to speak:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="diag-8a7fb4bb9c84453a4bf01a24558e8026.png" alt="diag 8a7fb4bb9c84453a4bf01a24558e8026" width="415" height="420">
</div>
</div>
<div class="paragraph">
<p>When you configure a connector with the HTTP/2 protocol, you typically want to also configure the HTTP/1.1 protocol.
The reason to configure both protocols is that you typically do not control the clients: for example an old browser that does not support HTTP/2, or a monitoring console that performs requests using HTTP/1.1, or a heartbeat service that performs a single HTTP/1.0 request to verify that the server is alive.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-secure-vs-clear-text-http2"><a class="anchor" href="#og-secure-vs-clear-text-http2"></a><a class="link" href="#og-secure-vs-clear-text-http2">Secure vs Clear-Text HTTP/2</a></h4>
<div class="paragraph">
<p>Deciding whether you want to configure Jetty with <a href="#og-protocols-http2s">secure HTTP/2</a> or <a href="#og-protocols-http2c">clear-text HTTP/2</a> depends on your use case.</p>
</div>
<div class="paragraph">
<p>You want to configure secure HTTP/2 when Jetty is exposed directly to browsers, because browsers only support secure HTTP/2.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="diag-7387dfbb6f9fb9cfa951a697aca488a8.png" alt="diag 7387dfbb6f9fb9cfa951a697aca488a8" width="307" height="210">
</div>
</div>
<div class="paragraph">
<p>You may configure clear-text HTTP/2 (mostly for performance reasons) if you offload TLS at a load balancer (for example, <a href="https://haproxy.org/">HAProxy</a>) or at a reverse proxy (for example, <a href="https://nginx.org/">nginx</a>).</p>
</div>
<div class="imageblock">
<div class="content">
<img src="diag-70817cc5c7137abc9759cdcd3edbb658.png" alt="diag 70817cc5c7137abc9759cdcd3edbb658" width="307" height="210">
</div>
</div>
<div class="paragraph">
<p>You may configure clear-text HTTP/2 (mostly for performance reasons) to call microservices deployed to different Jetty servers (although you may want to use secure HTTP/2 for confidentiality reasons).</p>
</div>
<div class="imageblock">
<div class="content">
<img src="diag-2830e38460d606111888c5df2a645163.png" alt="diag 2830e38460d606111888c5df2a645163" width="307" height="210">
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-protocols-http2s"><a class="anchor" href="#og-protocols-http2s"></a><a class="link" href="#og-protocols-http2s">Configuring Secure HTTP/2</a></h4>
<div class="paragraph">
<p>When you enable secure HTTP/2 you typically want to enable also secure HTTP/1.1, for backwards compatibility reasons: in this way, old browsers or other clients that do not support HTTP/2 will be able to connect to your server.</p>
</div>
<div class="paragraph">
<p>You need to enable:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>the <code>ssl</code> Jetty module, which provides the secure connector and the keystore and TLS configuration</p>
</li>
<li>
<p>the <code>http2</code> Jetty module, which adds ALPN handling and adds the HTTP/2 protocol to the secured connector</p>
</li>
<li>
<p>optionally, the <code>https</code> Jetty module, which adds the HTTP/1.1 protocol to the secured connector</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Use the following command (issued from within the <code>$JETTY_BASE</code> directory):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=ssl,http2,https</pre>
</div>
</div>
<div class="paragraph">
<p>As when enabling the <code>https</code> Jetty module, you need a valid keystore (read <a href="#og-keystore">this section</a> to create your own keystore).</p>
</div>
<div class="paragraph">
<p>As a quick example, you can enable the <a href="#og-module-test-keystore"><code>test-keystore</code> module</a>, that provides a keystore containing a self-signed certificate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=test-keystore</pre>
</div>
</div>
<div class="paragraph">
<p>Starting Jetty yields:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>2020-09-29 19:00:47.316:INFO :oejs.Server:main: jetty-10.0.0-SNAPSHOT; built: 2020-09-29T13:28:40.441Z; git: 9c0082610528a846b366ae26f4c74894579a8e48; jvm 15+36-1562
2020-09-29 19:00:47.528:INFO :oejus.SslContextFactory:main: x509=X509@7770f470(mykey,h=[localhost],w=[]) for Server@24313fcc[provider=null,keyStore=file:///tmp/jetty.base/etc/test-keystore.p12,trustStore=file:///tmp/jetty.base/etc/test-keystore.p12]
2020-09-29 19:00:47.621:INFO :oejs.AbstractConnector:main: Started ServerConnector@73700b80<mark>{SSL, (ssl, alpn, h2, http/1.1)}{0.0.0.0:8443}</mark>
2020-09-29 19:00:47.630:INFO :oejs.Server:main: Started Server@30ee2816{STARTING}[10.0.0-SNAPSHOT,sto=5000] @746ms</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how Jetty is listening on port <code>8443</code> and the protocols supported are the sequence <code>(ssl, alpn, h2, http/1.1)</code>.</p>
</div>
<div class="paragraph">
<p>The (ordered) list of protocols after <code>alpn</code> are the <em>application protocols</em>, in the example above <code>(h2, http/1.1)</code>.</p>
</div>
<div class="paragraph">
<p>When a new connection is accepted by the connector, Jetty first interprets the TLS bytes, then it handles the ALPN negotiation knowing that the application protocols are (in order) <code>h2</code> and then <code>http/1.1</code>.</p>
</div>
<div class="paragraph">
<p>You can customize the list of application protocols and the default protocol to use in case the ALPN negotiation fails by editing the <a href="#og-module-alpn"><code>alpn</code> module</a> properties.</p>
</div>
<div class="paragraph">
<p>The HTTP/2 protocol parameters can be configured by editing the <a href="#og-module-http2"><code>http2</code> module</a> properties.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-protocols-http2c"><a class="anchor" href="#og-protocols-http2c"></a><a class="link" href="#og-protocols-http2c">Configuring Clear-Text HTTP/2</a></h4>
<div class="paragraph">
<p>When you enable clear-text HTTP/2 you typically want to enable also clear-text HTTP/1.1, for backwards compatibility reasons and to allow clients to <a href="https://tools.ietf.org/html/rfc7540#section-3.2">upgrade</a> from HTTP/1.1 to HTTP/2.</p>
</div>
<div class="paragraph">
<p>You need to enable:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>the <code>http</code> Jetty module, which provides the clear-text connector and adds the HTTP/1.1 protocol to the clear-text connector</p>
</li>
<li>
<p>the <code>http2c</code> Jetty module, which adds the HTTP/2 protocol to the clear-text connector</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=http,http2c</pre>
</div>
</div>
<div class="paragraph">
<p>Starting Jetty yields:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>2020-09-30 09:18:36.322:INFO :oejs.Server:main: jetty-10.0.0-SNAPSHOT; built: 2020-09-29T22:40:09.015Z; git: ba5f91fe00a68804a586b7dd4e2520c8c948dcc8; jvm 15+36-1562
2020-09-30 09:18:36.349:INFO :oejs.AbstractConnector:main: Started ServerConnector@636be97c<mark>{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8080}</mark>
2020-09-30 09:18:36.361:INFO :oejs.Server:main: Started Server@3c72f59f{STARTING}[10.0.0-SNAPSHOT,sto=5000] @526ms</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how Jetty is listening on port <code>8080</code> and the protocols supported are HTTP/1.1 and <code>h2c</code> (i.e. clear-text HTTP/2).</p>
</div>
<div class="paragraph">
<p>With this configuration, browsers and client applications will be able to connect to port <code>8080</code> using:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>HTTP/1.1 directly (e.g. <code>curl --http1.1 http://localhost:8080</code>):</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre>GET / HTTP/1.1
Host: localhost:8080</pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>HTTP/1.1 with upgrade to HTTP/2 (e.g. <code>curl --http2 http://localhost:8080</code>):</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre>GET / HTTP/1.1
Host: localhost:8080
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings:</pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>HTTP/2 directly (e.g. <code>curl --http2-prior-knowledge http://localhost:8080</code>):</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre>50 52 49 20 2a 20 48 54 54 50 2f 32 2e 30 0d 0a
0d 0a 53 4d 0d 0a 0d 0a 00 00 12 04 00 00 00 00
00 00 03 00 00 00 64 00 04 40 00 00 00 00 02 00
00 00 00 00 00 1e 01 05 00 00 00 01 82 84 86 41
8a a0 e4 1d 13 9d 09 b8 f0 1e 07 7a 88 25 b6 50
c3 ab b8 f2 e0 53 03 2a 2f 2a</pre>
</div>
</div>
<div class="paragraph">
<p>The HTTP/2 protocol parameters can be configured by editing the <a href="#og-module-http2c"><code>http2c</code> module</a> properties.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-protocols-ssl"><a class="anchor" href="#og-protocols-ssl"></a><a class="link" href="#og-protocols-ssl">Configuring Secure Protocols</a></h4>
<div class="paragraph">
<p>Secure protocols are normal protocols such as HTTP/1.1 or WebSocket that are wrapped by the <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLS protocol</a>.
Any network protocol can be wrapped with TLS.</p>
</div>
<div class="paragraph">
<p>The <code>https</code> scheme used in URIs really means <code>tls+http/1.1</code> and similarly the <code>wss</code> scheme used in URIs really means <code>tls+websocket</code>, etc.
Senders wrap the underlying protocol bytes (e.g. HTTP/1.1 bytes or WebSocket bytes) with the TLS protocol, while receivers first interpret the TLS protocol to obtain the underlying protocol bytes, and then interpret the wrapped bytes.</p>
</div>
<div class="paragraph">
<p>Secure protocols have a slightly more complicated configuration since they require to configure a <em>keystore</em>.</p>
</div>
<div class="paragraph">
<p>A keystore is a file on the file system that contains a private key and a public certificate, along with the certificate chain of the certificate authorities that issued the certificate.
The private key, the public certificate and the certificate chain, but more generally the items present in a keystore, are typically referred to as "cryptographic material".</p>
</div>
<div class="paragraph">
<p>Keystores may encode the cryptographic material with different encodings, the most common being <a href="https://en.wikipedia.org/wiki/PKCS_12">PKCS12</a>, and are typically protected by a password.</p>
</div>
<div class="paragraph">
<p>After configuring the keystore path and keystore password, you may want to further customize the parameters of the TLS protocol, such as the minimum TLS protocol version, or the TLS algorithms, etc.</p>
</div>
<div class="paragraph">
<p>The <code>ssl</code> Jetty module allows you to configure a secure network connector&#8201;&#8212;&#8201;i.e. a connector configured with the TLS protocol, the keystore and the TLS parameters; if other modules require encryption, they declare a dependency on the <code>ssl</code> module.</p>
</div>
<div class="paragraph">
<p>It is the job of other Jetty modules to configure the wrapped protocol.</p>
</div>
<div class="paragraph">
<p>For example, it is the <a href="#og-protocols-https"><code>https</code> module</a> that configures the wrapped protocol to be HTTP/1.1.
Similarly, it is the <a href="#og-protocols-http2"><code>http2</code> module</a> that configures the wrapped protocol to be HTTP/2.</p>
</div>
<div class="paragraph">
<p>Recall from the <a href="#og-modules">section about modules</a>, that only modules that are explicitly enabled get their module configuration file (<code>*.ini</code>) saved in <code>$JETTY_BASE/start.d/</code>, and you want <code>$JETTY_BASE/start.d/ssl.ini</code> to be present so that you can configure the connector properties, the keystore properties and the TLS properties.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-modules"><a class="anchor" href="#og-modules"></a><a class="link" href="#og-modules">Jetty Modules</a></h4>
<div class="paragraph">
<p>TODO</p>
</div>
</div>
<div class="sect3">
<h4 id="og-module-bytebufferpool"><a class="anchor" href="#og-module-bytebufferpool"></a><a class="link" href="#og-module-bytebufferpool">Module <code>bytebufferpool</code></a></h4>
<div class="paragraph">
<p>The <code>bytebufferpool</code> module allows you to configure the server-wide <code>ByteBuffer</code> pool.</p>
</div>
<div class="paragraph">
<p>The module file is <code>$JETTY_HOME/modules/bytebufferpool.mod</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>Unresolved directive in modules/module-bytebufferpool.adoc - include::../../../../../../jetty-home/target/jetty-home/modules/bytebufferpool.mod[]</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="paragraph">
<p>TODO</p>
</div>
</div>
<div class="sect3">
<h4 id="og-module-deploy"><a class="anchor" href="#og-module-deploy"></a><a class="link" href="#og-module-deploy">Module <code>deploy</code></a></h4>
<div class="paragraph">
<p>The <code>deploy</code> module provides the deployment feature through a <code>DeploymentManager</code> component that watches a directory for changes (see <a href="#og-deploy">how to deploy web applications</a> for more information).</p>
</div>
<div class="paragraph">
<p>Files or directories added in this monitored directory cause the <code>DeploymentManager</code> to deploy them as web applications; updating files already existing in this monitored directory cause the <code>DeploymentManager</code> to re-deploy the correspondent web application; removing files in this monitored directory cause the <code>DeploymentManager</code> to undeploy the correspondent web application (see also <a href="#og-deploy-rules">here</a> for more information).</p>
</div>
<div class="paragraph">
<p>The module file is <code>$JETTY_HOME/modules/deploy.mod</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>Unresolved directive in modules/module-deploy.adoc - include::../../../../../../jetty-home/target/jetty-home/modules/deploy.mod[]</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>jetty.deploy.monitoredDir</code>, to change the name of the monitored directory.</p>
</li>
<li>
<p><code>jetty.deploy.scanInterval</code>, to change the scan period, that is how frequently the <code>DeploymentManager</code> wakes up to scan the monitored directory for changes.
Setting <code>jetty.deploy.scanInterval=0</code> disabled <em>hot</em> deployment so that only static deployment will be possible (see also <a href="#og-deploy-hot-static">here</a> for more information).</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="og-module-http"><a class="anchor" href="#og-module-http"></a><a class="link" href="#og-module-http">Module <code>http</code></a></h4>
<div class="paragraph">
<p>The <code>http</code> module provides support for the clear-text HTTP/1.1 protocol and depends on the <a href="#og-module-server"><code>server</code> module</a>.</p>
</div>
<div class="paragraph">
<p>The module file is <code>$JETTY_HOME/modules/http.mod</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>Unresolved directive in modules/module-http.adoc - include::../../../../../../jetty-home/target/jetty-home/modules/http.mod[]</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>jetty.http.port</code>, default <code>8080</code>, is the network port that Jetty listens to for clear-text HTTP/1.1 connections.</p>
</li>
<li>
<p><code>jetty.http.idleTimeout</code>, default <code>30</code> seconds, is the amount of time a connection can be idle (i.e. no bytes received and no bytes sent) until the server decides to close it to save resources.</p>
</li>
<li>
<p><code>jetty.http.acceptors</code>, default -1 (i.e. an accept heuristic decides the value based on the number of cores), is the number of threads that compete to accept connections.</p>
</li>
<li>
<p><code>jetty.http.selectors</code>, default -1 (i.e. a select heuristic decides the value based on the number of cores), is the number of NIO selectors (with an associated thread) that manage connections.</p>
</li>
</ul>
</div>
<div class="sect4">
<h5 id="og-module-http-acceptors"><a class="anchor" href="#og-module-http-acceptors"></a><a class="link" href="#og-module-http-acceptors">Configuration of Acceptors</a></h5>
<div class="paragraph">
<p>Accepting connections is a blocking operation, so a thread is blocked in the <code>accept()</code> call until a connection is accepted, and other threads are blocked on the lock acquired just before the <code>accept()</code> call.</p>
</div>
<div class="paragraph">
<p>When the accepting thread accepts a connection, it performs a little processing of the just accepted connection, before forwarding it to other components.</p>
</div>
<div class="paragraph">
<p>During this little processing other connections may be established; if there is only one accepting thread, the newly established connections are waiting for the accepting thread to finish the processing of the previously accepted connection and call again <code>accept()</code>.</p>
</div>
<div class="paragraph">
<p>Servers that manage a very high number of connections that may (naturally) come and go, or that handle inefficient protocols that open and close connections very frequently (such as HTTP/1.0) may benefit of an increased number of acceptor threads.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-module-http-selectors"><a class="anchor" href="#og-module-http-selectors"></a><a class="link" href="#og-module-http-selectors">Configuration of Selectors</a></h5>
<div class="paragraph">
<p>Performing a NIO <code>select()</code> call is a blocking operation, where the selecting thread is blocked in the <code>select()</code> call until at least one connection is ready to be processed for an I/O operation.
There are 4 I/O operations: ready to be accepted, ready to be connected, ready to be read and ready to be written.</p>
</div>
<div class="paragraph">
<p>A single NIO selector can manage thousands of connections, with the assumption that not many of them will be ready at the same time.</p>
</div>
<div class="paragraph">
<p>For a single NIO selector, the ratio between the average number of selected connections over the total number of connections for every <code>select()</code> call depends heavily on the protocol but also on the application.</p>
</div>
<div class="paragraph">
<p>Multiplexed protocols such as HTTP/2 tend to be busier than duplex protocols such as HTTP/1.1, leading to a higher ratio.</p>
</div>
<div class="paragraph">
<p>REST applications that exchange many little JSON messages tend to be busier than file server applications, leading to a higher ratio.</p>
</div>
<div class="paragraph">
<p>The higher the ratio, the higher the number of selectors you want to have, compatibly with the number of cores&#8201;&#8212;&#8201;there is no point in having 64 selector threads on a single core hardware.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-module-server"><a class="anchor" href="#og-module-server"></a><a class="link" href="#og-module-server">Module <code>server</code></a></h4>
<div class="paragraph">
<p>The <code>server</code> module provides generic server support, and configures generic HTTP properties that apply to all HTTP protocols, the scheduler properties and the server specific properties.</p>
</div>
<div class="paragraph">
<p>The <code>server</code> module depends on the <a href="#og-module-threadpool"><code>threadpool</code> module</a>, the <a href="#og-module-bytebufferpool"><code>bytebufferpool</code> module</a> and the <a href="#og-module-logging"><code>logging</code> module</a>.</p>
</div>
<div class="paragraph">
<p>The module file is <code>$JETTY_HOME/modules/server.mod</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>Unresolved directive in modules/module-server.adoc - include::../../../../../../jetty-home/target/jetty-home/modules/server.mod[]</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="paragraph">
<p>TODO</p>
</div>
</div>
<div class="sect3">
<h4 id="og-module-threadpool"><a class="anchor" href="#og-module-threadpool"></a><a class="link" href="#og-module-threadpool">Module <code>threadpool</code></a></h4>
<div class="paragraph">
<p>The <code>threadpool</code> module allows you to configure the server-wide thread pool.</p>
</div>
<div class="paragraph">
<p>The module file is <code>$JETTY_HOME/modules/threadpool.mod</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>Unresolved directive in modules/module-threadpool.adoc - include::../../../../../../jetty-home/target/jetty-home/modules/threadpool.mod[]</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="paragraph">
<p>TODO</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-sessions"><a class="anchor" href="#og-sessions"></a><a class="link" href="#og-sessions">HTTP Session Management</a></h3>
<div class="paragraph">
<p>HTTP sessions are a concept within the Servlet API which allow requests to store and retrieve information across the time a user spends in an application.
Jetty offers a number of pluggable alternatives for managing and distributing/persisting sessions.
Choosing the best alternative is an important consideration for every application as is the correct configuration to achieve optimum performance.</p>
</div>
<div class="sect3">
<h4 id="og-session-overview"><a class="anchor" href="#og-session-overview"></a><a class="link" href="#og-session-overview">HTTP Session Overview</a></h4>
<div class="sect4">
<h5 id="og-terminology"><a class="anchor" href="#og-terminology"></a><a class="link" href="#og-terminology">Terminology</a></h5>
<div class="paragraph">
<p>Before diving into the specifics of how to plug-in and configure various alternative HTTP session management modules, let&#8217;s review some useful terminology:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Session</dt>
<dd>
<p>is a means of retaining information across requests for a particular user.
The Servlet Specification defines the semantics of sessions.
Some of the most important characteristics of sessions is that they have a unique id and that their contents cannot be shared between different contexts (although the id can be): if a session is invalidated in one context, then all other sessions that share the same id in other contexts will also be invalidated.
Sessions can expire or they can be explicitly invalidated.</p>
</dd>
<dt class="hdlist1">SessionIdManager</dt>
<dd>
<p>is responsible for allocating session ids.
A Jetty server can have at most 1 SessionIdManager.</p>
</dd>
<dt class="hdlist1">HouseKeeper</dt>
<dd>
<p>is responsible for periodically orchestrating the removal of expired sessions.
This process is referred to as <a href="#og-session-base-scavenge">"scavenging"</a>.</p>
</dd>
<dt class="hdlist1">SessionHandler</dt>
<dd>
<p>is responsible for managing the lifecycle of sessions.
A context can have at most 1 <code>SessionHandler</code>.</p>
</dd>
<dt class="hdlist1">SessionCache</dt>
<dd>
<p>is a L1 cache of in-use session objects.
The <code>SessionCache</code> is used by the <code>SessionHandler</code>.</p>
</dd>
<dt class="hdlist1">SessionDataStore</dt>
<dd>
<p>is responsible for all clustering/persistence operations on sessions.
A <code>SessionCache</code> uses a <code>SessionDataStore</code> as a backing store.</p>
</dd>
<dt class="hdlist1">CachingSessionDataStore</dt>
<dd>
<p>is an L2 cache of session data.
A <code>SessionCache</code> can use a <code>CachingSessionDataStore</code> as its backing store.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>More details on these concepts can be found in the <a href="../programming-guide/index.html/server/sessions/sessions">Programming Guide</a>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p><code>SessionDataStore</code>s implementations interact with other, usually third party, systems responsible for storing and/or distributing session information.
Sessions can be distributed without being persisted.
They can also be persisted without being distributed.
Because persisting session information to a shared store is a very common way of distributing (also known as "clustering") sessions, in the documentation we will often refer to just "persisting".</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="og-session-modules"><a class="anchor" href="#og-session-modules"></a><a class="link" href="#og-session-modules">Session Modules</a></h5>
<div class="paragraph">
<p>There are a number of modules that offer pluggable alternatives for http session management.
You can design how you want to cache and store http sessions by selecting alternative combinations of session modules.</p>
</div>
<div class="paragraph">
<p>For example, Jetty ships with two alternative implementations of the <code>SessionCache</code>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>one that caches sessions in memory: <a href="#og-session-cache-hash"><code>session-cache-hash</code></a></p>
</li>
<li>
<p>one that does not actually cache: <a href="#og-session-cache-null"><code>session-cache-null</code></a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>There are at least 6 alternative implementations of the <code>SessionDataStore</code> that you can use to persist/distribute your http sessions:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>file system storage: <a href="#og-session-filesystem"><code>session-store-file</code></a></p>
</li>
<li>
<p>relational database storage: <a href="#og-session-jdbc"><code>session-store-jdbc</code></a></p>
</li>
<li>
<p>NoSQL database storage: <a href="#og-session-mongo"><code>session-store-mongo</code></a></p>
</li>
<li>
<p>Google Cloud datastore storage: <a href="#og-session-gcloud"><code>session-store-gcloud</code></a></p>
</li>
<li>
<p>Hazelcast: <a href="#og-session-hazelcast-remote"><code>session-store-hazelcast-remote</code></a> or <a href="#og-session-hazelcast-embedded"><code>session-store-hazelcast-embedded</code></a></p>
</li>
<li>
<p>Infinispan: <a href="#og-session-infinispan"><code>session-store-infinispan-remote</code></a> or <a href="#og-session-infinispan-embedded"><code>session-store-infinispan-embedded</code></a></p>
</li>
</ul>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
It is worth noting that if you do not configure <em>any</em> session modules, Jetty will still provide HTTP sessions that are cached in memory but are never persisted.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-session-base"><a class="anchor" href="#og-session-base"></a><a class="link" href="#og-session-base">The Base Session Module</a></h4>
<div class="paragraph">
<p>The <code>sessions</code> module is the base module that all other session modules depend upon.
As such it will be <em>transitively</em> enabled if you enable any of the other session modules: you need to <em>explicitly</em> enable it if you wish to <em>change</em> any settings from their defaults.</p>
</div>
<div class="paragraph">
<p>Enabling the <code>sessions</code> module puts the <code>$JETTY_HOME/etc/sessions/id-manager.xml</code> file onto the execution path and generates a <code>$JETTY_BASE/start.d/sessions.ini</code> file.</p>
</div>
<div class="paragraph">
<p>The <code>id-manager.xml</code> file instantiates a <code>DefaultSessionIdManager</code> and <code>HouseKeeper</code>.
The former is used to generate and manage session ids whilst the latter is responsible for periodic <a href="#og-session-base-scavenge">scavenging</a> of expired sessions.</p>
</div>
<div class="sect4">
<h5 id="og-configuration"><a class="anchor" href="#og-configuration"></a><a class="link" href="#og-configuration">Configuration</a></h5>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/sessions.ini</code> file contains these configuration properties:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.sessionIdManager.workerName</dt>
<dd>
<p>This uniquely identifies the jetty server instance and is applied to the <code>SessionIdManager</code>.
You can either provide a value for this property, or you can allow Jetty to try and synthesize a <code>workerName</code> - the latter option is <em>only</em> advisable in the case of a single, non-clustered deployment.
There are two ways a default <code>workerName</code> can be synthesized:</p>
<div class="ulist">
<ul>
<li>
<p>if running on Google AppEngine, the <code>workerName</code> will be formed by concatenating the values of the environment variables <code>JETTY_WORKER_INSTANCE</code> and <code>GAE_MODULE_INSTANCE</code></p>
</li>
<li>
<p>otherwise, the <code>workerName</code> will be formed by concatenating the environment variable <code>JETTY_WORKER_INSTANCE</code> and the literal <code>0</code>.</p>
</li>
</ul>
</div>
</dd>
</dl>
</div>
<div class="paragraph">
<p>So, if you&#8217;re not running on Google AppEngine, and you haven&#8217;t configured one, the workerName will always be: <code>node0</code>.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
If you have more than one Jetty instance, it is <strong>crucial</strong> that you configure the <code>workerName</code> differently for each instance.
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.sessionScavengeInterval.seconds</dt>
<dd>
<p>This is the period in <em>seconds</em> between runs of the <code>HouseKeeper</code>, responsible for orchestrating the removal of expired sessions.
By default it will run approximately every 600 secs (ie 10 mins).
As a rule of thumb, you should ensure that the <a href="#og-session-base-scavenge">scavenge</a> interval is shorter than the <code>&lt;session-timeout&gt;</code> of your sessions to ensure that they are promptly scavenged.
On the other hand, if you have a backend store configured for your sessions, <a href="#og-session-base-scavenge">scavenging</a> too frequently can increase the load on it.</p>
</dd>
</dl>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
Don&#8217;t forget that the <code>&lt;session-timeout&gt;</code> is specified in <code>web.xml</code> in <em>minutes</em> and the value of the <code>jetty.sessionScavengeInterval.seconds</code> is in <em>seconds</em>.
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="og-session-base-scavenge"><a class="anchor" href="#og-session-base-scavenge"></a><a class="link" href="#og-session-base-scavenge">Session Scavenging</a></h5>
<div class="paragraph">
<p>The <code>HouseKeeper</code> is responsible for the periodic initiation of session scavenge cycles.
The <code>jetty.sessionScavengeInterval.seconds</code> property in <code>$JETTY_BASE/start.d/sessions.ini</code> controls the periodicity of the cycle.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The HouseKeeper semi-randomly adds an additional 10% to the configured <code>sessionScavengeInterval</code>.
This is to prevent multiple nodes in a cluster that are all started at once from syncing up scavenge cycles and placing extra load on the configured persistence mechanism.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>A session whose expiry time has been exceeded is considered eligible for scavenging.
The session might be present in a <code>SessionCache</code> and/or present in the session persistence/clustering mechanism.</p>
</div>
<div class="paragraph">
<p>Scavenging occurs for all contexts on a server at every cycle.
The <code>HouseKeeper</code> sequentially asks the <code>SessionHandler</code> in each context to find and remove expired sessions.
The <code>SessionHandler</code> works with the <code>SessionDataStore</code> to evaluate candidates for expiry held in the <code>SessionCache</code>, and also to sweep the persistence mechanism to find expired sessions.</p>
</div>
<div class="paragraph">
<p>The sweep takes two forms: once per cycle the <code>SessionDataStore</code> searches for sessions for its own context that have expired; infrequently, the <code>SessionDataStore</code> will widen the search to expired sessions in all contexts.
The former finds sessions that are no longer in this context&#8217;s <code>SessionCache</code>, and using some heuristics, are unlikely to be in the <code>SessionCache</code> of the same context on another node either.
These sessions will be loaded and fully expired, meaning that <code>HttpSessionListener.destroy()</code> will be called for them.
The latter finds sessions that have not been disposed of by scavenge cycles on any other context/node.
As these will be sessions that expired a long time ago, and may not be appropriate to load by the context doing the scavenging, these are summarily deleted without <code>HttpSessionListener.destroy()</code> being called.</p>
</div>
<div class="paragraph">
<p>A combination of these sweeps should ensure that the persistence mechanism does not fill over time with expired sessions.</p>
</div>
<div class="paragraph">
<p>As aforementioned, the sweep period needs to be short enough to find expired sessions in a timely fashion, but not so often that it overloads the persistence mechanism.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-session-cache"><a class="anchor" href="#og-session-cache"></a><a class="link" href="#og-session-cache">Modules for HTTP Session Caching</a></h4>
<div class="paragraph">
<p>In this section we will look at the alternatives for the <code>SessionCache</code>, i.e. the L1 cache of in-use session objects.
Jetty ships with 2 alternatives: an in-memory cache, and a null cache.
The latter does not actually do any caching of sessions, and can be useful if you either want to minimize your support for sessions, or you are in a clustered deployment without a sticky loadbalancer.</p>
</div>
<div class="paragraph">
<p>The <a href="#og-session-usecases">scenarios</a> go into more detail on this.</p>
</div>
<div class="sect4">
<h5 id="og-session-cache-hash"><a class="anchor" href="#og-session-cache-hash"></a><a class="link" href="#og-session-cache-hash">Caching in Memory</a></h5>
<div class="paragraph">
<p>If you wish to change any of the default configuration values you should enable the <code>session-cache-hash</code> <a href="#startup-modules">module</a>.
The name <code>"hash"</code> harks back to historical Jetty session implementations, whereby sessions were kept in memory using a HashMap.</p>
</div>
<div class="sect5">
<h6 id="og-configuration-2"><a class="anchor" href="#og-configuration-2"></a><a class="link" href="#og-configuration-2">Configuration</a></h6>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/session-cache-hash.ini</code> contains the following configurable properties:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.evictionPolicy</dt>
<dd>
<p>Integer, default -1.
This controls whether session objects that are held in memory are subject to eviction from the cache.
Eviction means that the session is removed from the cache.
This can reduce the memory footprint of the cache and can be useful if you have a lot of sessions.
Eviction is usually used in conjunction with a <code>SessionDataStore</code> that persists sessions.
The eviction strategies and their corresponding values are:</p>
<div class="dlist">
<dl>
<dt class="hdlist1">-1 (NO EVICTION)</dt>
<dd>
<p>sessions are never evicted from the cache.
The only way they leave are via expiration or invalidation.</p>
</dd>
<dt class="hdlist1">0 (EVICT AFTER USE)</dt>
<dd>
<p>sessions are evicted from the cache as soon as the last active request for it finishes.
The session will be passed to the <code>SessionDataStore</code> to be written out before eviction.</p>
</dd>
<dt class="hdlist1">&gt;= 1 (EVICT ON INACTIVITY)</dt>
<dd>
<p>any positive number is the time in seconds after which a session that is in the cache but has not experienced any activity will be evicted.
Use the <code>jetty.session.saveOnInactiveEvict</code> property to force a session write before eviction.</p>
</dd>
</dl>
</div>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
If you are not using one of the session store modules, ie one of the <code>session-store-xxxx</code>s, then sessions will be lost when the context is stopped, or the session is evicted.
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.saveOnInactiveEvict</dt>
<dd>
<p>Boolean, default <code>false</code>.
This controls whether a session will be persisted to the <code>SessionDataStore</code> if it is being evicted due to the EVICT ON INACTIVITY policy.
Usually sessions will be written to the <code>SessionDataStore</code> whenever the last simultaneous request exits the session.
However, as <code>SessionDataStores</code> can be configured to skip some writes (see the documentation for the <code>session-store-xxx</code> module that you are using), this option is provided to ensure that the session will be written out.</p>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Be careful with this option, as in clustered scenarios it would be possible to "re-animate" a session that has actually been deleted by another node.
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.saveOnCreate</dt>
<dd>
<p>Boolean, default <code>false</code>.
Controls whether a session that is newly created will be immediately saved to the <code>SessionDataStore</code> or lazily saved as the last request for the session exits.
This can be useful if the request dispatches to another context and needs to re-use the same session id.</p>
</dd>
<dt class="hdlist1">jetty.session.removeUnloadableSessions</dt>
<dd>
<p>Boolean, default <code>false</code>.
Controls whether the session cache should ask a <code>SessionDataStore</code> to delete a session that cannot be restored - for example because it is corrupted.</p>
</dd>
<dt class="hdlist1">jetty.session.flushOnResponseCommit</dt>
<dd>
<p>Boolean, default <code>false</code>.
If true, if a session is "dirty" - ie its attributes have changed - it will be written to the <code>SessionDataStore</code> as the response is about to commit.
This ensures that all subsequent requests whether to the same or different node will see the updated session data.
If false, a dirty session will only be written to the backing store when the last simultaneous request for it leaves the session.</p>
</dd>
<dt class="hdlist1">jetty.session.invalidateOnShutdown</dt>
<dd>
<p>Boolean, default <code>false</code>.
If true, when a context is shutdown, all sessions in the cache are invalidated and deleted both from the cache and from the <code>SessionDataStore</code>.</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-session-cache-null"><a class="anchor" href="#og-session-cache-null"></a><a class="link" href="#og-session-cache-null">No Caching</a></h5>
<div class="paragraph">
<p>You may need to use the <code>session-cache-null</code> module if your clustering setup does not have a sticky load balancer, or if you want absolutely minimal support for sessions.
If you enable this module, but you don&#8217;t enable a module that provides session persistence (ie one of the <code>session-store-xxx</code> modules), then sessions will <em>neither</em> be retained in memory <em>nor</em> persisted.</p>
</div>
<div class="sect5">
<h6 id="og-configuration-3"><a class="anchor" href="#og-configuration-3"></a><a class="link" href="#og-configuration-3">Configuration</a></h6>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/session-cache-null.ini</code> contains the following configurable properties:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.saveOnCreate</dt>
<dd>
<p>Boolean, default <code>false</code>.
Controls whether a session that is newly created will be immediately saved to the <code>SessionDataStore</code> or lazily saved as the last request for the session exits.
This can be useful if the request dispatches to another context and needs to re-use the same session id.</p>
</dd>
<dt class="hdlist1">jetty.session.removeUnloadableSessions</dt>
<dd>
<p>Boolean, default <code>false</code>.
Controls whether the session cache should ask a <code>SessionDataStore</code> to delete a session that cannot be restored - for example because it is corrupted.</p>
</dd>
<dt class="hdlist1">jetty.session.flushOnResponseCommit</dt>
<dd>
<p>Boolean, default <code>false</code>.
If true, if a session is "dirty" - ie its attributes have changed - it will be written to the backing store as the response is about to commit.
This ensures that all subsequent requests whether to the same or different node will see the updated session data.
If false, a dirty session will only be written to the backing store when the last simultaneous request for it leaves the session.</p>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-session-filesystem"><a class="anchor" href="#og-session-filesystem"></a><a class="link" href="#og-session-filesystem">Modules for Persistent HTTP Sessions: File System</a></h4>
<div class="paragraph">
<p>The <code>session-store-file</code> Jetty module supports persistent storage of session data in a filesystem.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
Persisting sessions to the local file system should <strong>never</strong> be used in a clustered environment.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Enabling this module creates the <code>$JETTY_BASE/sessions</code> directory.
By default session data will be saved to this directory, one file representing each session.</p>
</div>
<div class="paragraph">
<p>File names follow this pattern:</p>
</div>
<div class="paragraph">
<p><code>[expiry]_[contextpath]_[virtualhost]_[id]</code></p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">expiry</dt>
<dd>
<p>This is the expiry time in milliseconds since the epoch.</p>
</dd>
<dt class="hdlist1">contextpath</dt>
<dd>
<p>This is the context path with any special characters, including <code>/</code>, replaced by the <code><em></code> underscore character.
For example, a context path of <code>/catalog</code> would become <code>_catalog</code>.
A context path of simply <code>/</code> becomes just <code>_</em></code>.</p>
</dd>
<dt class="hdlist1">virtualhost</dt>
<dd>
<p>This is the first virtual host associated with the context and has the form of 4 digits separated by <code>.</code> characters: <code>[digit].[digit].[digit].[digit]</code>.
If there are no virtual hosts associated with a context, then <code>0.0.0.0</code> is used.</p>
</dd>
<dt class="hdlist1">id</dt>
<dd>
<p>This is the unique id of the session.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>Putting all of the above together as an example, a session with an id of <code>node0ek3vx7x2y1e7pmi3z00uqj1k0</code> for the context with path <code>/test</code> with no virtual hosts and an expiry of <code>1599558193150</code> would have a file name of:</p>
</div>
<div class="paragraph">
<p><code>1599558193150__test_0.0.0.0_node0ek3vx7x2y1e7pmi3z00uqj1k0</code></p>
</div>
<div class="sect4">
<h5 id="og-configuration-4"><a class="anchor" href="#og-configuration-4"></a><a class="link" href="#og-configuration-4">Configuration</a></h5>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/sessions.ini</code> file contains the following properties which may be modified to customise filesystem session storage:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.storeDir</dt>
<dd>
<p>The default is <code>$JETTY_BASE/sessions</code>.
This is a path that defines the location for storage of session files.</p>
</dd>
<dt class="hdlist1">jetty.session.file.deleteUnrestorableFiles</dt>
<dd>
<p>Boolean, default <code>false</code>.
If set to <code>true</code>, unreadable files will be deleted.
This is useful to prevent repeated logging of the same error when the scavenger periodically (re-)attempts to load the corrupted information for a session in order to expire it.</p>
</dd>
<dt class="hdlist1">jetty.session.gracePeriod.seconds</dt>
<dd>
<p>Integer, default 3600.
Used during session <a href="#og-session-base-scavenge">scavenging</a>.
Multiples of this period are used to define how long ago a stored session must have expired before it should be <a href="#og-session-base-scavenge">scavenged</a>.</p>
</dd>
<dt class="hdlist1">jetty.session.savePeriod.seconds</dt>
<dd>
<p>Integer, in seconds, default is <code>0</code>.
Whenever a session is accessed by a request, its <code>lastAccessTime</code> and <code>expiry</code> are updated.
Even if your sessions are read-mostly, the <code>lastAccessTime</code> and <code>expiry</code> will always change.
For heavily-used, read-mostly sessions you can save some time by skipping some writes for sessions for which only these fields have changed (ie no session attributes changed).
The value of this property is used to skip writes for these kinds of sessions: the session will only be written out if the time since the last write exceeds the value of this property.</p>
</dd>
</dl>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You should be careful in the use of this property in clustered environments: if you set too large a value for this property, the session may not be written out sufficiently often to update its <code>expiry</code> time thus making it appear to other nodes that it has expired.
Thorough consideration of the <code>maxIdleTime</code> of the session when setting the <code>savePeriod</code> is imperative - it would be undesirable to set a <code>savePeriod</code> that is larger than the <code>maxIdleTime</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-session-jdbc"><a class="anchor" href="#og-session-jdbc"></a><a class="link" href="#og-session-jdbc">Modules for Persistent HTTP Sessions: JDBC</a></h4>
<div class="paragraph">
<p>Enabling the <code>session-store-jdbc</code> module configures Jetty to persist session data in a relational database.</p>
</div>
<div class="sect4">
<h5 id="og-configuration-5"><a class="anchor" href="#og-configuration-5"></a><a class="link" href="#og-configuration-5">Configuration</a></h5>
<div class="paragraph">
<p>After enabling the module, the <code>$JETTY_BASE/start.d/session-store-jdbc.ini</code> file contains the following customizable properties:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.gracePeriod.seconds</dt>
<dd>
<p>Integer, default 3600.
Used during session <a href="#og-session-base-scavenge">scavenging</a>.
Multiples of this period are used to define how long ago a stored session must have expired before it should be <a href="#og-session-base-scavenge">scavenged</a>.</p>
</dd>
<dt class="hdlist1">jetty.session.savePeriod.seconds</dt>
<dd>
<p>Integer, in seconds, default is <code>0</code>.
Whenever a session is accessed by a request, its <code>lastAccessTime</code> and <code>expiry</code> are updated.
Even if your sessions are read-mostly, the <code>lastAccessTime</code> and <code>expiry</code> will always change.
For heavily-used, read-mostly sessions you can save some time by skipping some writes for sessions for which only these fields have changed (ie no session attributes changed).
The value of this property is used to skip writes for these kinds of sessions: the session will only be written out if the time since the last write exceeds the value of this property.</p>
</dd>
</dl>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You should be careful in the use of this property in clustered environments: if you set too large a value for this property, the session may not be written out sufficiently often to update its <code>expiry</code> time thus making it appear to other nodes that it has expired.
Thorough consideration of the <code>maxIdleTime</code> of the session when setting the <code>savePeriod</code> is imperative - it would be undesirable to set a <code>savePeriod</code> that is larger than the <code>maxIdleTime</code>.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">db-connection-type</dt>
<dd>
<p>Default <code>datasource</code>.
Set to either <code>datasource</code> or <code>driver</code> depending on the type of connection being used.
Depending which you select, there are additional properties available:</p>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>datasource</code></dt>
<dd>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.jdbc.datasourceName</dt>
<dd>
<p>Name of the remote datasource.</p>
</dd>
</dl>
</div>
</dd>
<dt class="hdlist1"><code>driver</code></dt>
<dd>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.jdbc.driverClass</dt>
<dd>
<p>Name of the JDBC driver that controls access to the remote database, such as <code>com.mysql.jdbc.Driver</code></p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.driverUrl</dt>
<dd>
<p>URL of the database which includes the driver type, host name and port, service name and any specific attributes unique to the database, such as a username.
As an example, here is a mysql connection with the username appended: <code>jdbc:mysql://127.0.0.1:3306/sessions?user=sessionsadmin</code>.</p>
</dd>
</dl>
</div>
</dd>
</dl>
</div>
</dd>
<dt class="hdlist1">jetty.session.jdbc.blobType</dt>
<dd>
<p>Optional.
Default <code>blob</code> or <code>bytea</code> for Postgres.
This is the keyword used by the particular database to identify the blob data type.
If netiher default is suitable you can set this value explicitly.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.longType</dt>
<dd>
<p>Optional.
Default <code>bigint</code> or <code>number(20)</code> for Oracle.
This is the keyword used by the particular database to identify the long integer data type.
Set this explicitly if neither of the default values is appropriate.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.stringType</dt>
<dd>
<p>Optional.
Default <code>varchar</code>.
This is the keyword used by the particular database to identify character type.
If the default is not suitable, you can set this value explicitly.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.schemaName</dt>
<dt class="hdlist1">jetty.session.jdbc.schema.catalogName</dt>
<dd>
<p>Optional.
The exact meaning of these two properties is dependent on your database vendor, but can broadly be described as further scoping for the session table name.
See <a href="https://en.wikipedia.org/wiki/Database_schema" class="bare">https://en.wikipedia.org/wiki/Database_schema</a> and <a href="https://en.wikipedia.org/wiki/Database_catalog" class="bare">https://en.wikipedia.org/wiki/Database_catalog</a>.
These extra scoping names can come into play at startup time when Jetty determines if the session table already exists, or otherwise creates it on-the-fly.
If you have employed either of these concepts when you pre-created the session table, or you want to ensure that Jetty uses them when it auto-creates the session table, then you have two options: either set them explicitly, or let Jetty infer them from a database connection (obtained using either a Datasource or Driver according to the <code>db-connection-type</code> you have configured).
To set them explicitly, uncomment and supply appropriate values for the <code>jetty.session.jdbc.schema.schemaName</code> and/or <code>jetty.session.jdbc.schema.catalogName</code> properties.
Alternatively, to allow Jetty to infer them from a database connection, use the special string <code>INFERRED</code> instead.
If you leave them blank or commented out, then the sessions table will not be scoped by schema or catalog name.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.table</dt>
<dd>
<p>Default <code>JettySessions</code>.
This is the name of the table in which session data is stored.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.accessTimeColumn</dt>
<dd>
<p>Default <code>accessTime</code>.
This is the name of the column that stores the time - in ms since the epoch - at which a session was last accessed</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.contextPathColumn</dt>
<dd>
<p>Default <code>contextPath</code>.
This is the name of the column that stores the <code>contextPath</code> of a session.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.cookieTimeColumn</dt>
<dd>
<p>Default <code>cookieTime</code>.
This is the name of the column that stores the time - in ms since the epoch - that the cookie was last set for a session.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.createTimeColumn</dt>
<dd>
<p>Default <code>createTime</code>.
This is the name of the column that stores the time - in ms since the epoch - at which a session was created.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.expiryTimeColumn</dt>
<dd>
<p>Default <code>expiryTime</code>.
This is name of the column that stores - in ms since the epoch - the time at which a session will expire.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.lastAccessTimeColumn</dt>
<dd>
<p>Default <code>lastAccessTime</code>.
This is the name of the column that stores the time - in ms since the epoch - that a session was previously accessed.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.lastSavedTimeColumn</dt>
<dd>
<p>Default <code>lastSavedTime</code>.
This is the name of the column that stores the time - in ms since the epoch - at which a session was last written.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.idColumn</dt>
<dd>
<p>Default <code>sessionId</code>.
This is the name of the column that stores the id of a session.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.lastNodeColumn</dt>
<dd>
<p>Default <code>lastNode</code>.
This is the name of the column that stores the <code>workerName</code> of the last node to write a session.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.virtualHostColumn</dt>
<dd>
<p>Default <code>virtualHost</code>.
This is the name of the column that stores the first virtual host of the context of a session.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.maxIntervalColumn</dt>
<dd>
<p>Default <code>maxInterval</code>.
This is the name of the column that stores the interval - in ms - during which a session can be idle before being considered expired.</p>
</dd>
<dt class="hdlist1">jetty.session.jdbc.schema.mapColumn</dt>
<dd>
<p>Default <code>map</code>.
This is the name of the column that stores the serialized attributes of a session.</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-session-mongo"><a class="anchor" href="#og-session-mongo"></a><a class="link" href="#og-session-mongo">Modules for Persistent HTTP Sessions: MongoDB</a></h4>
<div class="paragraph">
<p>Enabling the <code>session-store-mongo</code> module configures Jetty to store session data in MongoDB.</p>
</div>
<div class="paragraph">
<p>Because MongoDB is not a technology provided by the Eclipse Foundation, you will be prompted to assent to the licenses of the external vendor (Apache in this case) during the install.
Jars needed by MongoDB are downloaded and stored into a directory named <code>$JETTY_BASE/lib/nosql/</code>.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
If you want to use updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated <code>$JETTY_BASE/lib/</code> directory and use the <code>--skip-file-validation=&lt;module name&gt;</code> command line option to prevent errors when starting your server.
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="og-configuration-6"><a class="anchor" href="#og-configuration-6"></a><a class="link" href="#og-configuration-6">Configuration</a></h5>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/session-store-mongo.ini</code> file contains these configurable properties:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.mongo.dbName</dt>
<dd>
<p>Default is "HttpSessions".
This is the name of the database in MongoDB used to store the session collection.</p>
</dd>
<dt class="hdlist1">jetty.session.mongo.collectionName</dt>
<dd>
<p>Default is "jettySessions".
This is the name of the collection in MongoDB used to store all of the sessions.</p>
</dd>
<dt class="hdlist1">The connection type-</dt>
<dd>
<p>You can connect to MongoDB either using a host/port combination, or a URI.
By default, the host/port method is selected, but you can change this by commenting out the unwanted method, and uncommenting the other one.</p>
<div class="dlist">
<dl>
<dt class="hdlist1">connection-type=address</dt>
<dd>
<p>Used when utilizing a direct connection to the MongoDB server.</p>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.mongo.host</dt>
<dd>
<p>Host name or address for the remote MongoDB instance.</p>
</dd>
<dt class="hdlist1">jetty.session.mongo.port</dt>
<dd>
<p>Port number for the remote MongoDB instance.</p>
</dd>
</dl>
</div>
</dd>
<dt class="hdlist1">connection-type=uri</dt>
<dd>
<p>Used when utilizing MongoURI for secured connections.</p>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.mongo.connectionString</dt>
<dd>
<p>The string defining the MongoURI value, such as <code>mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]</code>.
More information on how to format the MongoURI string can be found in the <a href="https://docs.mongodb.com/manual/reference/connection-string/">official documentation for mongo</a>.</p>
</dd>
</dl>
</div>
</dd>
</dl>
</div>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You will only use <strong>one</strong> <code>connection-type</code> at a time, either <code>address</code> or <code>uri</code>.
If both are utilized in your <code>session-store-mongo.ini</code>, only the <em>last</em> <code>connection-type</code> configured in the file will be used.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.gracePeriod.seconds</dt>
<dd>
<p>Integer, in seconds.
Default 3600.
Used during session <a href="#og-session-base-scavenge">scavenging</a>.
Multiples of this period are used to define how long ago a stored session must have expired before it should be <a href="#og-session-base-scavenge">scavenged</a>.</p>
</dd>
<dt class="hdlist1">jetty.session.savePeriod.seconds</dt>
<dd>
<p>Integer, in seconds, default is <code>0</code>.
Whenever a session is accessed by a request, its <code>lastAccessTime</code> and <code>expiry</code> are updated.
Even if your sessions are read-mostly, the <code>lastAccessTime</code> and <code>expiry</code> will always change.
For heavily-used, read-mostly sessions you can save some time by skipping some writes for sessions for which only these fields have changed (ie no session attributes changed).
The value of this property is used to skip writes for these kinds of sessions: the session will only be written out if the time since the last write exceeds the value of this property.</p>
</dd>
</dl>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You should be careful in the use of this property in clustered environments: if you set too large a value for this property, the session may not be written out sufficiently often to update its <code>expiry</code> time thus making it appear to other nodes that it has expired.
Thorough consideration of the <code>maxIdleTime</code> of the session when setting the <code>savePeriod</code> is imperative - it would be undesirable to set a <code>savePeriod</code> that is larger than the <code>maxIdleTime</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-session-infinispan"><a class="anchor" href="#og-session-infinispan"></a><a class="link" href="#og-session-infinispan">Modules for Persistent HTTP Sessions: Infinispan</a></h4>
<div class="paragraph">
<p>In order to persist/cluster sessions using Infinispan, Jetty needs to know how to contact Infinispan.
There are two options: a remote Infinispan instance, or an in-process Infinispan instance.
The former is referred to as "remote" Infinispan and the latter as "embedded" Infinispan.
If you wish Jetty to be able to <a href="#og-session-base-scavenge">scavenge</a> expired sessions, you will also need to enable the appropriate <code>infinispan-[remote|embedded]-query</code> module.</p>
</div>
<div class="sect4">
<h5 id="og-session-infinispan-remote"><a class="anchor" href="#og-session-infinispan-remote"></a><a class="link" href="#og-session-infinispan-remote">Remote Infinispan Session Module</a></h5>
<div class="paragraph">
<p>The <code>session-store-infinispan-remote</code> module configures Jetty to talk to an external Infinispan instance to store session data.</p>
</div>
<div class="paragraph">
<p>Because Infinispan is not a technology provided by the Eclipse Foundation, you will be prompted to assent to the licenses of the external vendor (Apache in this case).</p>
</div>
<div class="paragraph">
<p>Infinispan-specific jar files are download to the directory named <code>$JETTY_BASE/lib/infinispan/</code>.</p>
</div>
<div class="paragraph">
<p>In addition to adding these modules to the classpath of the server it also added several ini configuration files to the <code>$JETTY_BASE/start.d</code> directory.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated <code>$JETTY_BASE/lib/</code> directory and use the <code>--skip-file-validation=&lt;module name&gt;</code> command line option to prevent errors when starting your server.
</td>
</tr>
</table>
</div>
<div class="sect5">
<h6 id="og-configuration-7"><a class="anchor" href="#og-configuration-7"></a><a class="link" href="#og-configuration-7">Configuration</a></h6>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/session-store-infinispan-remote.ini</code> contains the following configurable properties:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.infinispan.remoteCacheName</dt>
<dd>
<p>Default <code>"sessions"</code>.
This is the name of the cache in Infinispan where sessions will be stored.</p>
</dd>
<dt class="hdlist1">jetty.session.infinispan.idleTimeout.seconds</dt>
<dd>
<p>Integer, in seconds, default <code>0</code>.
This is the amount of time, in seconds, that a session entry in Infinispan can be idle (ie neither read nor written) before Infinispan will delete its entry.
Usually, you do <strong>not</strong> want to set a value for this, as you want Jetty to manage all session expiration (and call any HttpSessionListeners).
You <strong>should</strong> enable the <a href="#og-session-infinispan-remote-query">infinispan-remote-query</a> to allow jetty to <a href="#og-session-base-scavenge">scavenge</a> for expired sessions.
If you do not, then there is the possibility that sessions can be left in Infinispan but no longer referenced by any Jetty node (so called "zombie" or "orphan" sessions), in which case you can use this feature to ensure their removal.</p>
</dd>
</dl>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
You should make sure that the number of seconds you specify is larger than the configured <code>maxIdleTime</code> for sessions.
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.gracePeriod.seconds</dt>
<dd>
<p>Integer, default 3600.
Used during session <a href="#og-session-base-scavenge">scavenging</a>.
Multiples of this period are used to define how long ago a stored session must have expired before it should be <a href="#og-session-base-scavenge">scavenged</a>.</p>
</dd>
<dt class="hdlist1">jetty.session.savePeriod.seconds</dt>
<dd>
<p>Integer, in seconds, default is <code>0</code>.
Whenever a session is accessed by a request, its <code>lastAccessTime</code> and <code>expiry</code> are updated.
Even if your sessions are read-mostly, the <code>lastAccessTime</code> and <code>expiry</code> will always change.
For heavily-used, read-mostly sessions you can save some time by skipping some writes for sessions for which only these fields have changed (ie no session attributes changed).
The value of this property is used to skip writes for these kinds of sessions: the session will only be written out if the time since the last write exceeds the value of this property.</p>
</dd>
</dl>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You should be careful in the use of this property in clustered environments: if you set too large a value for this property, the session may not be written out sufficiently often to update its <code>expiry</code> time thus making it appear to other nodes that it has expired.
Thorough consideration of the <code>maxIdleTime</code> of the session when setting the <code>savePeriod</code> is imperative - it would be undesirable to set a <code>savePeriod</code> that is larger than the <code>maxIdleTime</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-session-infinispan-remote-query"><a class="anchor" href="#og-session-infinispan-remote-query"></a><a class="link" href="#og-session-infinispan-remote-query">Remote Infinispan Query Module</a></h5>
<div class="paragraph">
<p>The <code>infinispan-remote-query</code> module allows Jetty to <a href="#og-session-base-scavenge">scavenge</a> expired sessions.
Note that this is an <strong>additional</strong> module, to be used in conjunction with the <code>session-store-infinispan-remote</code> module.</p>
</div>
<div class="paragraph">
<p>There are no configuration properties associated with this module.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-session-infinispan-embedded"><a class="anchor" href="#og-session-infinispan-embedded"></a><a class="link" href="#og-session-infinispan-embedded">Embedded Infinispan Session Module</a></h5>
<div class="paragraph">
<p>Enabling the <code>session-store-infinispan-embedded</code> module runs an in-process instance of Infinispan.</p>
</div>
<div class="paragraph">
<p>Because Infinispan is not a technology provided by the Eclipse Foundation, you will be prompted to assent to the licenses of the external vendor (Apache in this case).
Infinispan-specific jar files will be downloaded and saved to a directory named <code>$JETTY_BASE/lib/infinispan/</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated <code>$JETTY_BASE/lib/</code> directory and use the <code>--skip-file-validation=&lt;module name&gt;</code> command line option to prevent errors when starting your server.
</td>
</tr>
</table>
</div>
<div class="sect5">
<h6 id="og-configuration-8"><a class="anchor" href="#og-configuration-8"></a><a class="link" href="#og-configuration-8">Configuration</a></h6>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/session-store-infinispan-embedded.ini</code> contains the following configurable properties:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.infinispan.idleTimeout.seconds</dt>
<dd>
<p>Integer, in seconds, default <code>0</code>.
This is the amount of time, in seconds, that a session entry in Infinispan can be idle (ie neither read nor written) before Infinispan will delete its entry.
Usually, you do <strong>not</strong> want to set a value for this, as you want Jetty to manage all session expiration (and call any HttpSessionListeners).
You <strong>should</strong> enable the <a href="#og-session-infinispan-embedded-query">infinispan-embedded-query</a> to allow Jetty to <a href="#og-session-base-scavenge">scavenge</a> for expired sessions.
If you do not, then there is the possibility that expired sessions can be left in Infinispan.</p>
</dd>
</dl>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
You should make sure that the number of seconds you specify is larger than the configured <code>maxIdleTime</code> for sessions.
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.gracePeriod.seconds</dt>
<dd>
<p>Integer, default 3600.
Used during session <a href="#og-session-base-scavenge">scavenging</a>.
Multiples of this period are used to define how long ago a stored session must have expired before it should be <a href="#og-session-base-scavenge">scavenged</a>.</p>
</dd>
<dt class="hdlist1">jetty.session.savePeriod.seconds</dt>
<dd>
<p>Integer, in seconds, default is <code>0</code>.
Whenever a session is accessed by a request, its <code>lastAccessTime</code> and <code>expiry</code> are updated.
Even if your sessions are read-mostly, the <code>lastAccessTime</code> and <code>expiry</code> will always change.
For heavily-used, read-mostly sessions you can save some time by skipping some writes for sessions for which only these fields have changed (ie no session attributes changed).
The value of this property is used to skip writes for these kinds of sessions: the session will only be written out if the time since the last write exceeds the value of this property.</p>
</dd>
</dl>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Thorough consideration of the <code>maxIdleTime</code> of the session when setting the <code>savePeriod</code> is imperative - it would be undesirable to set a <code>savePeriod</code> that is larger than the <code>maxIdleTime</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-session-infinispan-embedded-query"><a class="anchor" href="#og-session-infinispan-embedded-query"></a><a class="link" href="#og-session-infinispan-embedded-query">Embedded Infinispan Query Module</a></h5>
<div class="paragraph">
<p>The <code>infinispan-embedded-query</code> module allows Jetty to <a href="#og-session-base-scavenge">scavenge</a> expired sessions.</p>
</div>
<div class="paragraph">
<p>There are no configuration properties associated with this module.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-converting-session-format-for-jetty-9-4-13"><a class="anchor" href="#og-converting-session-format-for-jetty-9-4-13"></a><a class="link" href="#og-converting-session-format-for-jetty-9-4-13">Converting Session Format for Jetty-9.4.13</a></h5>
<div class="paragraph">
<p>From Jetty-9.4.13 onwards, we have changed the format of the serialized session when using a remote cache (ie using hotrod).
Prior to release 9.4.13 we used the default Infinispan serialization, however this was not able to store sufficient information to allow Jetty to properly deserialize session attributes in all circumstances.
See issue <a href="https://github.com/eclipse/jetty.project/issues/2919" class="bare">https://github.com/eclipse/jetty.project/issues/2919</a> for more background.</p>
</div>
<div class="paragraph">
<p>We have provided a conversion program which will convert any sessions stored in Infinispan to the new format.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
We recommend that you backup your stored sessions before running the conversion program.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>How to use the converter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>java -cp jetty-jakarta-servlet-api-4.0.2.jar:jetty-util-{VERSION}.jar:jetty-server-{VERSION}.jar:infinispan-remote-9.1.0.Final.jar:jetty-infinispan-{VERSION}.jar:[other classpath] org.eclipse.jetty.session.infinispan.InfinispanSessionLegacyConverter
Usage: InfinispanSessionLegacyConverter [-Dhost=127.0.0.1] [-Dverbose=true|false] &lt;cache-name&gt; [check]</pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">The classpath</dt>
<dd>
<p>Must contain the servlet-api, jetty-util, jetty-server, jetty-infinispan and infinispan-remote jars. If your sessions contain attributes that use application classes, you will also need to also put those classes onto the classpath. If your session has been authenticated, you may also need to include the jetty-security and jetty-http jars on the classpath.</p>
</dd>
<dt class="hdlist1">Parameters</dt>
<dd>
<p>When used with no arguments the usage message is printed. When used with the <code>cache-name</code> parameter the conversion is performed. When used with both <code>cache-name</code> and <code>check</code> parameters, sessions are checked for whether or not they are converted.</p>
<div class="dlist">
<dl>
<dt class="hdlist1">-Dhost</dt>
<dd>
<p>you can optionally provide a system property with the address of your remote Infinispan server. Defaults to the localhost.</p>
</dd>
<dt class="hdlist1">-Dverbose</dt>
<dd>
<p>defaults to false. If true, prints more comprehensive stacktrace information about failures. Useful to diagnose why a session is not converted.</p>
</dd>
<dt class="hdlist1">cache-name</dt>
<dd>
<p>the name of the remote cache containing your sessions. This is mandatory.</p>
</dd>
<dt class="hdlist1">check</dt>
<dd>
<p>the optional check command will verify sessions have been converted. Use it <em>after</em> doing the conversion.</p>
</dd>
</dl>
</div>
</dd>
</dl>
</div>
<div class="paragraph">
<p>To perform the conversion, run the InfinispanSessionLegacyConverter with just the <code>cache-name</code>, and optionally the <code>host</code> system property.
The following command will attempt to convert all sessions in the cached named <code>my-remote-cache</code> on the machine <code>myhost</code>, ensuring that application classes in the <code>/my/custom/classes</code> directory are on the classpath:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>java -cp jetty-jakarta-servlet-api-4.0.2.jar:jetty-util-{VERSION}.jar:jetty-server-{VERSION}.jar:infinispan-remote-9.1.0.Final.jar:jetty-infinispan-{VERSION}.jar:/my/custom/classes org.eclipse.jetty.session.infinispan.InfinispanSessionLegacyConverter -Dhost=myhost my-remote-cache</pre>
</div>
</div>
<div class="paragraph">
<p>If the converter fails to convert a session, an error message and stacktrace will be printed and the conversion will abort. The failed session should be untouched, however <em>it is prudent to take a backup of your cache before attempting the conversion</em>.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-session-hazelcast"><a class="anchor" href="#og-session-hazelcast"></a><a class="link" href="#og-session-hazelcast">Modules for Persistent HTTP Sessions: Hazelcast</a></h4>
<div class="paragraph">
<p>Hazelcast can be used to cluster session information in one of two modes: either remote or embedded.
Remote mode means that Hazelcast will create a client to talk to other instances, possibly on other nodes.
Embedded mode means that Hazelcast will start a local instance and communicate with that.</p>
</div>
<div class="sect4">
<h5 id="og-session-hazelcast-remote"><a class="anchor" href="#og-session-hazelcast-remote"></a><a class="link" href="#og-session-hazelcast-remote">Remote Hazelcast Clustering</a></h5>
<div class="paragraph">
<p>Enabling the <code>session-store-hazelcast-remote</code> module allows jetty to communicate with a remote Hazelcast instance to cluster session data.</p>
</div>
<div class="paragraph">
<p>Because Hazelcast is not a technology provided by the Eclipse Foundation, you will be prompted to assent to the licenses of the external vendor (Apache in this case).</p>
</div>
<div class="paragraph">
<p>Hazelcast-specific jar files will be downloaded and saved to a directory named <code>$JETTY_BASE/lib/hazelcast/</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated <code>$JETTY_BASE/lib/</code> directory and use the <code>--skip-file-validation=&lt;module name&gt;</code> command line option to prevent errors when starting your server.
</td>
</tr>
</table>
</div>
<div class="sect5">
<h6 id="og-configuration-9"><a class="anchor" href="#og-configuration-9"></a><a class="link" href="#og-configuration-9">Configuration</a></h6>
<div class="paragraph">
<p>The <code>start.d/session-store-hazelcast-remote.ini</code> contains a list of all the configurable options for the Hazelcast module:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.hazelcast.mapName</dt>
<dd>
<p>The default is "jetty-distributed-session-map".
This is the name of the Map in Hazelcast where sessions will be stored.</p>
</dd>
<dt class="hdlist1">jetty.session.hazelcast.onlyClient</dt>
<dd>
<p>Boolean, default <code>true</code>.
The Hazelcast instance will be configured in client mode.</p>
</dd>
<dt class="hdlist1">jetty.session.hazelcast.configurationLocation</dt>
<dd>
<p>Optional.
This is the path to an external Hazelcast xml configuration file.</p>
</dd>
<dt class="hdlist1">jetty.session.hazelcast.useQueries</dt>
<dd>
<p>Boolean, default <code>false</code>.
If <code>true</code>, Jetty will use Hazelcast queries to find sessions to <a href="#og-session-base-scavenge">scavenge</a>.
If <code>false</code> sessions that are not currently in a <a href="#og-session-cache">session cache</a> cannot be <a href="#og-session-base-scavenge">scavenged</a>, and will need to be removed by some external process.</p>
</dd>
<dt class="hdlist1">jetty.session.hazelcast.addresses</dt>
<dd>
<p>Optional.
These are the addresses of remote Hazelcast instances with which to communicate.</p>
</dd>
<dt class="hdlist1">jetty.session.gracePeriod.seconds</dt>
<dd>
<p>Integer, in seconds.
Default 3600.
Used during session <a href="#og-session-base-scavenge">scavenging</a>.
Multiples of this period are used to define how long ago a stored session must have expired before it should be <a href="#og-session-base-scavenge">scavenged</a>.</p>
</dd>
<dt class="hdlist1">jetty.session.savePeriod.seconds</dt>
<dd>
<p>Integer, in seconds, default is <code>0</code>.
Whenever a session is accessed by a request, its <code>lastAccessTime</code> and <code>expiry</code> are updated.
Even if your sessions are read-mostly, the <code>lastAccessTime</code> and <code>expiry</code> will always change.
For heavily-used, read-mostly sessions you can save some time by skipping some writes for sessions for which only these fields have changed (ie no session attributes changed).
The value of this property is used to skip writes for these kinds of sessions: the session will only be written out if the time since the last write exceeds the value of this property.</p>
</dd>
</dl>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You should be careful in the use of this property in clustered environments: if you set too large a value for this property, the session may not be written out sufficiently often to update its <code>expiry</code> time thus making it appear to other nodes that it has expired.
Thorough consideration of the <code>maxIdleTime</code> of the session when setting the <code>savePeriod</code> is imperative - it would be undesirable to set a <code>savePeriod</code> that is larger than the <code>maxIdleTime</code>.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
Be aware that if your session attributes contain classes from inside your webapp (or Jetty classes) then you will need to put these classes onto the classpath of all of your Hazelcast instances.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-session-hazelcast-embedded"><a class="anchor" href="#og-session-hazelcast-embedded"></a><a class="link" href="#og-session-hazelcast-embedded">Embedded Hazelcast Clustering</a></h5>
<div class="paragraph">
<p>This will run an in-process instance of Hazelcast.
This can be useful for example during testing.
To enable this you enable the <code>session-store-hazelcast-embedded</code> module.</p>
</div>
<div class="paragraph">
<p>Because Hazelcast is not a technology provided by the Eclipse Foundation, you will be prompted to assent to the licenses of the external vendor (Apache in this case).</p>
</div>
<div class="paragraph">
<p>Hazelcast-specific jar files will be downloaded to a directory named <code>$JETTY_BASE/lib/hazelcast/</code>.</p>
</div>
<div class="sect5">
<h6 id="og-configuration-10"><a class="anchor" href="#og-configuration-10"></a><a class="link" href="#og-configuration-10">Configuration</a></h6>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/start.d/session-store-hazelcast-embedded.ini</code> contains a list of all the configurable options for the Hazelcast module:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.hazelcast.mapName</dt>
<dd>
<p>The default is "jetty-distributed-session-map".
This is the name of the Map in Hazelcast where sessions will be stored.
jetty.session.hazelcast.hazelcastInstanceName
Default is "JETTY_DISTRIBUTED_SESSION_INSTANCE".
This is the unique name of the Hazelcast instance that will be created.</p>
</dd>
<dt class="hdlist1">jetty.session.hazelcast.configurationLocation</dt>
<dd>
<p>Optional.
This is the path to an external Hazelcast xml configuration file.</p>
</dd>
<dt class="hdlist1">jetty.session.hazelcast.useQueries</dt>
<dd>
<p>Boolean, default <code>false'.
If `true</code>, Jetty will use Hazelcast queries to find expired sessions to <a href="#og-session-base-scavenge">scavenge</a>.
If <code>false</code> sessions that are not currently in a <a href="#og-session-cache">session cache</a> cannot be <a href="#og-session-base-scavenge">scavenged</a>, and will need to be removed by some external process.</p>
</dd>
<dt class="hdlist1">jetty.session.gracePeriod.seconds</dt>
<dd>
<p>Integer, in seconds.
Default 3600.
Used during session <a href="#og-session-base-scavenge">scavenging</a>.
Multiples of this period are used to define how long ago a stored session must have expired before it should be <a href="#og-session-base-scavenge">scavenged</a>.</p>
</dd>
<dt class="hdlist1">jetty.session.savePeriod.seconds</dt>
<dd>
<p>Integer, in seconds, default is <code>0</code>.
Whenever a session is accessed by a request, its <code>lastAccessTime</code> and <code>expiry</code> are updated.
Even if your sessions are read-mostly, the <code>lastAccessTime</code> and <code>expiry</code> will always change.
For heavily-used, read-mostly sessions you can save some time by skipping some writes for sessions for which only these fields have changed (ie no session attributes changed).
The value of this property is used to skip writes for these kinds of sessions: the session will only be written out if the time since the last write exceeds the value of this property.</p>
</dd>
</dl>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You should be careful in the use of this property in clustered environments: if you set too large a value for this property, the session may not be written out sufficiently often to update its <code>expiry</code> time thus making it appear to other nodes that it has expired.
Thorough consideration of the <code>maxIdleTime</code> of the session when setting the <code>savePeriod</code> is imperative - it would be undesirable to set a <code>savePeriod</code> that is larger than the <code>maxIdleTime</code>.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
If your session attributes contain classes from inside your webapp (or jetty classes) then you will need to put these classes onto the classpath of all of your hazelcast instances. In the case of embedded hazelcast, as it is started before your webapp, it will NOT have access to your webapp&#8217;s classes - you will need to extract these classes and put them onto the jetty server&#8217;s classpath.
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-session-gcloud"><a class="anchor" href="#og-session-gcloud"></a><a class="link" href="#og-session-gcloud">Modules for Persistent HTTP Sessions: Google Cloud DataStore</a></h4>
<div class="paragraph">
<p>Jetty can store http session information into GCloud by enabling the <code>session-store-gcloud</code> module.</p>
</div>
<div class="sect4">
<h5 id="og-preparation"><a class="anchor" href="#og-preparation"></a><a class="link" href="#og-preparation">Preparation</a></h5>
<div class="paragraph">
<p>You will first need to create a project and enable the Google Cloud api: <a href="https://cloud.google.com/docs/authentication#preparation" class="bare">https://cloud.google.com/docs/authentication#preparation</a>.
Take note of the project id that you create in this step as you need to supply it in later steps.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-communicating-with-gclouddatastore"><a class="anchor" href="#og-communicating-with-gclouddatastore"></a><a class="link" href="#og-communicating-with-gclouddatastore">Communicating with GCloudDataStore</a></h5>
<div class="sect5">
<h6 id="og-when-running-jetty-outside-of-google-infrastructure"><a class="anchor" href="#og-when-running-jetty-outside-of-google-infrastructure"></a><a class="link" href="#og-when-running-jetty-outside-of-google-infrastructure">When Running Jetty Outside of Google Infrastructure</a></h6>
<div class="paragraph">
<p>Before running Jetty, you will need to choose one of the following methods to set up the local environment to enable remote GCloud DataStore communications.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Using the GCloud SDK:</p>
<div class="ulist">
<ul>
<li>
<p>Ensure you have the GCloud SDK installed: <a href="https://cloud.google.com/sdk/?hl=en" class="bare">https://cloud.google.com/sdk/?hl=en</a></p>
</li>
<li>
<p>Use the GCloud tool to set up the project you created in the preparation step: <code>gcloud config set project PROJECT_ID</code></p>
</li>
<li>
<p>Use the GCloud tool to authenticate a google account associated with the project created in the preparation step: <code>gcloud auth login ACCOUNT</code></p>
</li>
</ul>
</div>
</li>
<li>
<p>Using environment variables</p>
<div class="ulist">
<ul>
<li>
<p>Define the environment variable <code>GCLOUD_PROJECT</code> with the project id you created in the preparation step.</p>
</li>
<li>
<p>Generate a JSON <a href="https://cloud.google.com/storage/docs/authentication?hl=en#service_accounts">service account key</a> and then define the environment variable <code>GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/key.json</code></p>
</li>
</ul>
</div>
</li>
</ol>
</div>
</div>
<div class="sect5">
<h6 id="og-when-running-jetty-inside-of-google-infrastructure"><a class="anchor" href="#og-when-running-jetty-inside-of-google-infrastructure"></a><a class="link" href="#og-when-running-jetty-inside-of-google-infrastructure">When Running Jetty Inside of Google Infrastructure</a></h6>
<div class="paragraph">
<p>The Google deployment tools will automatically configure the project and authentication information for you.</p>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-configuring-indexes-for-session-data"><a class="anchor" href="#og-configuring-indexes-for-session-data"></a><a class="link" href="#og-configuring-indexes-for-session-data">Configuring Indexes for Session Data</a></h5>
<div class="paragraph">
<p>Using some special, composite indexes can speed up session search operations, although it may make write operations slower.
By default, indexes will <em>not</em> be used.
In order to use them, you will need to manually upload a file that defines the indexes.
This file is named <code>index.yaml</code> and you can find it in your distribution in <code>$JETTY_BASE/etc/sessions/gcloud/index.yaml</code>.</p>
</div>
<div class="paragraph">
<p>Follow the instructions <a href="https://cloud.google.com/datastore/docs/tools/#the_development_workflow_using_gcloud">here</a> to upload the pre-generated <code>index.yaml</code> file.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-communicating-with-the-gclouddatastore-emulator"><a class="anchor" href="#og-communicating-with-the-gclouddatastore-emulator"></a><a class="link" href="#og-communicating-with-the-gclouddatastore-emulator">Communicating with the GCloudDataStore Emulator</a></h5>
<div class="paragraph">
<p>To enable communication using the GCloud Emulator:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Ensure you have the GCloud SDK installed: <a href="https://cloud.google.com/sdk/?hl=en" class="bare">https://cloud.google.com/sdk/?hl=en</a></p>
</li>
<li>
<p>Follow the instructions <a href="https://cloud.google.com/datastore/docs/tools/datastore-emulator">here</a> on how to start the GCloud datastore emulator, and how to propagate the environment variables that it creates to the terminal in which you run Jetty.</p>
</li>
</ul>
</div>
</div>
<div class="sect4">
<h5 id="og-enabling-the-google-cloud-datastore-module"><a class="anchor" href="#og-enabling-the-google-cloud-datastore-module"></a><a class="link" href="#og-enabling-the-google-cloud-datastore-module">Enabling the Google Cloud DataStore Module</a></h5>
<div class="paragraph">
<p>The <code>session-store-gcloud</code> module provides GCloud support for storing session data.</p>
</div>
<div class="paragraph">
<p>Because the Google Cloud DataStore is not a technology provided by the Eclipse Foundation, when enabling the module you will be prompted to assent to the licenses of the external vendor.</p>
</div>
<div class="paragraph">
<p>As GCloud requires certain Java Commons Logging features to work correctly, Jetty routes these through SLF4J by transitively enabling the <code>jcl-slf4j</code> module during installation.
Therefore, you will <em>also</em> need to enable one of the SLF4J implementation modules.
You can either choose one ahead of time and enable it at the same time as the <code>session-store-gcloud</code> module, or you can just enable <code>session-store-gcloud</code> module and it will print out a list of available SLF4J implementations.
You can then choose one and enable it.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
If you want to use updated versions of the jar files automatically downloaded during the module enablement, you can place them in the associated <code>$JETTY_BASE/lib/</code> directory and use the <code>--skip-file-validation=&lt;module name&gt;</code> command line option to prevent errors when starting your server.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-configuration-11"><a class="anchor" href="#og-configuration-11"></a><a class="link" href="#og-configuration-11">Configuration</a></h4>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/session-store-gcloud.ini</code> file contains all of the configurable properties for the <code>session-store-gcloud</code> module:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.gcloud.maxRetries</dt>
<dd>
<p>Integer.
Default 5.
Maximum number of retries to connect to GCloud DataStore to write a session.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.backoffMs</dt>
<dd>
<p>Integer in milliseconds.
Default 1000.
Number of milliseconds between successive attempts to connect to the GCloud DataStore to write a session.</p>
</dd>
<dt class="hdlist1">jetty.session.gracePeriod.seconds</dt>
<dd>
<p>Integer, in seconds.
Default 3600.
Used during session <a href="#og-session-base-scavenge">scavenging</a>.
Multiples of this period are used to define how long ago a stored session must have expired before it should be <a href="#og-session-base-scavenge">scavenged</a>.</p>
</dd>
<dt class="hdlist1">jetty.session.savePeriod.seconds</dt>
<dd>
<p>Integer, in seconds, default is <code>0</code>.
Whenever a session is accessed by a request, its <code>lastAccessTime</code> and <code>expiry</code> are updated.
Even if your sessions are read-mostly, the <code>lastAccessTime</code> and <code>expiry</code> will always change.
For heavily-used, read-mostly sessions you can save some time by skipping some writes for sessions for which only these fields have changed (ie no session attributes changed).
The value of this property is used to skip writes for these kinds of sessions: the session will only be written out if the time since the last write exceeds the value of this property.</p>
</dd>
</dl>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You should be careful in the use of this property in clustered environments: if you set too large a value for this property, the session may not be written out sufficiently often to update its <code>expiry</code> time thus making it appear to other nodes that it has expired.
Thorough consideration of the <code>maxIdleTime</code> of the session when setting the <code>savePeriod</code> is imperative - it would be undesirable to set a <code>savePeriod</code> that is larger than the <code>maxIdleTime</code>.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.gcloud.namespace</dt>
<dd>
<p>Optional.
Sets the namespace for GCloud Datastore to use.
If set, partitions the visibility of session data between webapps, which is helpful for multi-tenant deployments.
More information can be found <a href="https://cloud.google.com/datastore/docs/concepts/multitenancy">here.</a></p>
</dd>
<dt class="hdlist1">Configuration of the stored session object and its fields names-</dt>
<dd>
<p>You should very rarely, if ever, need to change these defaults.</p>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.gcloud.model.kind</dt>
<dd>
<p>The default is "GCloudSession".
This is the type of the object that is stored in GCloud.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.id</dt>
<dd>
<p>The default is "id".
This is the session id.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.contextPath</dt>
<dd>
<p>The default is "contextPath".
This is the canonicalized context path of the context to which the session belongs.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.vhost</dt>
<dd>
<p>The default is "vhost".
This is the canonicalized virtual host of the context to which the session belongs.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.accessed</dt>
<dd>
<p>The default is "accessed".
This is the current access time of the session.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.lastAccessed</dt>
<dd>
<p>The default is "lastAccessed".
This is the last access time of the session.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.createTime</dt>
<dd>
<p>The default is "createTime".
This is the time, in ms since the epoch, at which the session was created.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.cookieSetTime</dt>
<dd>
<p>The default is "cookieSetTime".
This is the time at which the session cookie was last set.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.lastNode</dt>
<dd>
<p>The default is "lastNode".
This is the <code>workerName</code> of the last node to manage the session.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.expiry</dt>
<dd>
<p>The default is "expiry".
This is the time, in ms since the epoch, at which the session will expire.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.maxInactive</dt>
<dd>
<p>The default is "maxInactive".
This is the session timeout in ms.</p>
</dd>
<dt class="hdlist1">jetty.session.gcloud.model.attributes</dt>
<dd>
<p>The default is "attributes".
This is a map of all the session attributes.</p>
</dd>
</dl>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect3">
<h4 id="og-session-memcached"><a class="anchor" href="#og-session-memcached"></a><a class="link" href="#og-session-memcached">Modules for Persistent HTTP Sessions: The L2 Session Data Cache</a></h4>
<div class="paragraph">
<p>If your chosen persistence technology is slow, it can be helpful to locally cache the session data.
The <code>CachingSessionDataStore</code> is a special type of <code>SessionDataStore</code> that locally caches session data, which makes reads faster. It writes-through to your chosen type of <code>SessionDataStore</code> when session data changes.</p>
</div>
<div class="sect4">
<h5 id="og-memcachedsessiondatamap"><a class="anchor" href="#og-memcachedsessiondatamap"></a><a class="link" href="#og-memcachedsessiondatamap">MemcachedSessionDataMap</a></h5>
<div class="paragraph">
<p>The <code>MemcachedSessionDataMap</code> uses <code>memcached</code> to perform caching of <code>SessionData</code>.</p>
</div>
<div class="paragraph">
<p>To enable it with the Jetty distribution, enable the <code>session-store-cache</code> module, along with your chosen <code>session-store-xxxx</code> module.</p>
</div>
<div class="sect5">
<h6 id="og-configuration-12"><a class="anchor" href="#og-configuration-12"></a><a class="link" href="#og-configuration-12">Configuration</a></h6>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/session-store-cache.ini</code> contains the following configurable properties:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.session.memcached.host</dt>
<dd>
<p>Default value is <code>localhost</code>.
This is the host on which the memcached server resides.</p>
</dd>
<dt class="hdlist1">jetty.session.memcached.port</dt>
<dd>
<p>Default value is <code>11211</code>.
This is the port on which the memcached server is listening.</p>
</dd>
<dt class="hdlist1">jetty.session.memcached.expirySec</dt>
<dd>
<p>Default value <code>0</code>.
This is the length of time in seconds that an item can remain in the memcached cache, where 0 indicates indefinitely.</p>
</dd>
<dt class="hdlist1">jetty.session.memcached.heartbeats</dt>
<dd>
<p>Default value <code>true</code>.
Whether the memcached system should generate heartbeats.</p>
</dd>
</dl>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-session-usecases"><a class="anchor" href="#og-session-usecases"></a><a class="link" href="#og-session-usecases">Session Scenarios</a></h4>
<div class="sect4">
<h5 id="og-minimizing-support-for-sessions"><a class="anchor" href="#og-minimizing-support-for-sessions"></a><a class="link" href="#og-minimizing-support-for-sessions">Minimizing Support for Sessions</a></h5>
<div class="paragraph">
<p>The standard support for webapps in Jetty will use sessions cached in memory, but not persisted/clustered, with a scavenge for expired sessions that occurs every 10 minutes.
If you wish to pare back support for sessions because you know your app doesn&#8217;t use them (or use JSPs that use them), then you can do the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>enable the <a href="#og-session-base">base sessions module</a> and <a href="#og-session-base">configure the scavenge interval</a> to 0 to prevent scavenging</p>
</li>
<li>
<p>enable the <a href="#og-session-cache-null">null session cache module</a> to prevent sessions being cached in memory</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If you wish to do any further minimization, you should consult the <a href="../programming-guide/index.html">Programming Guide</a>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-clustering-with-a-sticky-load-balancer"><a class="anchor" href="#og-clustering-with-a-sticky-load-balancer"></a><a class="link" href="#og-clustering-with-a-sticky-load-balancer">Clustering with a Sticky Load Balancer</a></h5>
<div class="paragraph">
<p>Preferably, your cluster will utilize a sticky load balancer.
This will route requests for the same session to the same Jetty instance.
In this case, the <a href="#og-session-cache-hash"><code>DefaultSessionCache</code></a> can be used to keep in-use session objects <a href="#og-session-cache-hash">in memory</a>.
You can fine-tune the cache by controlling how long session objects remain in memory with the <a href="#og-session-cache-hash">eviction policy settings</a>.</p>
</div>
<div class="paragraph">
<p>If you have a large number of sessions or very large session objects, then you may want to manage your memory allocation by controlling the amount of time session objects spend in the cache.
The <code>EVICT_ON_SESSION_EXIT</code> eviction policy will remove a session object from the cache as soon as the last simultaneous request referencing it exits.
Alternatively, the <code>EVICT_ON_INACTIVITY</code> policy will remove a session object from the cache after a configurable amount of time has passed without a request referencing it.</p>
</div>
<div class="paragraph">
<p>If your sessions are very long lived and infrequently referenced, you might use the <code>EVICT_ON_INACTIVITY_POLICY</code> to control the size of the cache.</p>
</div>
<div class="paragraph">
<p>If your sessions are small, or relatively few or stable in number or they are read-mostly, then you might select the <code>NEVER_EVICT</code> policy.
With this policy, session objects will remain in the cache until they either expire or are explicitly invalidated.</p>
</div>
<div class="paragraph">
<p>If you have a high likelihood of simultaneous requests for the same session object, then the <code>EVICT_ON_SESSION_EXIT</code> policy will ensure the session object stays in the cache as long as it is needed.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-clustering-without-a-sticky-load-balancer"><a class="anchor" href="#og-clustering-without-a-sticky-load-balancer"></a><a class="link" href="#og-clustering-without-a-sticky-load-balancer">Clustering Without a Sticky Load Balancer</a></h5>
<div class="paragraph">
<p>Without a sticky load balancer requests for the same session may arrive on any node in the cluster.
This means it is likely that the copy of the session object in any <code>SessionCache</code> is likely to be out-of-date, as the session was probably last accessed on a different node.
In this case, your choices are to use either the <a href="#og-session-cache-null"><code>NullSessionCache</code></a> or to de-tune the <a href="#og-session-cache-hash"><code>DefaultSessionCache</code></a>.
If you use the <code>NullSessionCache</code> all session object caching is avoided.
This means that every time a request references a session it must be read in from persistent storage.
It also means that there can be no sharing of session objects for multiple requests for the same session: each will have their own independent session object.
Furthermore, the outcome of session writes are indeterminate because the Servlet Specification does not mandate ACID transactions for sessions.</p>
</div>
<div class="paragraph">
<p>If you use the <code>DefaultSessionCache</code>, there is a risk that the caches on some nodes will contain out-of-date session information as simultaneous requests for the same session are scattered over the cluster.
To mitigate this somewhat you can use the <code>EVICT_ON_SESSION_EXIT</code> eviction policy: this will ensure that the session is removed from the cache as soon as the last simultaneous request for it exits.
Again, due to the lack of session transactionality, the ordering outcome of write operations cannot be guaranteed.
As the session is cached while at least one request is accessing it, it is possible for multiple simultaneous requests to share the same session object.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-handling-corrupted-or-unreadable-session-data"><a class="anchor" href="#og-handling-corrupted-or-unreadable-session-data"></a><a class="link" href="#og-handling-corrupted-or-unreadable-session-data">Handling Corrupted or Unreadable Session Data</a></h5>
<div class="paragraph">
<p>For various reasons it might not be possible for the <code>SessionDataStore</code> to re-read a stored session.
One scenario is that the session stores a serialized object in its attributes, and after a re-deployment there in an incompatible class change.
Setting the <code>$JETTY_BASE/start.d/session-cache-hash.ini</code> or <code>$JETTY_BASE/start.d/session-cache-null.ini</code> property <code>jetty.session.removeUnloadableSessions</code> to <code>true</code> will allow the unreadable session to be removed from persistent storage.
This can be useful for preventing the <a href="#og-session-base-scavenge">scavenger</a> from continually generating errors on the same expired, but un-readable session.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-xml"><a class="anchor" href="#og-xml"></a><a class="link" href="#og-xml">Jetty XML</a></h3>
<div class="paragraph">
<p>The Jetty XML format is a straightforward mapping of XML elements to Java APIs so that any object can be instantiated and getters, setters, and methods can be called.</p>
</div>
<div class="paragraph">
<p>The Jetty XML format is very similar to that of frameworks like Spring or Plexus, although it predates all of them and it&#8217;s typically more powerful as it can invoke any Java API.</p>
</div>
<div class="paragraph">
<p>The Jetty XML format is used in <a href="#og-modules">Jetty modules</a> to create the Jetty server components, as well as in <a href="#og-deploy">Jetty XML context files</a> to configure web applications, but it can be used to call any Java API.</p>
</div>
<div class="sect3">
<h4 id="og-xml-syntax"><a class="anchor" href="#og-xml-syntax"></a><a class="link" href="#og-xml-syntax">Jetty XML Syntax</a></h4>
<div class="paragraph">
<p>The Jetty XML syntax defines XML element that allow you to call any Java API and that allow you to interact in a simpler way with the <a href="#og-modules">Jetty module system</a> and the <a href="#og-deploy">Jetty deploy system</a>.</p>
</div>
<div class="paragraph">
<p>The Jetty XML elements define attributes such as <code>id</code>, <code>name</code>, <code>class</code>, etc. that may be replaced by correspondent elements, so that these XML documents are equivalent:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure&gt;
&lt;Get id="stderr" class="java.lang.System" name="err"&gt;
&lt;Call name="println" arg="HELLO" /&gt;
&lt;/Get&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure&gt;
&lt;Get&gt;
&lt;Id&gt;stderr&lt;/Id&gt;
&lt;Name&gt;err&lt;/Name&gt;
&lt;Class&gt;java.lang.System&lt;/Class&gt;
&lt;Call&gt;
&lt;Name&gt;println&lt;/Name&gt;
&lt;Arg&gt;HELLO&lt;/Arg&gt;
&lt;/Call&gt;
&lt;/Get&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The version using attributes is typically shorter and nicer to read, but sometimes the attribute value cannot be a literal string (for example, it could be the value of a system property) and that&#8217;s where elements gives you the required flexibility.</p>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-configure"><a class="anchor" href="#og-xml-syntax-configure"></a><a class="link" href="#og-xml-syntax-configure"><code>&lt;Configure&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>Configure</code> must be the root element of the XML document.</p>
</div>
<div class="paragraph">
<p>The following Jetty XML creates an empty <code>String</code> and assigns it the id <code>mystring</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure id="mystring" class="java.lang.String" /&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is equivalent to the following Java code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">var mystring = new String();</code></pre>
</div>
</div>
<div class="paragraph">
<p>If an object with the id <code>mystring</code> already exists, then it is not created again but rather just referenced.</p>
</div>
<div class="paragraph">
<p>Typically the <code>&lt;Configure&gt;</code> element is used to configure a <code>Server</code> instance or <code>ContextHandler</code> subclasses such as <code>WebAppContext</code> that represent web applications.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-arg"><a class="anchor" href="#og-xml-syntax-arg"></a><a class="link" href="#og-xml-syntax-arg"><code>&lt;Arg&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>Arg</code> is used to pass arguments to <a href="#og-xml-syntax-new">constructors</a> and <a href="#og-xml-syntax-call">method calls</a>.</p>
</div>
<div class="paragraph">
<p>The following example creates a minimal Jetty <code>Server</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.server.Server"&gt;
&lt;Arg type="int"&gt;8080&lt;/Arg&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Arguments may have a <code>type</code> attribute that explicitly performs <a href="#og-xml-syntax-types">type coercion</a>.</p>
</div>
<div class="paragraph">
<p>Arguments may also have a <code>name</code> attribute, which is matched with the corresponding Java annotation in the source class, that helps to identify arguments:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.server.Server"&gt;
&lt;Arg name="port" type="int"&gt;8080&lt;/Arg&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-new"><a class="anchor" href="#og-xml-syntax-new"></a><a class="link" href="#og-xml-syntax-new"><code>&lt;New&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;New&gt;</code> creates a new object of the type specified by the mandatory <code>class</code> attribute.
A sequence of <code>Arg</code> elements, that must be contiguous and before other elements, may be present to specify the constructor arguments.</p>
</div>
<div class="paragraph">
<p>Within element <code>&lt;New&gt;</code> the newly created object is in <a href="#og-xml-syntax-scope">scope</a> and may be the implicit target of other, nested, elements.</p>
</div>
<div class="paragraph">
<p>The following example creates an <code>ArrayList</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure&gt;
&lt;New id="mylist" class="java.util.ArrayList"&gt;
&lt;Arg type="int"&gt;16&lt;/Arg&gt;
&lt;/New&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is equivalent to the following Java code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">var mylist = new ArrayList(16);</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-call"><a class="anchor" href="#og-xml-syntax-call"></a><a class="link" href="#og-xml-syntax-call"><code>&lt;Call&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;Call&gt;</code> invokes a method specified by the mandatory <code>name</code> attribute.
A sequence of <code>Arg</code> elements, that must be contiguous and before other elements, may be present to specify the method arguments.</p>
</div>
<div class="paragraph">
<p>Within element <code>&lt;Call&gt;</code> the return value, if the return type is not <code>void</code>, is in <a href="#og-xml-syntax-scope">scope</a> and may be the implicit target of other, nested, elements.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure&gt;
&lt;New class="java.util.ArrayList"&gt;
&lt;Call name="listIterator"&gt;
&lt;Arg type="int"&gt;0&lt;/Arg&gt;
&lt;/Call&gt;
&lt;Call name="next" /&gt;
&lt;/New&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is equivalent to the following Java code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">new ArrayList().listIterator(0).next();</code></pre>
</div>
</div>
<div class="paragraph">
<p>It is possible to call <code>static</code> methods by specifying the <code>class</code> attribute:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure&gt;
&lt;Call id="myhost" name="getByName" class="java.net.InetAddress"&gt;
&lt;Arg&gt;jdk.java.net&lt;/Arg&gt;
&lt;/Call&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is equivalent to the following Java code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">var myhost = InetAddress.getByName("jdk.java.net");</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-get"><a class="anchor" href="#og-xml-syntax-get"></a><a class="link" href="#og-xml-syntax-get"><code>&lt;Get&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;Get&gt;</code> retrieves the value of a JavaBean property specified by the mandatory <code>name</code> attribute.</p>
</div>
<div class="paragraph">
<p>If the JavaBean property is <code>foo</code> (or <code>Foo</code>), <code>&lt;Get&gt;</code> first attempts to invoke <em>method</em> <code>getFoo()</code>; failing that, attempts to retrieve the value from <em>field</em> <code>foo</code> (or <code>Foo</code>).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure id="server" class="org.eclipse.jetty.server.Server"&gt;
&lt;!-- Invokes getter method server.getVersion() --&gt;
&lt;Get id="version" name="version" /&gt;
&lt;!-- Gets the System.err field --&gt;
&lt;Get class="java.lang.System" name="err"&gt;
&lt;Call name="println"&gt;
&lt;Arg&gt;Jetty&lt;/Arg&gt;
&lt;/Call&gt;
&lt;/Get&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-set"><a class="anchor" href="#og-xml-syntax-set"></a><a class="link" href="#og-xml-syntax-set"><code>&lt;Set&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;Set&gt;</code> stores the value of a JavaBean property specified by the mandatory <code>name</code> attribute.</p>
</div>
<div class="paragraph">
<p>If the JavaBean property is <code>foo</code> (or <code>Foo</code>), <code>&lt;Set&gt;</code> first attempts to invoke <em>method</em> <code>setFoo(&#8230;&#8203;)</code> with the value in the <a href="#og-xml-syntax-scope">scope</a> as argument; failing that, attempts to store the value in the scope to <em>field</em> <code>foo</code> (or <code>Foo</code>).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure id="server" class="org.eclipse.jetty.server.Server"&gt;
&lt;!-- The value in the &lt;Set&gt; scope is the string "true" --&gt;
&lt;Set name="dryRun"&gt;true&lt;/Set&gt;
&lt;!-- The value in the &lt;Set&gt; scope is the instance created by &lt;New&gt; --&gt;
&lt;Set name="requestLog"&gt;
&lt;New class="org.eclipse.jetty.server.CustomRequestLog" /&gt;
&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-map"><a class="anchor" href="#og-xml-syntax-map"></a><a class="link" href="#og-xml-syntax-map"><code>&lt;Map&gt;</code> and <code>&lt;Entry&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;Map&gt;</code> allows the creation of a new <code>java.util.Map</code> implementation, specified by the <code>class</code> attribute&#8201;&#8212;&#8201;by default a <code>HashMap</code>.</p>
</div>
<div class="paragraph">
<p>The map entries are specified with a sequence of <code>&lt;Entry&gt;</code> elements, each with exactly 2 <code>&lt;Item&gt;</code> elements, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure&gt;
&lt;Map class="java.util.concurrent.ConcurrentHashMap"&gt;
&lt;Entry&gt;
&lt;Item&gt;host&lt;/Item&gt;
&lt;Item&gt;
&lt;Call class="java.net.InetAddress" name="getByName"&gt;
&lt;Arg&gt;localhost&lt;/Arg&gt;
&lt;/Call&gt;
&lt;/Item&gt;
&lt;/Entry&gt;
&lt;/Map&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-put"><a class="anchor" href="#og-xml-syntax-put"></a><a class="link" href="#og-xml-syntax-put"><code>&lt;Put&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;Put&gt;</code> is a convenience element that puts a key/value pair into objects that implement <code>java.util.Map</code>.
You can only specify the key value via the <code>name</code> attribute, so the key can only be a literal string (for keys that are not literal strings, use the <code>&lt;Call&gt;</code> element).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure&gt;
&lt;New class="java.util.Properties"&gt;
&lt;Put name="host"&gt;
&lt;Call class="java.net.InetAddress" name="getByName"&gt;
&lt;Arg&gt;localhost&lt;/Arg&gt;
&lt;/Call&gt;
&lt;/Put&gt;
&lt;/New&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-array"><a class="anchor" href="#og-xml-syntax-array"></a><a class="link" href="#og-xml-syntax-array"><code>&lt;Array&gt;</code> and <code>&lt;Item&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;Array&gt;</code> creates a new array, whose component type may be specified by the <code>type</code> attribute.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure&gt;
&lt;Array type="java.lang.Object"&gt;
&lt;Item /&gt; &lt;!-- null --&gt;
&lt;Item&gt;literalString&lt;/Item&gt;
&lt;Item type="String"&gt;&lt;/Item&gt; &lt;!-- empty string --&gt;
&lt;Item type="Double"&gt;1.0D&lt;/Item&gt;
&lt;Item&gt;
&lt;New class="java.lang.Exception" /&gt;
&lt;/Item&gt;
&lt;/Array&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-ref"><a class="anchor" href="#og-xml-syntax-ref"></a><a class="link" href="#og-xml-syntax-ref"><code>&lt;Ref&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;Ref&gt;</code> allows you to reference an object via the <code>refid</code> attribute`, putting it into <a href="#og-xml-syntax-scope">scope</a> so that nested elements can operate on it.
You must give a unique <code>id</code> attribute to the objects you want to reference.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;!-- The Jetty Server has id="server" --&gt;
&lt;Configure id="server" class="org.eclipse.jetty.server.Server"&gt;
&lt;Get class="java.lang.System" name="err"&gt;
&lt;!-- Here the System.err field is in scope, but you
want to operate on the server to get its version --&gt;
&lt;Ref refid="server"&gt;
&lt;!-- Store the server version under id="myversion" --&gt;
&lt;Get id="myversion" name="version" /&gt;
&lt;/Ref&gt;
&lt;Call name="println"&gt;
&lt;!-- Reference the server version stored above --&gt;
&lt;Arg&gt;Server version is: &lt;Ref refid="myversion" /&gt;&lt;/Arg&gt;
&lt;/Call&gt;
&lt;/Get&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-property"><a class="anchor" href="#og-xml-syntax-property"></a><a class="link" href="#og-xml-syntax-property"><code>&lt;Property&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;Property&gt;</code> retrieves the value of the Jetty module property specified by the <code>name</code> attribute, and it is mostly used when creating <a href="#og-modules">custom Jetty modules</a> or when using <a href="#og-deploy-jetty">Jetty context XML files</a>.</p>
</div>
<div class="paragraph">
<p>The <code>deprecated</code> attribute allows you to specify a comma separated list of old, deprecated, property names for backward compatibility.</p>
</div>
<div class="paragraph">
<p>The <code>default</code> attribute allows you to specify a default value for the property, if it has not been explicitly defined.</p>
</div>
<div class="paragraph">
<p>For example, you may want to configure the context path of your web application in this way:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure class="org.eclipse.jetty.webapp.WebAppContext"&gt;
&lt;Set name="contextPath"&gt;
<mark>&lt;Property name="com.myapps.mywiki.context.path" default="/wiki" /&gt;</mark>
&lt;/Set&gt;
&lt;Set name="war"&gt;/opt/myapps/mywiki.war&lt;/Set&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>contextPath</code> value is resolved by looking for the Jetty module property <code>com.myapps.mywiki.context.path</code>; if this property is not set, then the default value of <code>/wiki</code> is used.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-system-property"><a class="anchor" href="#og-xml-syntax-system-property"></a><a class="link" href="#og-xml-syntax-system-property"><code>&lt;SystemProperty&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;SystemProperty&gt;</code> retrieves the value of the JVM system property specified by the <code>name</code> attribute, via <code>System.getProperty(&#8230;&#8203;)</code>.</p>
</div>
<div class="paragraph">
<p>The <code>deprecated</code> attribute allows you to specify a comma separated list of old, deprecated, system property names for backward compatibility.</p>
</div>
<div class="paragraph">
<p>The <code>default</code> attribute allows you to specify a default value for the system property value, if it has not been explicitly defined.</p>
</div>
<div class="paragraph">
<p>The following example creates a minimal Jetty <code>Server</code> that listens on a port specified by the <code>com.acme.http.port</code> system property:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure id="server" class="org.eclipse.jetty.server.Server"&gt;
&lt;Arg type="int"&gt;
&lt;SystemProperty name="com.acme.http.port" default="8080" /&gt;
&lt;/Arg&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-env"><a class="anchor" href="#og-xml-syntax-env"></a><a class="link" href="#og-xml-syntax-env"><code>&lt;Env&gt;</code></a></h5>
<div class="paragraph">
<p>Element <code>&lt;Env&gt;</code> retrieves the value of the environment variable specified by the <code>name</code> attribute, via <code>System.getenv(&#8230;&#8203;)</code>.</p>
</div>
<div class="paragraph">
<p>The <code>deprecated</code> attribute allows you to specify a comma separated list of old, deprecated, environment variable names for backward compatibility.</p>
</div>
<div class="paragraph">
<p>The <code>default</code> attribute allows you to specify a default value for the environment variable value, if it has not been explicitly defined.</p>
</div>
<div class="paragraph">
<p>The following example creates a minimal Jetty <code>Server</code> that listens on a port specified by the <code>COM_ACME_HTTP_PORT</code> environment variable:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure id="server" class="org.eclipse.jetty.server.Server"&gt;
&lt;Arg type="int"&gt;
&lt;Env name="COM_ACME_HTTP_PORT" default="8080" /&gt;
&lt;/Arg&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-types"><a class="anchor" href="#og-xml-syntax-types"></a><a class="link" href="#og-xml-syntax-types">Type Coercion</a></h5>
<div class="paragraph">
<p>Elements that have the <code>type</code> attribute explicitly perform the type coercion of the string value present in the XML document to the Java type specified by the <code>type</code> attribute.</p>
</div>
<div class="paragraph">
<p>Supported types are the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>all primitive types and their boxed equivalents, for example <code>type="int"</code> but also <code>type="Integer"</code> (short form) and <code>type="java.lang.Integer"</code> (fully qualified form)</p>
</li>
<li>
<p><code>java.lang.String</code>, in both short form and fully qualified form</p>
</li>
<li>
<p><code>java.net.URL</code>, in both short form and fully qualified form</p>
</li>
<li>
<p><code>java.net.InetAddress</code>, in both short form and fully qualified form</p>
</li>
</ul>
</div>
</div>
<div class="sect4">
<h5 id="og-xml-syntax-scope"><a class="anchor" href="#og-xml-syntax-scope"></a><a class="link" href="#og-xml-syntax-scope">Scopes</a></h5>
<div class="paragraph">
<p>Elements that create new objects or that return a value create a <em>scope</em>.
Within these elements there may be nested elements that will operate on that scope, i.e. on the new object or returned value.</p>
</div>
<div class="paragraph">
<p>The following example illustrates how scopes work:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd"&gt;
&lt;Configure id="server" class="org.eclipse.jetty.server.Server"&gt;
&lt;Arg type="int"&gt;8080&lt;/Arg&gt;
&lt;!-- Here the Server object has been created and is in scope --&gt;
&lt;!-- Calls the setter on the Server object that is in scope --&gt;
&lt;Set name="stopTimeout"&gt;5000&lt;/Set&gt;
&lt;!-- Creates a new object --&gt;
&lt;New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration"&gt;
&lt;!-- Here the HttpConfiguration just created is in a nested scope --&gt;
&lt;!-- Calls the setter on the HttpConfiguration object that is in scope --&gt;
&lt;Set name="secureScheme"&gt;https&lt;/Set&gt;
&lt;/New&gt;
&lt;!-- Calls the getter on the Server object that is in scope --&gt;
&lt;Get name="ThreadPool"&gt;
&lt;!-- Here the ThreadPool object returned by the getter is in a nested scope --&gt;
&lt;!-- Calls the setter on the ThreadPool object that is in scope --&gt;
&lt;Set name="maxThreads" type="int"&gt;256&lt;/Set&gt;
&lt;/Get&gt;
&lt;!-- Gets the System.err field --&gt;
&lt;Get class="java.lang.System" name="err"&gt;
&lt;!-- Here the System.err object is in scope --&gt;
&lt;!-- Equivalent to: var myversion = server.getVersion() --&gt;
&lt;Ref refid="server"&gt;
&lt;!-- Here the "server" object is in scope --&gt;
&lt;Get id="myversion" name="version" /&gt;
&lt;/Ref&gt;
&lt;!-- Calls println() on the System.err object --&gt;
&lt;Call name="println"&gt;
&lt;Arg&gt;Server version is: &lt;Ref refid="myversion" /&gt;&lt;/Arg&gt;
&lt;/Call&gt;
&lt;/Get&gt;
&lt;/Configure&gt;</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Version 11.0.0-SNAPSHOT<br>
Last updated 2020-10-04 00:12:43 UTC
</div>
</div>
</body>
</html>