blob: 7340dbd3f9c3777c5ec95fc3113318855cb78f62 [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.15">
<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">
<link rel="stylesheet" href="./coderay-asciidoctor.css">
<link rel="stylesheet" href="../styles.css">
<link rel="stylesheet" href="../toc.css">
<script src="../toc.js"></script>
</head>
<body class="article toc2 toc-left">
<div id="header">
<h1><a href="https://eclipse.org/jetty">Eclipse Jetty</a>: 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 10.0.7,</span>
<span id="revdate">2021-10-06</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-begin">Getting Started</a>
<ul class="sectlevel3">
<li><a href="#og-quick-setup">Quick Setup</a></li>
<li><a href="#og-begin-download">Downloading Jetty</a></li>
<li><a href="#og-begin-install">Installing Jetty</a></li>
<li><a href="#og-begin-start">Starting Jetty</a></li>
<li><a href="#og-begin-deploy">Deploying Web Applications</a>
<ul class="sectlevel4">
<li><a href="#og-begin-deploy-war">Deploying *.war Files</a></li>
<li><a href="#og-begin-deploy-war-advanced">Advanced Deployment</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-arch">Architecture Overview</a>
<ul class="sectlevel3">
<li><a href="#og-arch-concepts">Main Concepts</a></li>
<li><a href="#og-arch-modules">Jetty Modules</a></li>
<li><a href="#og-arch-jetty-base"><code>$JETTY_HOME</code> and <code>$JETTY_BASE</code></a></li>
<li><a href="#og-arch-start">Start Mechanism</a></li>
</ul>
</li>
<li><a href="#og-features">Eclipse Jetty Features</a></li>
<li><a href="#og-howtos">Eclipse Jetty How-Tos</a></li>
<li><a href="#og-start">Jetty Start Mechanism</a>
<ul class="sectlevel3">
<li><a href="#og-start-configure">Configuring $JETTY_BASE</a>
<ul class="sectlevel4">
<li><a href="#og-start-configure-enable">Enabling Modules</a></li>
<li><a href="#og-start-configure-disable">Disabling Modules</a></li>
<li><a href="#og-start-configure-edit-ini">Editing <code>*.ini</code> Files</a></li>
<li><a href="#og-start-configure-custom-module">Adding Your Own Modules</a></li>
<li><a href="#og-start-configure-custom-module-exec">Custom Module with JVM Options</a></li>
<li><a href="#og-start-configure-display">Displaying the Configuration</a></li>
<li><a href="#og-start-configure-dry-run">Displaying the JVM Command Line</a></li>
</ul>
</li>
<li><a href="#og-start-start">Starting Jetty</a>
<ul class="sectlevel4">
<li><a href="#og-start-start-class-path">Server Class-Path</a></li>
<li><a href="#og-start-start-xml">Assembling Jetty Components</a></li>
</ul>
</li>
<li><a href="#og-start-start-jpms">Starting Jetty using JPMS</a>
<ul class="sectlevel4">
<li><a href="#og-start-start-jpms-advanced">Advanced JPMS Configuration</a></li>
</ul>
</li>
<li><a href="#og-start-stop">Stopping Jetty</a>
<ul class="sectlevel4">
<li><a href="#og-start-stop-remote">Stopping Jetty from Remote</a></li>
</ul>
</li>
<li><a href="#og-start-mechanism-logging">Start Mechanism Logging</a></li>
<li><a href="#og-start-reference">Usage Reference</a></li>
</ul>
</li>
<li><a href="#og-modules">Jetty Modules</a>
<ul class="sectlevel3">
<li><a href="#og-modules-names">Module Names</a></li>
<li><a href="#og-modules-components">Module Components</a></li>
<li><a href="#og-modules-properties">Module Properties</a></li>
<li><a href="#og-modules-directives">Module Directives</a>
<ul class="sectlevel4">
<li><a href="#og-modules-directive-description">[description]</a></li>
<li><a href="#og-modules-directive-tags">[tags]</a></li>
<li><a href="#og-modules-directive-provides">[provides]</a></li>
<li><a href="#og-modules-directive-depends">[depends]</a></li>
<li><a href="#og-modules-directive-after">[after]</a></li>
<li><a href="#og-modules-directive-before">[before]</a></li>
<li><a href="#og-modules-directive-files">[files]</a></li>
<li><a href="#og-modules-directive-libs">[libs]</a></li>
<li><a href="#og-modules-directive-xml">[xml]</a></li>
<li><a href="#og-modules-directive-ini">[ini]</a></li>
<li><a href="#og-modules-directive-ini-template">[ini-template]</a></li>
<li><a href="#og-modules-directive-exec">[exec]</a></li>
<li><a href="#og-modules-directive-jpms">[jpms]</a></li>
<li><a href="#og-modules-directive-license">[license]</a></li>
<li><a href="#og-modules-directive-version">[version]</a></li>
</ul>
</li>
<li><a href="#og-modules-custom">Custom Jetty Modules</a>
<ul class="sectlevel4">
<li><a href="#og-modules-custom-modify">Modifying an Existing Module</a></li>
<li><a href="#og-modules-custom-create">Creating a New Module</a></li>
</ul>
</li>
<li><a href="#og-modules-standard">Standard Modules</a></li>
<li><a href="#og-module-alpn">Module <code>alpn</code></a>
<ul class="sectlevel4">
<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="sectlevel5">
<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-http2">Module <code>http2</code></a></li>
<li><a href="#og-module-http2c">Module <code>http2c</code></a></li>
<li><a href="#og-module-http-forwarded">Module <code>http-forwarded</code></a></li>
<li><a href="#og-module-https">Module <code>https</code></a></li>
<li><a href="#og-module-jmx-remote">Module <code>jmx-remote</code></a></li>
<li><a href="#og-module-server">Module <code>server</code></a>
<ul class="sectlevel5">
<li><a href="#og-module-server-http-config">HTTP Configuration Properties</a></li>
<li><a href="#og-module-server-config">Server Configuration Properties</a></li>
<li><a href="#og-module-server-compliance">Server Compliance Properties</a></li>
<li><a href="#og-module-scheduler-config">Server Scheduler Configuration Properties</a></li>
</ul>
</li>
<li><a href="#og-module-ssl">Module <code>ssl</code></a>
<ul class="sectlevel5">
<li><a href="#og-module-ssl-connector">Secure Connector Properties</a></li>
<li><a href="#og-module-ssl-keystore-tls">KeyStore Properties and TLS Properties</a></li>
</ul>
</li>
<li><a href="#og-module-ssl-reload">Module <code>ssl-reload</code></a></li>
<li><a href="#og-module-test-keystore">Module <code>test-keystore</code></a></li>
<li><a href="#og-module-threadpool">Module <code>threadpool</code></a></li>
<li><a href="#og-module-console-capture">Module <code>console-capture</code></a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-deploy">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">Jetty Connectors and Protocols</a>
<ul class="sectlevel3">
<li><a href="#og-protocols-http">Clear-Text HTTP/1.1</a></li>
<li><a href="#og-protocols-https">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">Secure HTTP/2</a></li>
<li><a href="#og-protocols-http2c">Clear-Text HTTP/2</a></li>
<li><a href="#og-protocols-ssl">Configuring Secure Protocols</a>
<ul class="sectlevel4">
<li><a href="#og-protocols-ssl-customize">Customizing KeyStore and SSL/TLS Configuration</a>
<ul class="sectlevel5">
<li><a href="#og-protocols-ssl-customize-versions">Customizing SSL/TLS Protocol Versions</a></li>
<li><a href="#og-protocols-ssl-customize-ciphers">Customizing SSL/TLS Ciphers</a></li>
</ul>
</li>
<li><a href="#og-protocols-ssl-renew">Renewing the Certificates</a></li>
<li><a href="#og-protocols-ssl-reload">Watching and Reloading the KeyStore</a></li>
<li><a href="#og-protocols-ssl-conscrypt">Using Conscrypt as SSL/TLS Provider</a></li>
<li><a href="#og-protocols-ssl-sni">Configuring SNI</a></li>
</ul>
</li>
<li><a href="#og-protocols-proxy">Jetty Behind a Load Balancer or Reverse Proxy</a>
<ul class="sectlevel4">
<li><a href="#og-protocols-proxy-forwarded">Configuring the Forwarded Header</a></li>
<li><a href="#og-protocols-proxy-protocol">Configuring the Proxy Protocol</a></li>
<li><a href="#og-protocols-proxy-haproxy">HAProxy and Jetty with HTTP/1.1 and HTTP/2</a></li>
</ul>
</li>
<li><a href="#og-protocols-websocket">WebSocket</a>
<ul class="sectlevel4">
<li><a href="#og-protocols-websocket-configure">Configuring WebSocket</a></li>
<li><a href="#og-protocols-websocket-disable">Selectively Disabling WebSocket</a></li>
<li><a href="#og-protocols-websocket-webapp-client">Using WebSocket Client in WebApps</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-keystore">Configuring SSL/TLS KeyStores</a>
<ul class="sectlevel3">
<li><a href="#og-keystore-create">Creating a KeyStore</a>
<ul class="sectlevel4">
<li><a href="#og-keystore-create-many">KeyStores with Multiple Entries</a></li>
</ul>
</li>
<li><a href="#og-keystore-csr">Creating a Certificate Signing Request</a></li>
<li><a href="#og-keystore-csr-import">Importing the Signed Certificate</a></li>
<li><a href="#og-keystore-client-authn">Creating a KeyStore for Client Certificate Authentication</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>
<ul class="sectlevel5">
<li><a href="#og-configuration-2">Configuration</a></li>
</ul>
</li>
<li><a href="#og-session-cache-null">No Caching</a>
<ul class="sectlevel5">
<li><a href="#og-configuration-3">Configuration</a></li>
</ul>
</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>
<ul class="sectlevel5">
<li><a href="#og-configuration-7">Configuration</a></li>
</ul>
</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>
<ul class="sectlevel5">
<li><a href="#og-configuration-8">Configuration</a></li>
</ul>
</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>
<ul class="sectlevel5">
<li><a href="#og-configuration-9">Configuration</a></li>
</ul>
</li>
<li><a href="#og-session-hazelcast-embedded">Embedded Hazelcast Clustering</a>
<ul class="sectlevel5">
<li><a href="#og-configuration-10">Configuration</a></li>
</ul>
</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>
<ul class="sectlevel5">
<li><a href="#og-when-running-jetty-outside-of-google-infrastructure">When Running Jetty Outside of Google Infrastructure</a></li>
<li><a href="#og-when-running-jetty-inside-of-google-infrastructure">When Running Jetty Inside of Google Infrastructure</a></li>
</ul>
</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>
<ul class="sectlevel5">
<li><a href="#og-configuration-12">Configuration</a></li>
</ul>
</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-quickstart">Faster Web Application Deployment</a>
<ul class="sectlevel3">
<li><a href="#og-enabling">Enabling</a></li>
</ul>
</li>
<li><a href="#og-annotations">Annotations</a>
<ul class="sectlevel3">
<li><a href="#og-annotations-scanning">Annotation Scanning</a>
<ul class="sectlevel4">
<li><a href="#og-the-container-classpath">The container classpath</a></li>
<li><a href="#og-the-webapp-classpath">The webapp classpath</a></li>
<li><a href="#og-multi-threading">Multi-threading</a></li>
</ul>
</li>
<li><a href="#og-annotations-scis">ServletContainerInitializers</a>
<ul class="sectlevel4">
<li><a href="#og-exclusions">Exclusions</a></li>
<li><a href="#og-ordering">Ordering</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-jsp">Java Server Pages</a>
<ul class="sectlevel3">
<li><a href="#og-configuration-of-the-jsp-servlet">Configuration of the JSP Servlet</a></li>
</ul>
</li>
<li><a href="#og-javaserver-pages-standard-tag-libraries">JavaServer Pages Standard Tag Libraries</a></li>
<li><a href="#og-javaserver-faces-taglibs">JavaServer Faces TagLibs</a></li>
<li><a href="#og-jndi">JNDI</a>
<ul class="sectlevel3">
<li><a href="#og-declaring-resources">Declaring resources</a>
<ul class="sectlevel4">
<li><a href="#og-jndi-env">org.eclipse.jetty.plus.jndi.EnvEntry</a></li>
<li><a href="#og-jndi-resource">org.eclipse.jetty.plus.jndi.Resource</a>
<ul class="sectlevel5">
<li><a href="#og-datasources">DataSources</a></li>
<li><a href="#og-jms-queues-topics-and-connectionfactories">JMS Queues, Topics and ConnectionFactories</a></li>
<li><a href="#og-mail">Mail</a></li>
</ul>
</li>
<li><a href="#og-jndi-tx">org.eclipse.jetty.plus.jndi.Transaction</a></li>
<li><a href="#og-jndi-link">org.eclipse.jetty.plus.jndi.Link</a></li>
<li><a href="#og-jndi-xml">Jetty XML files</a></li>
<li><a href="#og-jndi-scope">Resource scoping</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-jaas">JAAS</a>
<ul class="sectlevel3">
<li><a href="#og-jaas-configuration">Configuration</a>
<ul class="sectlevel4">
<li><a href="#og-jaas-module">The <code>jaas</code> module</a></li>
<li><a href="#og-jaas-webapp">Configure the webapp for JAAS</a></li>
<li><a href="#og-jaas-loginconf">Configure JAAS</a></li>
</ul>
</li>
<li><a href="#og-jaas-loginmodules">Provided LoginModules</a>
<ul class="sectlevel4">
<li><a href="#og-jdbcloginmodule">JDBCLoginModule</a></li>
<li><a href="#og-datasourceloginmodule">DataSourceLoginModule</a></li>
<li><a href="#og-propertyfileloginmodule">PropertyFileLoginModule</a></li>
<li><a href="#og-ldaploginmodule">LdapLoginModule</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-jaspi">JASPI</a>
<ul class="sectlevel3">
<li><a href="#og-jaspi-configuration">Configuration</a>
<ul class="sectlevel4">
<li><a href="#og-jaspi-module">The <code>jaspi</code> module</a></li>
<li><a href="#og-jaspi-xml">Configure JASPI</a>
<ul class="sectlevel5">
<li><a href="#og-jaspi-demo">JASPI Demo</a></li>
</ul>
</li>
<li><a href="#og-integration-with-jetty-authentication-mechanisms">Integration with Jetty Authentication Mechanisms</a></li>
<li><a href="#og-replacing-the-jetty-defaultauthconfigfactory">Replacing the Jetty DefaultAuthConfigFactory</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-jmx">Eclipse Jetty Monitoring &amp; Management</a>
<ul class="sectlevel3">
<li><a href="#og-jmx-local">Enabling Local JMX Support</a></li>
<li><a href="#og-jmx-remote">Enabling Remote JMX Support</a>
<ul class="sectlevel4">
<li><a href="#og-jmx-remote-ssh-tunnel">Remote JMX Access with Port Forwarding via SSH Tunnel</a></li>
<li><a href="#og-jmx-remote-auth">Remote JMX Access Authentication &amp; Authorization</a></li>
<li><a href="#og-jmx-remote-secure">Securing Remote JMX Access with TLS</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-logging">Logging</a>
<ul class="sectlevel3">
<li><a href="#og-logging-server">Server Logging</a>
<ul class="sectlevel4">
<li><a href="#og-logging-server-default">Default Configuration</a>
<ul class="sectlevel5">
<li><a href="#og-logging-server-default-rolling">Capturing Logs to a Rolling File</a></li>
</ul>
</li>
<li><a href="#og-logging-server-custom">Custom Configuration</a>
<ul class="sectlevel5">
<li><a href="#og-logging-server-custom-logback">Logging with LogBack</a></li>
<li><a href="#og-logging-server-custom-log4j2">Logging with Log4J2</a></li>
</ul>
</li>
<li><a href="#og-logging-server-bridges">Bridging Logging to SLF4J</a>
<ul class="sectlevel5">
<li><a href="#og-logging-server-bridge-jul">Bridging <code>java.util.logging</code></a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#og-logging-request">Request Logging</a></li>
</ul>
</li>
<li><a href="#og-troubleshooting">Troubleshooting</a>
<ul class="sectlevel3">
<li><a href="#og-troubleshooting-dump">Server Dump</a>
<ul class="sectlevel4">
<li><a href="#og-troubleshooting-dump-start-stop">Dump at Server Start/Stop</a></li>
<li><a href="#og-troubleshooting-dump-detailed">Detailed ThreadPool Information</a></li>
<li><a href="#og-troubleshooting-dump-example">Dump Example</a></li>
</ul>
</li>
<li><a href="#og-troubleshooting-logging">Enabling DEBUG Logging</a>
<ul class="sectlevel4">
<li><a href="#og-troubleshooting-logging-backend">Jetty Behind a Load Balancer</a></li>
<li><a href="#og-troubleshooting-logging-jmx">Enabling DEBUG Logging for a Short Time</a></li>
<li><a href="#og-troubleshooting-logging-subpackages">Enabling DEBUG Logging for SubPackages</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-begin"><a class="anchor" href="#og-begin"></a><a class="link" href="#og-begin">Getting Started</a></h3>
<div class="paragraph">
<p>If you are new to Eclipse Jetty, read on to download, install, start and deploy web applications to Jetty.</p>
</div>
<div class="sect3">
<h4 id="og-quick-setup"><a class="anchor" href="#og-quick-setup"></a><a class="link" href="#og-quick-setup">Quick 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 a directory called <code>$JETTY_BASE</code>.
There may be more than one <code>$JETTY_BASE</code> directories with different configurations.</p>
</div>
<div class="paragraph">
<p>The following commands can be used to set up 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>The last command creates 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 demo 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 <a href="#og-begin-download">downloading</a>, <a href="#og-begin-install">installing</a> and <a href="#og-begin-start">starting</a> Jetty, and <a href="#og-begin-deploy">deploying</a> your web applications to Jetty.</p>
</div>
<div class="paragraph">
<p>Read the <a href="#og-arch">Jetty architecture section</a> for more information about Jetty modules, <code>$JETTY_HOME</code>, <code>$JETTY_BASE</code> and how to customize and start 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 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 operating 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 Jetty</a></h4>
<div class="paragraph">
<p>After the download, unpacking Eclipse Jetty will extract the files into a directory called <code>jetty-home-VERSION</code>, where <code>VERSION</code> is the version that you downloaded, for example <code>10.0.7</code>, so that the directory is called <code>jetty-home-10.0.7</code>.</p>
</div>
<div class="paragraph">
<p>Unpack Eclipse Jetty compressed file in a convenient location, for example under <code>/opt</code>.</p>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></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, you should read the <a href="#og-arch">Jetty architecture section</a> to become familiar with the terms used in this documentation.
Otherwise, you can jump to the <a href="#og-begin-start">section on starting Jetty</a>.</p>
</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 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-arch">architecture section</a> that Jetty is based on <a href="#og-modules">modules</a>, that provides features, and on <a href="#og-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> from within a <code>$JETTY_BASE</code> directory, so 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</pre>
</div>
</div>
<div class="paragraph">
<p>If you try to start Jetty from an empty <code>$JETTY_BASE</code> you get:</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="CodeRay highlight nowrap"><code>ERROR : No enabled jetty modules found!
INFO : ${jetty.home} = /path/to/jetty.home
INFO : ${jetty.base} = /path/to/jetty.base
ERROR : Please create and/or configure a ${jetty.base} directory.
Usage: java -jar $JETTY_HOME/start.jar [options] [properties] [configs]
java -jar $JETTY_HOME/start.jar --help # for more information</code></pre>
</div>
</div>
<div class="paragraph">
<p>Jetty exited complaining that there are no modules enabled, since the <code>$JETTY_BASE</code> you just created is empty and therefore there is no configuration to read 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">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>Let&#8217;s 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 class="CodeRay highlight nowrap"><code>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</code></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="CodeRay highlight nowrap"><code><strong>2021-10-06 14:47:58.474:</strong>INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17+35
<strong>2021-10-06 14:47:58.526:</strong>INFO :oejs.AbstractConnector:main: Started ServerConnector@2fd05ff<mark>{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}</mark>
<strong>2021-10-06 14:47:58.542:</strong>INFO :oejs.Server:main: Started Server@48524010{STARTING}[10.0.7,sto=5000] @800ms</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="CodeRay 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="CodeRay 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="CodeRay highlight nowrap"><code><strong>2021-10-06 14:47:59.768:</strong>INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17+35
<strong>2021-10-06 14:47:59.820:</strong>INFO :oejs.AbstractConnector:main: Started ServerConnector@65d07359<mark>{HTTP/1.1, (http/1.1)}{0.0.0.0:9999}</mark>
<strong>2021-10-06 14:47:59.835:</strong>INFO :oejs.Server:main: Started Server@48524010{STARTING}[10.0.7,sto=5000] @795ms</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 mechanism, you can read the <a href="#og-arch-start">Jetty start mechanism</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</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 web application 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 *.war Files</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="CodeRay 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 class="CodeRay highlight nowrap"><code>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</code></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 web application 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, and you can use one of the demos shipped with Jetty:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=demo-simple</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
└── demo-simple.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 class="CodeRay highlight nowrap"><code><strong>2021-10-06 14:48:02.593:</strong>INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17+35
<strong>2021-10-06 14:48:02.647:</strong>INFO :oejdp.ScanningAppProvider:main: Deployment monitor [file:///path/to/jetty.base/webapps/]
<strong>2021-10-06 14:48:02.774:</strong>INFO :oejw.StandardDescriptorProcessor:main: NO JSP Support for /demo-simple, did not find org.eclipse.jetty.jsp.JettyJspServlet
<strong>2021-10-06 14:48:02.785:</strong>INFO :oejss.DefaultSessionIdManager:main: Session workerName=node0
<mark><strong>2021-10-06 14:48:02.818:</strong>INFO :oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@610f7aa{Simple Web Application,/demo-simple,file:///path/to/jetty.base/work/jetty-0_0_0_0-8080-demo-simple_war-_demo-simple-any-/webapp/,AVAILABLE}{/path/to/jetty.base/webapps/demo-simple.war}</mark>
<strong>2021-10-06 14:48:02.831:</strong>INFO :oejs.AbstractConnector:main: Started ServerConnector@72aa181d{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
<strong>2021-10-06 14:48:02.849:</strong>INFO :oejs.Server:main: Started Server@10e31a9a{STARTING}[10.0.7,sto=5000] @1099ms</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note the highlighted line that logs the deployment of <code>demo-simple.war</code>.</p>
</div>
<div class="paragraph">
<p>Now you can access the web application by pointing your browser to <code>http://localhost:8080/demo-simple</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-begin-deploy-war-advanced"><a class="anchor" href="#og-begin-deploy-war-advanced"></a><a class="link" href="#og-begin-deploy-war-advanced">Advanced Deployment</a></h5>
<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-arch"><a class="anchor" href="#og-arch"></a><a class="link" href="#og-arch">Architecture Overview</a></h3>
<div class="sect3">
<h4 id="og-arch-concepts"><a class="anchor" href="#og-arch-concepts"></a><a class="link" href="#og-arch-concepts">Main Concepts</a></h4>
<div class="paragraph">
<p>Jetty is an HTTP server and Servlet Container, and supports deployments of web applications.</p>
</div>
<div class="paragraph">
<p>The Jetty <em>server</em> listens on one or more network ports using one or more <em>connector</em>s.</p>
</div>
<div class="paragraph">
<p>Clients send HTTP requests for specific URIs, such as <code>https://host/store/cart</code>.</p>
</div>
<div class="paragraph">
<p>The HTTP requests arrive to the connectors through the network; the Jetty server processes the requests and, based on their URIs, forwards them to the appropriate web application.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/diag-cb8a854642d32c964b17f0a090ef16e3.png" alt="Diagram" width="445" height="430">
</div>
</div>
<div class="paragraph">
<p>There are three main concepts on which the Jetty standalone server is based:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The <a href="#og-arch-modules">Jetty <em>module</em> system</a>, where Jetty modules provides Jetty features.</p>
</li>
<li>
<p>The <a href="#og-arch-jetty-base"><code>$JETTY_BASE</code> directory</a>, that provides a place where you configure which Jetty modules you want to enable, configure the properties of each enabled module, and therefore configure the features you need for your web applications.</p>
</li>
<li>
<p>The <a href="#og-arch-start">Jetty start mechanism</a>, that starts a JVM that runs Jetty with the configuration you specified.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>After installing Jetty, you will want to set up a <a href="#og-arch-jetty-base"><code>$JETTY_BASE</code> directory</a> where you configure <a href="#og-arch-modules">Jetty modules</a>.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-arch-modules"><a class="anchor" href="#og-arch-modules"></a><a class="link" href="#og-arch-modules">Jetty Modules</a></h4>
<div class="paragraph">
<p>The Jetty standalone server is made of Java components that are assembled together, configured and started to provide different features.</p>
</div>
<div class="paragraph">
<p>A Jetty <em>module</em> provides 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.
What you can do in Java code to assemble Jetty components 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 which 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 the corresponding Jetty module(s).</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 a client using 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="sect3">
<h4 id="og-arch-jetty-base"><a class="anchor" href="#og-arch-jetty-base"></a><a class="link" href="#og-arch-jetty-base"><code>$JETTY_HOME</code> and <code>$JETTY_BASE</code></a></h4>
<div class="paragraph">
<p>Instead of managing multiple Jetty distributions out of many 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>.</p>
</div>
<div class="paragraph">
<p>This separation between the binary installation directory and the specific configuration directory allows managing multiple, different, server configurations, and allows for quick, drop-in upgrades of Jetty.</p>
</div>
<div class="paragraph">
<p>There should always only be <strong>one</strong> <code>$JETTY_HOME</code> (per version of Jetty), but there can be many <code>$JETTY_BASE</code> directories that reference it.</p>
</div>
<div class="paragraph">
<p>This separation between <code>$JETTY_HOME</code> and <code>$JETTY_BASE</code> allows Jetty 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 may want that port to be <code>6060</code>, because <a href="#og-protocols-proxy">Jetty is behind a load balancer</a> that is configured to forward to the backend on port <code>6060</code>.
In this case, you configure the clear-text HTTP port in <code>$JETTY_BASE</code>, not in <code>$JETTY_HOME</code>.
When you upgrade Jetty, you will upgrade only the files in <code>$JETTY_HOME</code>, and all the configuration in <code>$JETTY_BASE</code> will remain unchanged, keeping your clear-text HTTP port at <code>6060</code>.</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 changes 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_HOME</code></dt>
<dd>
<p>This is the location for the Jetty binaries.</p>
</dd>
<dt class="hdlist1"><code>$JETTY_BASE</code></dt>
<dd>
<p>This is the location for your configurations and customizations to the Jetty binaries.</p>
</dd>
</dl>
</div>
</div>
<div class="sect3">
<h4 id="og-arch-start"><a class="anchor" href="#og-arch-start"></a><a class="link" href="#og-arch-start">Start Mechanism</a></h4>
<div class="paragraph">
<p>The Jetty start mechanism provides two features:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The mean to configure your <code>$JETTY_BASE</code> by enabling the desired modules, and to display the configuration of your <code>$JETTY_BASE</code>.</p>
</li>
<li>
<p>The mean to start Jetty itself, by starting a JVM that reads the Jetty configuration in <code>$JETTY_BASE</code>, which is then executed to assemble and start the Jetty components.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The Jetty start mechanism is invoked by executing <code>$JETTY_HOME/start.jar</code> from within your <code>$JETTY_BASE</code>, and you can think of it as the Jetty command line program, similar to many Unix/Windows command line programs.</p>
</div>
<div class="paragraph">
<p>For example, you can ask for help:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --help</pre>
</div>
</div>
<div class="paragraph">
<p>Or you can list all available modules (or only those with a specific tag):</p>
</div>
<div class="listingblock">
<div class="content">
<pre># List all the modules.
$ java -jar $JETTY_HOME/start.jar --list-modules=*
# List all the modules tagged as "demo".
$ java -jar $JETTY_HOME/start.jar --list-modules=demo</pre>
</div>
</div>
<div class="paragraph">
<p>You can enable a module, for example the <code>http</code> module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=http</pre>
</div>
</div>
<div class="paragraph">
<p>Once you have one or more module enabled, you can display the current configuration, to verify that the configuration is correct:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --list-config</pre>
</div>
</div>
<div class="paragraph">
<p>You can enable a Jetty demo module, which will deploy a demo web application:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=demo-simple</pre>
</div>
</div>
<div class="paragraph">
<p>Finally, you can start Jetty:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar</pre>
</div>
</div>
<div class="paragraph">
<p>Read more information at the <a href="#og-start">Jetty start mechanism section</a>.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-features"><a class="anchor" href="#og-features"></a><a class="link" href="#og-features">Eclipse Jetty Features</a></h3>
<div class="paragraph">
<p>If you know Eclipse Jetty already, jump to a feature:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Protocols</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p><a href="#og-protocols-http">HTTP/1.1 Support</a></p>
</li>
<li>
<p><a href="#og-protocols-http2">HTTP/2 Support</a></p>
</li>
<li>
<p><a href="#og-protocols-websocket">WebSocket Support</a></p>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1">Technologies</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p><a href="#og-annotations">Servlet Annotations</a></p>
</li>
<li>
<p><a href="#og-jaas">JAAS</a></p>
</li>
<li>
<p><a href="#og-jndi">JNDI</a></p>
</li>
<li>
<p><a href="#og-jsp">JSP</a></p>
</li>
<li>
<p><a href="#og-jmx">JMX Monitoring &amp; Management</a></p>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1">Clustering</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p><a href="#og-sessions">HTTP Session Caching and Clustering</a></p>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1">Performance</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p><a href="#og-quickstart">Faster Web Application Deployment</a></p>
</li>
</ul>
</div>
</dd>
</dl>
</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-howtos"><a class="anchor" href="#og-howtos"></a><a class="link" href="#og-howtos">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>
<li>
<p><a href="#og-protocols-proxy">Configure Jetty Behind a Load Balancer or Reverse Proxy</a></p>
</li>
<li>
<p><a href="#og-logging">Configure Jetty Logging</a></p>
</li>
<li>
<p><a href="#og-troubleshooting">Troubleshooting</a></p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="og-start"><a class="anchor" href="#og-start"></a><a class="link" href="#og-start">Jetty Start Mechanism</a></h3>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Make sure you have read the <a href="#og-arch">Jetty architecture section</a> if you are not familiar with the terms used in this section.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The Jetty start mechanism is invoked by executing <code>$JETTY_HOME/start.jar</code>, from within a <code>$JETTY_BASE</code> directory, with zero or more command line options:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ cd $JETTY_BASE
$ java -jar $JETTY_HOME/start.jar ...</pre>
</div>
</div>
<div class="paragraph">
<p>The Jetty start mechanism has two main modes of operation:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The <em>tool</em> mode, detailed in <a href="#og-start-configure">this section</a>, when it is used as a command line tool to configure the <code>$JETTY_BASE</code> directory by enabling modules, creating sub-directories and files, downloading files, etc.
In this mode, the JVM started with <code>java -jar $JETTY_HOME/start.jar</code> performs the specified command and then exits.</p>
</li>
<li>
<p>The <em>start</em> mode, detailed in <a href="#og-start-start">this section</a>, when it is used to start the JVM that runs Jetty with the specified configuration.
In this mode, the JVM started with <code>java -jar $JETTY_HOME/start.jar</code> starts Jetty and does not exit until stopped, for example by hitting <span class="keyseq"><kbd>Ctrl</kbd>+<kbd>C</kbd></span> on the terminal.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Refer to the <a href="#og-start-reference">Jetty start mechanism reference section</a> for the complete list of the available command line options.</p>
</div>
<div class="paragraph">
<p>You want to use the Jetty start mechanism to <a href="#og-start-configure">configure your $JETTY_BASE</a> and then to <a href="#og-start-start">start Jetty</a>.</p>
</div>
<div class="sect3">
<h4 id="og-start-configure"><a class="anchor" href="#og-start-configure"></a><a class="link" href="#og-start-configure">Configuring $JETTY_BASE</a></h4>
<div class="paragraph">
<p>Within the Jetty start mechanism, the source of configurations is layered in this order, from higher priority to lower priority:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The command line options.</p>
</li>
<li>
<p>The <code>$JETTY_BASE</code> directory, and its files.</p>
</li>
<li>
<p>The directory specified with the <code>--include-jetty-dir</code> option, and its files.</p>
</li>
<li>
<p>The <code>$JETTY_HOME</code> directory, and its files.</p>
</li>
</ul>
</div>
<div class="sect4">
<h5 id="og-start-configure-enable"><a class="anchor" href="#og-start-configure-enable"></a><a class="link" href="#og-start-configure-enable">Enabling Modules</a></h5>
<div class="paragraph">
<p>You can enable Jetty modules with the <code>--add-modules</code> command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=server,http</pre>
</div>
</div>
<div class="paragraph">
<p>The Jetty start mechanism will look for the specified modules following the order specified above.
In the common case (without a <code>--include-jetty-dir</code> directory), it will look in <code>$JETTY_BASE/modules/</code> first and then in <code>$JETTY_HOME/modules/</code>.</p>
</div>
<div class="paragraph">
<p>Since the <code>server</code> and <code>http</code> modules are standard Jetty modules, they are present in <code>$JETTY_HOME/modules/</code> and loaded from there.</p>
</div>
<div class="paragraph">
<p>When you enable a Jetty module, the Jetty start mechanism:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Creates the correspondent <code>$JETTY_BASE/start.d/*.ini</code> module configuration file.
The content of these <code>*.ini</code> files is copied from the <code>[ini-template]</code> section of the correspondent <code>*.mod</code> file.</p>
</li>
<li>
<p>Executes the directives specified in <code>[files]</code> section (if present) of the <code>*.mod</code> file.
This may simply create a file or a directory, or download files from the Internet.
This step is performed transitively for all module dependencies.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For example, enabling the <code>server</code> and <code>http</code> modules results in the <code>$JETTY_BASE</code> directory to have the following structure:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$JETTY_BASE
├── resources
│ └── jetty-logging.properties
└── start.d
├── http.ini
└── server.ini</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>$JETTY_BASE/resources/jetty-logging.properties</code> is created by the <code>[files]</code> directives of the <code>logging-jetty</code> module, which is a transitive dependency of the <code>server</code> module.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-start-configure-disable"><a class="anchor" href="#og-start-configure-disable"></a><a class="link" href="#og-start-configure-disable">Disabling Modules</a></h5>
<div class="paragraph">
<p>A module is enabled because the correspondent <code>$JETTY_BASE/start.d/*.ini</code> file contains a <code>--module=&lt;name&gt;</code> directive.</p>
</div>
<div class="paragraph">
<p>Commenting out the <code>--module=&lt;name&gt;</code> directive effectively disables the module.</p>
</div>
<div class="paragraph">
<p>Deleting the correspondent <code>$JETTY_BASE/start.d/*.ini</code> file also disables the module.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-start-configure-edit-ini"><a class="anchor" href="#og-start-configure-edit-ini"></a><a class="link" href="#og-start-configure-edit-ini">Editing <code>*.ini</code> Files</a></h5>
<div class="paragraph">
<p>You can now edit the <code>$JETTY_BASE/start.d/*.ini</code> configuration files, typically by uncommenting properties to change their default value.</p>
</div>
<div class="paragraph">
<p>The <code>$JETTY_BASE/start.d/*.ini</code> configuration file may be missing, if the correspondent module is a transitive dependency.
You can easily generate the configuration file by explicitly enabling the module, for example to generate the <code>$JETTY_BASE/start.d/logging-jetty.ini</code> configuration file you would issue the following command (the module order does not matter):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=server,http,logging-jetty</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>$JETTY_BASE</code> directory structure is now:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$JETTY_BASE
├── resources
│ └── jetty-logging.properties
└── start.d
├── http.ini
├── <mark>logging-jetty.ini</mark>
└── server.ini</code></pre>
</div>
</div>
<div class="paragraph">
<p>You want to edit the <code>$JETTY_BASE/start.d/*.ini</code> configuration files so that the configuration is applied every time Jetty is started (or re-started).</p>
</div>
<div class="paragraph">
<p>For example, <code>$JETTY_BASE/start.d/http.ini</code> contains the following property, commented out:</p>
</div>
<div class="listingblock">
<div class="title">http.ini</div>
<div class="content">
<pre># jetty.http.port=8080</pre>
</div>
</div>
<div class="paragraph">
<p>You can change the clear-text HTTP port Jetty listens to by uncommenting that property and changing its value:</p>
</div>
<div class="listingblock">
<div class="title">http.ini</div>
<div class="content">
<pre>jetty.http.port=9876</pre>
</div>
</div>
<div class="paragraph">
<p>When Jetty is started (or re-started) this configuration is applied and Jetty will listen for clear-text HTTP/1.1 on port <code>9876</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-start-configure-custom-module"><a class="anchor" href="#og-start-configure-custom-module"></a><a class="link" href="#og-start-configure-custom-module">Adding Your Own Modules</a></h5>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Refer to the <a href="#og-modules-custom">custom module section</a> for the details about how to create your own modules.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>You can add your own modules by adding a <code>$JETTY_BASE/modules/*.mod</code> file.</p>
</div>
<div class="paragraph">
<p>For example, you may want to add a Postgres JDBC driver to the server class-path, to avoid that each deployed web application bring its own version. This allows you to control the exact Postgres JDBC driver version for all web applications.</p>
</div>
<div class="paragraph">
<p>Create the <code>$JETTY_BASE/modules/postgresql.mod</code> file:</p>
</div>
<div class="listingblock">
<div class="title">postgresql.mod</div>
<div class="content">
<pre>[description]
Postgres JDBC Driver Module
[lib]
lib/postgresql-${postgresql-version}.jar
[files]
maven://org.postgresql/postgresql/${postgresql-version}|lib/postgresql-${postgresql-version}.jar
[ini]
postgresql-version?=42.2.18
[ini-template]
## Postgres JDBC version.
# postgresql-version=42.2.18</pre>
</div>
</div>
<div class="paragraph">
<p>Then enable it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=postgresql</pre>
</div>
</div>
<div class="paragraph">
<p>Enabling the <code>postgresql</code> module will execute the <code>[files]</code> directive (downloading the <code>*.jar</code> file from Maven Central if not already present) and create the <code>$JETTY_BASE/start.d/postgresql.ini</code> with the content of the <code>[ini-template]</code> section.</p>
</div>
<div class="paragraph">
<p>The <code>[lib]</code> section ensures that the specified file is in the server class-path when Jetty is started.</p>
</div>
<div class="paragraph">
<p>You can <a href="#og-start-configure-display">display the Jetty configuration</a> to verify that the server class-path is correct.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-start-configure-custom-module-exec"><a class="anchor" href="#og-start-configure-custom-module-exec"></a><a class="link" href="#og-start-configure-custom-module-exec">Custom Module with JVM Options</a></h5>
<div class="paragraph">
<p>Using a custom Jetty module, you can customize the JVM startup options.</p>
</div>
<div class="paragraph">
<p>This is useful if you need to start Jetty and want to specify JVM options such as:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>-Xmx</code>, to specify the max heap size</p>
</li>
<li>
<p><code>-Xlog:gc</code>, to specify the GC log file and options</p>
</li>
<li>
<p><code>-javaagent</code>, to specify Java agents</p>
</li>
<li>
<p><code>-XX:</code> options, for example to specify the GC implementation</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Start by creating <code>$JETTY_BASE/modules/jvm.mod</code>:</p>
</div>
<div class="listingblock">
<div class="title">jvm.mod</div>
<div class="content">
<pre>[description]
JVM Options Module
[exec]
-Xmx1g
-Xlog:gc*,gc+stats=off:file=logs/gc.log:time,level,tags</pre>
</div>
</div>
<div class="paragraph">
<p>Enable it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=jvm</pre>
</div>
</div>
<div class="paragraph">
<p>Since the module defines an <code>[exec]</code> section, it will fork <em>another</em> JVM when Jetty is started.</p>
</div>
<div class="paragraph">
<p>This means that when you start Jetty, there will be <em>two</em> JVMs running: one created by you when you run <code>java -jar $JETTY_HOME/start.jar</code>, and another forked by the Jetty start mechanism with the JVM options you specified (that cannot be applied to an already running JVM).</p>
</div>
<div class="paragraph">
<p>Again, you can <a href="#og-start-configure-dry-run">display the JVM command line</a> to verify that it is correct.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The second JVM forked by the Jetty start mechanism when one of the modules requires forking, for example a module that contains an <code>[exec]</code> section, may not be desirable, and may be avoided as explained in <a href="#og-start-configure-dry-run">this section</a>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="og-start-configure-display"><a class="anchor" href="#og-start-configure-display"></a><a class="link" href="#og-start-configure-display">Displaying the Configuration</a></h5>
<div class="paragraph">
<p>Once you have enabled and configured the <code>$JETTY_BASE</code>, you can display the configuration to verify that it is correct.</p>
</div>
<div class="paragraph">
<p>Using the standard <code>server</code> and <code>http</code> Jetty modules, and the <code>postgresql</code> and <code>jvm</code> custom Jetty module defined above, you obtain:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --list-config</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>Enabled Modules:
----------------
0) resources transitive provider of resources for logging-jetty
1) logging/slf4j transitive provider of logging/slf4j for logging-jetty
dynamic dependency of logging-jetty
2) logging-jetty transitive provider of logging for threadpool
transitive provider of logging for bytebufferpool
transitive provider of logging for server
3) bytebufferpool transitive provider of bytebufferpool for server
init template available with --add-module=bytebufferpool
4) threadpool transitive provider of threadpool for server
init template available with --add-module=threadpool
5) jvm ${jetty.base}/start.d/jvm.ini
6) server ${jetty.base}/start.d/server.ini
7) http ${jetty.base}/start.d/http.ini
8) postgresql ${jetty.base}/start.d/postgresql.ini
Java Environment:
-----------------
java.home = /path/to/java.home (null)
java.vm.vendor = Eclipse Adoptium (null)
java.vm.version = 17+35 (null)
java.vm.name = OpenJDK 64-Bit Server VM (null)
java.vm.info = mixed mode, sharing (null)
java.runtime.name = OpenJDK Runtime Environment (null)
java.runtime.version = 17+35 (null)
java.io.tmpdir = /path/to/jetty.base/work (null)
user.dir = /path/to/jetty.base (null)
user.language = en (null)
user.country = US (null)
Jetty Environment:
------------------
jetty.version = 10.0.7
jetty.tag.version = jetty-10.0.7
jetty.build = da8a4553af9dd84080931fa0f8c678cd2d60f3d9
jetty.home = /path/to/jetty.home
jetty.base = /path/to/jetty.base
Config Search Order:
--------------------
&lt;command-line&gt;
${jetty.base} -&gt; /path/to/jetty.base
${jetty.home} -&gt; /path/to/jetty.home
Forked JVM Arguments:
---------------------
-Xmx1g
-Xlog:gc*,gc+stats=off:file=logs/gc.log:time,level,tags
System Properties:
------------------
(no system properties specified)
Properties:
-----------
java.version = 17
java.version.major = 17
java.version.micro = 0
java.version.minor = 0
java.version.platform = 17
jetty.base = /path/to/jetty.base
jetty.base.uri = file:///path/to/jetty.base
jetty.home = /path/to/jetty.home
jetty.home.uri = file:///path/to/jetty.home
jetty.webapp.addServerClasses = org.eclipse.jetty.logging.,${jetty.home.uri}/lib/logging/,org.slf4j.
postgresql-version = 42.2.18
runtime.feature.alpn = true
slf4j.version = 2.0.0-alpha5
Jetty Server Classpath:
-----------------------
Version Information on 10 entries in the classpath.
Note: order presented here is how they would appear on the classpath.
changes to the --module=name command line options will be reflected here.
0: (dir) | ${jetty.base}/resources
1: 2.0.0-alpha5 | ${jetty.home}/lib/logging/slf4j-api-2.0.0-alpha5.jar
2: 10.0.7 | ${jetty.home}/lib/logging/jetty-slf4j-impl-10.0.7.jar
3: 4.0.6 | ${jetty.home}/lib/jetty-servlet-api-4.0.6.jar
4: 10.0.7 | ${jetty.home}/lib/jetty-http-10.0.7.jar
5: 10.0.7 | ${jetty.home}/lib/jetty-server-10.0.7.jar
6: 10.0.7 | ${jetty.home}/lib/jetty-xml-10.0.7.jar
7: 10.0.7 | ${jetty.home}/lib/jetty-util-10.0.7.jar
8: 10.0.7 | ${jetty.home}/lib/jetty-io-10.0.7.jar
9: 42.2.18 | ${jetty.base}/lib/postgresql-42.2.18.jar
Jetty Active XMLs:
------------------
${jetty.home}/etc/jetty-bytebufferpool.xml
${jetty.home}/etc/jetty-threadpool.xml
${jetty.home}/etc/jetty.xml
${jetty.home}/etc/jetty-http.xml</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how the configuration displayed above includes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>In the list of enabled modules, the <code>postgresql</code> and <code>jvm</code> modules</p>
</li>
<li>
<p>In the list of JVM arguments, those specified by the <code>jvm</code> module</p>
</li>
<li>
<p>In the server class-path, the <code>*.jar</code> file specified by the <code>postgresql</code> module</p>
</li>
</ul>
</div>
</div>
<div class="sect4">
<h5 id="og-start-configure-dry-run"><a class="anchor" href="#og-start-configure-dry-run"></a><a class="link" href="#og-start-configure-dry-run">Displaying the JVM Command Line</a></h5>
<div class="paragraph">
<p>The Jetty start mechanism can display a full JVM command line that will start Jetty with the configuration you specified, with the <code>--dry-run</code> option:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --dry-run</pre>
</div>
</div>
<div class="paragraph">
<p>The full JVM command line generated by <code>--dry-run</code> can be split in various parts that can be used individually, for example in scripts.</p>
</div>
<div class="paragraph">
<p>Furthermore, Jetty modules may specify the <code>--exec</code> option that will fork a second JVM to start Jetty, which may not be desirable.
Some option, such as <code>--jpms</code>, imply <code>--exec</code>, as it won&#8217;t be possible to modify the module-path in the already started JVM.</p>
</div>
<div class="paragraph">
<p>To start Jetty without forking a second JVM, the <code>--dry-run</code> option can be used to generate a command line that is then executed so that starting Jetty only spawns one JVM.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
You can use the <code>--dry-run</code> option as explained below to avoid forking a second JVM when using modules that have the <code>[exec]</code> section, or the <code>--exec</code> option, or when using the <code>--jpms</code> option.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>For example, using the <code>--dry-run</code> option with the <code>jvm.mod</code> introduced in <a href="#og-start-configure-custom-module-exec">this section</a> produces the following command line:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --dry-run</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>/path/to/java.home/bin/java \
-Djava.io.tmpdir=/path/to/jetty.base/work \
-Djetty.home=/path/to/jetty.home \
-Djetty.base=/path/to/jetty.base \
-Xmx1g \
-Xlog:gc*,gc+stats=off:file=logs/gc.log:time,level,tags \
--class-path \
/path/to/jetty.base/resources:/path/to/jetty.home/lib/logging/slf4j-api-2.0.0-alpha5.jar:/path/to/jetty.home/lib/logging/jetty-slf4j-impl-10.0.7.jar:/path/to/jetty.home/lib/jetty-servlet-api-4.0.6.jar:/path/to/jetty.home/lib/jetty-http-10.0.7.jar:/path/to/jetty.home/lib/jetty-server-10.0.7.jar:/path/to/jetty.home/lib/jetty-xml-10.0.7.jar:/path/to/jetty.home/lib/jetty-util-10.0.7.jar:/path/to/jetty.home/lib/jetty-io-10.0.7.jar \
org.eclipse.jetty.xml.XmlConfiguration \
java.version=17 \
java.version.major=17 \
java.version.micro=0 \
java.version.minor=0 \
java.version.platform=17 \
jetty.base=/path/to/jetty.base \
jetty.base.uri=file:///path/to/jetty.base \
jetty.home=/path/to/jetty.home \
jetty.home.uri=file:///path/to/jetty.home \
jetty.webapp.addServerClasses=org.eclipse.jetty.logging.,${jetty.home.uri}/lib/logging/,org.slf4j. \
runtime.feature.alpn=true \
slf4j.version=2.0.0-alpha5 \
/path/to/jetty.home/etc/jetty-bytebufferpool.xml \
/path/to/jetty.home/etc/jetty-threadpool.xml \
/path/to/jetty.home/etc/jetty.xml \
/path/to/jetty.home/etc/jetty-http.xml</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can then run the generated command line.</p>
</div>
<div class="paragraph">
<p>For example, in the Linux <code>bash</code> shell you can run it by wrapping it into <code>$(...)</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ $(java -jar $JETTY_HOME/start.jar --dry-run)</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>--dry-run</code> option is quite flexible and below you can find a few examples of how to use it to avoid forking a second JVM, or generating scripts or creating an arguments file that can be passed to (a possibly alternative) <code>java</code> executable.</p>
</div>
<div class="paragraph">
<p>To display the <code>java</code> executable used to start Jetty:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar --dry-run=<mark>java</mark></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>/path/to/java.home/bin/java</code></pre>
</div>
</div>
<div class="paragraph">
<p>To display the JVM options:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar --dry-run=<mark>opts</mark></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>-Djava.io.tmpdir=/path/to/jetty.base/work \
-Djetty.home=/path/to/jetty.home \
-Djetty.base=/path/to/jetty.base \
-Xmx1g \
-Xlog:gc*,gc+stats=off:file=logs/gc.log:time,level,tags</code></pre>
</div>
</div>
<div class="paragraph">
<p>To display the JVM class-path:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar --dry-run=<mark>path</mark></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>--class-path \
/path/to/jetty.base/resources:\
/path/to/jetty.home/lib/logging/slf4j-api-2.0.0-alpha5.jar:\
/path/to/jetty.home/lib/logging/jetty-slf4j-impl-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-servlet-api-4.0.6.jar:\
/path/to/jetty.home/lib/jetty-http-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-server-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-xml-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-util-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-io-10.0.7.jar</code></pre>
</div>
</div>
<div class="paragraph">
<p>To display the JVM class-path and module-path, if you want to <a href="#og-start-start-jpms">start Jetty using JPMS</a> with the <code>--jpms</code> option:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar <mark>--jpms</mark> --dry-run=<mark>path</mark></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>--module-path \
/path/to/jetty.home/lib/logging/slf4j-api-2.0.0-alpha5.jar:\
/path/to/jetty.home/lib/logging/jetty-slf4j-impl-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-servlet-api-4.0.6.jar:\
/path/to/jetty.home/lib/jetty-http-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-server-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-xml-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-util-10.0.7.jar:\
/path/to/jetty.home/lib/jetty-io-10.0.7.jar \
--class-path \
/path/to/jetty.base/resources \
--add-modules \
ALL-MODULE-PATH</code></pre>
</div>
</div>
<div class="paragraph">
<p>To display the JVM main class:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar --dry-run=<mark>main</mark></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>org.eclipse.jetty.xml.XmlConfiguration</code></pre>
</div>
</div>
<div class="paragraph">
<p>To display the JVM main class when <a href="#og-start-start-jpms">starting Jetty using JPMS</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar --jpms --dry-run=<mark>main</mark></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>--module org.eclipse.jetty.xml/org.eclipse.jetty.xml.XmlConfiguration</code></pre>
</div>
</div>
<div class="paragraph">
<p>The main class is typically Jetty&#8217;s <code>XmlConfiguration</code> class that accepts, as program arguments, a list of properties and a list of Jetty XML files to process.
The Jetty XML files compose together the Jetty components that are then configured with the values from the command line properties.</p>
</div>
<div class="paragraph">
<p>To display the program arguments passed to the main class:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar --dry-run=<mark>args</mark></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>java.version=17 \
java.version.major=17 \
java.version.micro=0 \
java.version.minor=0 \
java.version.platform=17 \
jetty.base=/path/to/jetty.base \
jetty.base.uri=file:///path/to/jetty.base \
jetty.home=/path/to/jetty.home \
jetty.home.uri=file:///path/to/jetty.home \
jetty.webapp.addServerClasses=org.eclipse.jetty.logging.,${jetty.home.uri}/lib/logging/,org.slf4j. \
runtime.feature.alpn=true \
slf4j.version=2.0.0-alpha5 \
/path/to/jetty.home/etc/jetty-bytebufferpool.xml \
/path/to/jetty.home/etc/jetty-threadpool.xml \
/path/to/jetty.home/etc/jetty.xml \
/path/to/jetty.home/etc/jetty-http.xml</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how the program arguments are a list of properties in the form <code>&lt;name&gt;=&lt;value&gt;</code> and a list of Jetty XML files.</p>
</div>
<div class="paragraph">
<p>The various parts of the full JVM command line can be combined to leverage the arguments file feature (that is, specify the JVM options in a file rather than on the command line) that is built-in in the <code>java</code> executable:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar --dry-run=<mark>opts,path,main,args</mark> > /tmp/jvm_cmd_line.txt
$ /some/other/java @/tmp/jvm_cmd_line.txt</code></pre>
</div>
</div>
<div class="paragraph">
<p>Using <code>--dry-run=opts,path,main,args</code> can be used to avoid that the Jetty start mechanism forks a second JVM when using modules that require forking:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java $(java -jar $JETTY_HOME/start.jar --dry-run=opts,path,main,args)</pre>
</div>
</div>
<div class="paragraph">
<p>The output of different <code>--dry-run</code> executions can be creatively combined in a shell script:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ OPTS=$(java -jar start.jar --dry-run=<mark>opts,path</mark>)
$ MAIN=$(java -jar start.jar --dry-run=<mark>main</mark>)
$ ARGS=$(java -jar start.jar --dry-run=<mark>args</mark>)
$ java $OPTS -Dextra=opt $MAIN $ARGS extraProp=value extra.xml</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-start-start"><a class="anchor" href="#og-start-start"></a><a class="link" href="#og-start-start">Starting Jetty</a></h4>
<div class="paragraph">
<p>After you have configured the <code>$JETTY_BASE</code> directory, as explained in <a href="#og-start-configure">this section</a>, you can start Jetty as a standalone server.</p>
</div>
<div class="paragraph">
<p>In the <em>start</em> mode, the Jetty start mechanism computes a JVM command line with JVM options, system properties, class-path, module-path, main class and program arguments, and then executes it, forking a new JVM if necessary.</p>
</div>
<div class="paragraph">
<p>The Jetty start mechanism performs these steps:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Loads all the Jetty modules files (that have extension <code>*.mod</code>) from the <code>modules/</code> subdirectory of each configuration source directory (see <a href="#og-start-configure">this section</a> for the list of configuration sources).
In this way, a Jetty module graph can be built in memory, where the module dependencies form the edges of the graph and each node contains the metadata information declared by each module (for example, the libraries that it needs, the XML files to process, and so on), in preparation for the next step.</p>
</li>
<li>
<p>Reads the Jetty module configuration files (that have extension <code>*.ini</code>) from the <code>start.d/</code> subdirectory of each configuration source directory and from the command line.
This step produces a list of <em>enabled</em> modules; for each enabled module all its dependencies are transitively resolved by navigating the graph built in the previous steps.</p>
</li>
<li>
<p>Processes the list of enabled (explicitly and transitively) modules, gathering the list of libraries to add to the class-path, the JPMS directives to add to the command line, the properties and XML files to add as program arguments, etc., so that a full JVM command line can be generated.</p>
</li>
<li>
<p>Executes the command line, either in-JVM or by forking a second JVM (if the <code>--exec</code> option is present or implied by other options such as <code>--jpms</code>), and waits for the JVM, or the forked JVM, to exit.</p>
</li>
</ol>
</div>
<div class="sect4">
<h5 id="og-start-start-class-path"><a class="anchor" href="#og-start-start-class-path"></a><a class="link" href="#og-start-start-class-path">Server Class-Path</a></h5>
<div class="paragraph">
<p>When the Jetty server is started in-JVM, the server class-path gathered by processing the enabled modules is organized in a <code>URLClassLoader</code>, the Jetty Start ClassLoader, that is a child of the System ClassLoader:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/diag-0f37d1d5b12f280e1587df6f3d528998.png" alt="Diagram" width="351" height="245">
</div>
</div>
<div class="paragraph">
<p>The System ClassLoader only has <code>$JETTY_HOME/start.jar</code> in its class-path, since the JVM was started with <code>java -jar $JETTY_HOME/start.jar</code>.
The Jetty Start ClassLoader has in its class-path the <code>*.jar</code> files gathered by processing the enabled modules, typically from <code>$JETTY_HOME/lib/jetty-*.jar</code>, but possibly also from <code>$JETTY_BASE/lib/*.jar</code> if custom modules extend the server class-path with their own <code>*.jar</code> files.</p>
</div>
<div class="paragraph">
<p>When the Jetty server is started in a forked JVM, there will be two JVMs: one started by you with <code>java -jar $JETTY_HOME/start.jar</code> and one forked by the Jetty start mechanism.
In the forked JVM, the System ClassLoader has the server class-path and/or module-path in its class-path, since the forked JVM is started with <code>java --class-path $JETTY_HOME/lib/jetty-server-&lt;version&gt;.jar:...</code>:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/diag-176305f848d18dc8b0c4ef7bd331705d.png" alt="Diagram" width="374" height="267">
</div>
</div>
<div class="paragraph">
<p>It is worth mentioning that there are two standard Jetty modules that allow you to easily add entries to the Jetty server class-path:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The <code>resources</code> module, that adds the <code>$JETTY_BASE/resources/</code> directory to the server class-path.
This is useful if you have third party libraries that lookup resources from the class-path: just put those resources in the <code>$JETTY_BASE/resources/</code> directory.<br>
Logging libraries often perform class-path lookup of their configuration files (for example, <code>log4j.properties</code>, <code>log4j.xml</code>, <code>logging.properties</code>, and <code>logback.xml</code>), so <code>$JETTY_BASE/resources/</code> is the ideal place to add those files.<br></p>
</li>
<li>
<p>The the <code>ext</code> module, that adds all the <code>*.jar</code> files under the <code>$JETTY_BASE/lib/ext/</code> directory, and subdirectories recursively, to the server class-path.<br></p>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
<div class="paragraph">
<p>On one hand, the <code>ext</code> module provides a handy place to put third party libraries and their dependencies; on the other hand, the <code>$JETTY_BASE/lib/ext/</code> directory may become a confused mixture of many <code>*.jar</code> files from different third party libraries.</p>
</div>
<div class="paragraph">
<p>Prefer to group third party libraries and their dependencies into their own directories using <a href="#og-modules-custom">custom modules</a>, or at least group them into <code>$JETTY_BASE/lib/ext/</code> subdirectories such as <code>$JETTY_BASE/lib/ext/util/</code> or <code>$JETTY_BASE/lib/ext/acme/</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</li>
</ul>
</div>
</div>
<div class="sect4">
<h5 id="og-start-start-xml"><a class="anchor" href="#og-start-start-xml"></a><a class="link" href="#og-start-start-xml">Assembling Jetty Components</a></h5>
<div class="paragraph">
<p>The Jetty start mechanism eventually invokes, by default, main class <code>org.eclipse.jetty.xml.XmlConfiguration</code>, passing properties and <a href="#og-xml">Jetty XML files</a> as program arguments.</p>
</div>
<div class="paragraph">
<p>The Jetty XML files are nothing more than Java code in XML format.</p>
</div>
<div class="paragraph">
<p>The XML files are processed to instantiate Jetty components such as <code>org.eclipse.jetty.server.Server</code> or <code>org.eclipse.jetty.util.ssl.SslContextFactory</code>.
The components are then assembled together to provide the configured Jetty features.</p>
</div>
<div class="paragraph">
<p>The Jetty XML files are parametrized using properties; a property is just a name/value pair.</p>
</div>
<div class="paragraph">
<p>This parametrization of the XML files allows an XML file that resides in <code>$JETTY_HOME/etc/</code> to <em>declare</em> a property such as <code>jetty.http.port</code>, and allow this property to be set in a <code>$JETTY_BASE/start.d/http.ini</code> file, so that you don&#8217;t need to change the XML files in <code>$JETTY_HOME</code>, but only change files in your <code>$JETTY_BASE</code>.</p>
</div>
<div class="paragraph">
<p>You can write your own <a href="#og-modules-custom">custom modules</a> with your own Jetty XML files, and your own properties, to further customize Jetty.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-start-start-jpms"><a class="anchor" href="#og-start-start-jpms"></a><a class="link" href="#og-start-start-jpms">Starting Jetty using JPMS</a></h4>
<div class="paragraph">
<p>Jetty modules are proper <a href="https://en.wikipedia.org/wiki/Java_Platform_Module_System">JPMS</a> modules: each Jetty module has a <code>module-info.class</code> file.
This makes possible to run Jetty from the module-path, rather than the class-path.</p>
</div>
<div class="paragraph">
<p>To start Jetty on the module-path rather than the class-path, it is enough to add the <code>--jpms</code> option to the command line, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --jpms</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>The <code>--jpms</code> option implies the <code>--exec</code> option.</p>
</div>
<div class="paragraph">
<p>When running on the module-path using the <code>--jpms</code> option, the Jetty start mechanism will fork a second JVM passing it the right JVM options to run on the module-path.</p>
</div>
<div class="paragraph">
<p>Therefore, you will have two JVMs running: one that runs <code>start.jar</code> and one that runs Jetty on the module-path.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>When Jetty is started in JPMS mode, all JPMS modules in the module-path are added to the set of JPMS <em>root modules</em> through the JVM option <code>--add-modules ALL_MODULE_PATH</code>.</p>
</div>
<div class="paragraph">
<p>For a <code>*.jar</code> file that is not a JPMS module, but is on the module-path, the JVM will assume internally it is an automatic JPMS module, with a JPMS module name derived from the <code>*.jar</code> file name.</p>
</div>
<div class="paragraph">
<p>Rather than adding the <code>--jpms</code> option to the command line, you can use a custom Jetty module to centralize your JPMS configuration, where you can specify additional JPMS directives.</p>
</div>
<div class="paragraph">
<p>Create the <code>$JETTY_BASE/modules/jpms.mod</code> file:</p>
</div>
<div class="listingblock">
<div class="title">jpms.mod</div>
<div class="content">
<pre>[description]
JPMS Configuration Module
[ini]
--jpms
[jpms]
# Additional JPMS configuration.</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>[ini]</code> section with <code>--jpms</code> is equivalent to passing the <code>--jpms</code> option to the command line (see also <a href="#og-modules-directive-ini">this section</a>).</p>
</div>
<div class="paragraph">
<p>The <code>[jpms]</code> section allows you to specify additional JPMS configuration, for example additional <code>--add-modules</code> options, or <code>--add-opens</code> options, etc. (see also <a href="#og-modules-directive-jpms">this section</a>).</p>
</div>
<div class="paragraph">
<p>Then enable it:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=jpms</pre>
</div>
</div>
<div class="paragraph">
<p>Now you can start Jetty without extra command line options, and it will start in JPMS mode because you have enabled the <code>jpms</code> module.</p>
</div>
<div class="sect4">
<h5 id="og-start-start-jpms-advanced"><a class="anchor" href="#og-start-start-jpms-advanced"></a><a class="link" href="#og-start-start-jpms-advanced">Advanced JPMS Configuration</a></h5>
<div class="paragraph">
<p>Web applications may need additional services from the Servlet Container, such as JDBC <code>DataSource</code> references or JTA <code>UserTransaction</code> references.</p>
</div>
<div class="paragraph">
<p>For example, for JDBC it is typical to store, in JNDI, a reference to the connection pool&#8217;s <code>DataSource</code> or directly a reference to the JDBC driver&#8217;s <code>DataSource</code> (for example, <code>org.postgresql.ds.PGConnectionPoolDataSource</code>).
Jetty needs to be able to instantiate those classes and therefore needs to be able to load those classes and all their super-classes, among which includes <code>javax.sql.DataSource</code>.</p>
</div>
<div class="paragraph">
<p>When Jetty runs on the class-path, this is easily achieved by using a <a href="#og-modules-custom">custom module</a> as explained in <a href="#og-start-configure-custom-module">this section</a>.</p>
</div>
<div class="paragraph">
<p>However, when running on the module-path, things are quite different.</p>
</div>
<div class="paragraph">
<p>When Jetty tries to load, for example, class <code>org.postgresql.ds.PGConnectionPoolDataSource</code>, it must be in a JPMS module that is resolved in the run-time module graph.
Furthermore, any dependency, for example classes from the <code>java.sql</code> JPMS module, must also be in a module present in the resolved module graph.</p>
</div>
<div class="paragraph">
<p>Thanks to the fact that when Jetty starts in JPMS mode the <code>--add-modules ALL_MODULE_PATH</code> option is added to the JVM command line, every <code>*.jar</code> file in the module-path is also present in the module graph.</p>
</div>
<div class="paragraph">
<p>There are now two cases for the <code>postgresql-&lt;version&gt;.jar</code> file: either it is a proper JPMS module, or it is an automatic JPMS module (either an explicit automatic JPMS module with the <code>Automatic-Module-Name</code> attribute in the manifest, or an implicit automatic JPMS module whose name is derived from the <code>*.jar</code> file name).</p>
</div>
<div class="paragraph">
<p>If the <code>postgresql-&lt;version&gt;.jar</code> file is a proper JPMS module, then there is nothing more that you should do: the <code>postgresql-&lt;version&gt;.jar</code> file is in the module-path, and all the modules in the module-path are in the module graph, and any dependency declared in the <code>module-info.class</code> will be added to the module graph.</p>
</div>
<div class="paragraph">
<p>Otherwise, <code>postgresql-&lt;version&gt;.jar</code> file is an automatic module, and will likely have a dependency on the JDK-bundled <code>java.sql</code> JPMS module.
However, the <code>java.sql</code> JPMS module is not in the module graph, because automatic modules do not have a way to declare their dependencies.</p>
</div>
<div class="paragraph">
<p>For this reason, you have to manually add the <code>java.sql</code> dependency to the module graph.
Using the <code>postgresql.mod</code> introduced in <a href="#og-start-configure-custom-module">this section</a> as an example, modify your custom module in the following way:</p>
</div>
<div class="listingblock">
<div class="title">postgresql.mod</div>
<div class="content">
<pre>...
[jpms]
add-modules: java.sql</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>[jpms]</code> section is only used when Jetty is started on the module-path.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-start-stop"><a class="anchor" href="#og-start-stop"></a><a class="link" href="#og-start-stop">Stopping Jetty</a></h4>
<div class="paragraph">
<p>When Jetty is started, the Jetty components that you have configured by enabling Jetty modules are assembled and started.</p>
</div>
<div class="paragraph">
<p>If you have started Jetty from a terminal, you can exit the Jetty JVM by hitting <span class="keyseq"><kbd>Ctrl</kbd>+<kbd>C</kbd></span> on the same terminal.</p>
</div>
<div class="paragraph">
<p>Similarly, from a different terminal, you can exit the Jetty JVM using <code>kill -INT &lt;pid&gt;</code> or <code>kill -TERM &lt;pid&gt;</code>.</p>
</div>
<div class="paragraph">
<p>In the three cases above, the JVM is exited, but by default Jetty components are not stopped.
If you want to stop the Jetty components, to stop Jetty more gracefully, you can start Jetty with this property:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar <mark>jetty.server.stopAtShutdown=true</mark></code></pre>
</div>
</div>
<div class="paragraph">
<p>This property can also be set in <code>$JETTY_BASE/start.d/server.ini</code> so that it is persistently configured across Jetty restarts (see also <a href="#og-module-server">the <code>server</code> module</a>).</p>
</div>
<div class="paragraph">
<p>The <code>jetty.server.stopAtShutdown</code> property configures a JVM shutdown hook that is run, stopping the <code>Server</code> instance, when the JVM exits.</p>
</div>
<div class="paragraph">
<p>Obviously, the JVM can also be stopped with <code>kill -KILL &lt;pid&gt;</code> that exits the process abruptly without running the JVM shutdown hooks.</p>
</div>
<div class="sect4">
<h5 id="og-start-stop-remote"><a class="anchor" href="#og-start-stop-remote"></a><a class="link" href="#og-start-stop-remote">Stopping Jetty from Remote</a></h5>
<div class="paragraph">
<p>You can configure a Jetty server so that it can be stopped by remote clients using a command sent through a TCP socket.</p>
</div>
<div class="paragraph">
<p>You can start Jetty with the following properties:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>stop.host</code>, the host name Jetty will bind to listen for stop commands. Defaults to <code>127.0.0.1</code> which means that the stop command can be issued only clients that run on the same host as Jetty.</p>
</li>
<li>
<p><code>stop.port</code>, the port number Jetty will listen to for stop commands. Defaults to <code>-1</code>, which means that Jetty will not listen to any port.</p>
</li>
<li>
<p><code>stop.key</code>, the password to verify when a stop command is received. Defaults to a password that is randomly generated and printed when Jetty starts.</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar <mark>stop.port=8181</mark></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code><mark>STOP.KEY=2wb4vri7f2o0</mark>
<strong>2021-10-06 14:48:18.126:</strong>INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17+35
<strong>2021-10-06 14:48:18.168:</strong>INFO :oejs.AbstractConnector:main: Started ServerConnector@bef2d72{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
<strong>2021-10-06 14:48:18.180:</strong>INFO :oejs.Server:main: Started Server@6295d394{STARTING}[10.0.7,sto=5000] @823ms</code></pre>
</div>
</div>
<div class="paragraph">
<p>In the example above, Jetty is started with just the <code>stop.port</code> property, and the <code>stop.key</code> is printed on the terminal when Jetty starts.</p>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
You can choose your own <code>stop.key</code>, but make sure it&#8217;s a strong password.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>A remote client can now use the Jetty start mechanism to stop the remote Jetty server:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar <mark>--stop</mark> stop.port=8181 stop.key=&lt;stop.key&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note the <code>--stop</code> command along with the <code>stop.port</code> and <code>stop.key</code> properties.
The <code>stop.key</code> must be the same as the one of remote Jetty server, either the one you chose, or the one printed on the terminal when Jetty starts.</p>
</div>
<div class="paragraph">
<p>Remote clients can wait for the remote Jetty server to shut down by specifying the <code>stop.wait</code> property with the number of seconds to wait:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --stop stop.port=8181 stop.key=&lt;stop.key&gt; stop.wait=15</pre>
</div>
</div>
<div class="paragraph">
<p>If the time specified elapses, without the confirmation that the remote Jetty server stopped, then the <code>--stop</code> command exits with a non-zero return code.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-start-mechanism-logging"><a class="anchor" href="#og-start-mechanism-logging"></a><a class="link" href="#og-start-mechanism-logging">Start Mechanism Logging</a></h4>
<div class="paragraph">
<p>The steps performed by the Jetty start mechanism are logged by the <code>StartLog</code> class, that outputs directly, by default, to <code>System.err</code>.</p>
</div>
<div class="paragraph">
<p>This is necessary to avoid that the Jetty start mechanism depend on logging libraries that may clash with those defined by Jetty logging modules, when Jetty is started in-VM.</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>This section is about the logging performed by the Jetty start mechanism <em>before</em> it configures and starts Jetty.
See the <a href="#og-logging">logging section</a> for information about logging when Jetty starts.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>You can enable DEBUG level logging with the <code>--debug</code> command line option, for both the <em>tool</em> and <em>start</em> modes:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --debug ...</pre>
</div>
</div>
<div class="paragraph">
<p>You can send the start log output to a file, by default relative to <code>$JETTY_BASE</code>, with the <code>--start-log-file=&lt;file&gt;</code> option:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --debug --start-log-file=start.log ...</pre>
</div>
</div>
<div class="paragraph">
<p>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>
</div>
</div>
<div class="sect3">
<h4 id="og-start-reference"><a class="anchor" href="#og-start-reference"></a><a class="link" href="#og-start-reference">Usage Reference</a></h4>
<div class="listingblock">
<div class="content">
<pre>Usage:
$ java -jar $JETTY_HOME/start.jar [command] [options...]
Commands can be of two types: report commands or configuration commands.
Commands execute and then exit the JVM.
Options can be specified with or without commands.
When no command is specified, Jetty is started with the given options.
Report Commands:
----------------
--help
Prints this help / usage information.
--version
Prints the version information for Jetty and
dependent jars, then exits.
--list-classpath
Prints the class-path (or module-path) information that
will be used to start Jetty.
--list-config
Lists the resolved configuration that will be used to
start Jetty.
Output includes:
o Enabled Jetty modules
o Java environment
o Jetty environment
o Config file search order
o JVM arguments
o System properties
o Properties
o Java class-path or module-path
o XML configuration files
--list-modules
Lists the modules defined in ${jetty.base}/modules/*.mod
and then in ${jetty.home}/modules/*.mod.
--list-modules=&lt;tag&gt;(,&lt;tag&gt;)*
Lists the modules by tag. Use '*' for all tags.
Prefix a tag with '-' to exclude the tag.
The special tag "internal" is always excluded unless it is
explicitly included.
--list-all-modules
Lists all modules.
--show-modules=&lt;module&gt;(,&lt;module&gt;)*
Shows the detail of the listed modules, including
dependencies, tags, libraries and XMLs.
--stop
Sends a stop signal to the running Jetty instance.
The running Jetty instance must have been started with a
stop.port=&lt;port&gt; property and the --stop command must
be executed with the same property.
--dry-run
Prints the command line that start.jar generates,
then exits.
This may be used to generate command lines into scripts:
$ java -jar start.jar --dry-run &gt; jetty.sh
--dry-run=&lt;part&gt;(,&lt;part&gt;)*
Prints specific parts of the command line. The parts are:
o "java" - the JVM to run
o "opts" - the JVM options (e.g. -D, -X and -XX flags)
o "path" - the JVM class-path and/or the JPMS module-path
o "main" - the main class to run
o "args" - the arguments passed to the main class
Configure Commands:
-------------------
--add-modules=&lt;moduleName&gt;(,&lt;moduleName&gt;)*
Adds the given modules to the list of modules enabled at
when Jetty starts.
Transitive dependencies are followed and dependent
modules may also explicitly added.
Modules are added by creating an *.ini file in the
${jetty.base}/start.d/ directory.
The *.ini file contains the --module option that enables
the module, and any other option defined in the module's
[ini-template] section.
If the *.ini file specifies properties, these may be
overridden by specifying the same properties on the
command line.
If a module is transitively enabled, its *.ini file will
not be generated.
To generate the *.ini file, the module must be explicitly
listed in the --add-modules=... command.
This option replaces the deprecated --add-to-start and
--add-to-startd commands.
--create-start-d
Creates a ${jetty.base}/start.d directory.
If the ${jetty.base}/start.ini file exists, then it is
moved into the ${jetty.base}/start.d/ directory.
Using a ${jetty.base}/start.d/ directory is the default and
this option is only needed to either force the creation of
the ${jetty.base}/start.d/ directory, or to move a
${jetty.base}/start.ini file to ${jetty.base}/start.d/.
--create-start-ini
Creates a ${jetty.base}/start.ini file.
If a ${jetty.base}/start.d/ directory exists, then all
the contained *.ini files are concatenated into the
${jetty.base}/start.ini file.
--update-ini
Scans all the ${jetty.base}/start.d/*.ini files and updates
any property with values specified on the command line.
For example:
$ java -jar ${jetty.host}/start.jar --update-ini jetty.http.port=8888
--create-files
Creates any missing files that are required by enabled
modules, as specified in their [files] section.
This may download a file from the network if a HTTP URI
is specified in the [files] section.
--write-module-graph=&lt;filename&gt;
Creates a graphviz *.dot file of the module graph as it
is configured for the current ${jetty.base}.
See https://graphviz.org/ for details on how to post-process
this file into the output best suited for your needs.
Options:
--------
--module=&lt;moduleName&gt;(,&lt;moduleName&gt;)*
Enables a module for this execution.
To enable a module for all future executions, use the
--add-modules command.
Note: this option is used in the ${jetty.base}/start.ini
file or in ${jetty.base}/start.d/*.ini files created by
the --add-modules command.
--lib=&lt;classpath&gt;
Adds the specified class-path entries to the the server
class-path (or module-path).
--download=&lt;http-uri&gt;|&lt;location&gt;
Downloads a file from the given HTTP URI, if it does
not already exist at the given location.
Note: the location is always relative to ${jetty.base}.
You might need to escape the pipe "\|" to use it in
some shell environments.
--exec
Executes the generated command line in a forked JVM
(see the --dry-run command).
This can be used when ${jetty.base}/start.d/*.ini files
contain -D, -X or -XX arguments, but creates an extra
JVM process.
--exec-properties=&lt;filename&gt;
Assigns 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.
--commands=&lt;filename&gt;
Uses each line of the specified file as arguments on the
JVM command line.
--jpms
Starts Jetty in JPMS mode in a forked JVM (see also the
--dry-run command).
The library *.jar files are set on the forked JVM module-path
(rather than the forked JVM class-path), while directories
are set on the forked JVM class-path.
The main class is specified with the JPMS option
--module &lt;moduleName&gt;/&lt;mainClassName&gt;.
--debug
Enables debug output of the startup execution.
Note: this does not setup debug logging for Jetty itself,
only for the startup execution.
If you want debug logging for Jetty, configure one of the
available logging modules using the --add-modules command.
--start-log-file=&lt;filename&gt;
A filename, relative to ${jetty.base}, where all startup
output will be sent. This is useful for capturing startup
issues when the Jetty logging module has not yet started
due to configuration errors.
--approve-all-licenses
Approves all license questions from modules that have
particular license requirements.
Useful for enabling modules from a script, so that it
does not require user interaction.
--skip-file-validation=&lt;moduleName&gt;(,&lt;moduleName&gt;)*
Disables the creation of files as specified by the
[files] section of the specified modules.
Useful if a logging module specifies a *.properties
config file, but you want to use that module with an
*.xml config file instead.
--include-jetty-dir=&lt;path&gt;
Includes the specified directory as a configuration source.
This directory behaves similarly to ${jetty.base} but sits
at a layer between ${jetty.home} and ${jetty.base}.
Useful when you want to apply a common "corporate"
configuration to all specific ${jetty.base} directories
without having to modify ${jetty.home}.
jetty.home=&lt;directory&gt;
Sets the ${jetty.home} directory.
By default it is resolved from the start.jar file path.
jetty.base=&lt;directory&gt;
Sets the ${jetty.base} directory.
By default it is resolved from the current directory path.
stop.host=&lt;string&gt;
Used with the --stop command.
Specifies the host where the Jetty server to stop is
running (defaults to 127.0.0.1).
stop.port=&lt;number&gt;
Used with the --stop command.
Specifies the port to use to contact the Jetty server
to stop.
stop.key=&lt;alphanumeric&gt;
Used with the --stop command.
The passphrase required to stop the Jetty server.
stop.wait=&lt;number&gt;
Used with the --stop command.
The time, in seconds, to wait for confirmation that the
running Jetty server has stopped.
If not specified, the stopper will not wait.
maven.repo.uri=&lt;url&gt;
The base URL to use to download Maven dependencies.
Defaults to: https://repo1.maven.org/maven2/.
&lt;name&gt;=&lt;value&gt;
Specifies a property value that overrides the same
property defined in a ${jetty.base}/start.d/*.ini file,
or in the [ini] section of a *.mod file.
&lt;name&gt;=&lt;value&gt;
Sets the property value unconditionally.
&lt;name&gt;+=&lt;value&gt;
Appends the given value to the existing value.
&lt;name&gt;?=&lt;value&gt;
Sets the property value only if it is not already set.
-D&lt;name&gt;=&lt;value&gt;
Specifies a system property, as well as a start property.
Note: this is a program argument that is interpreted and
added to the existing JVM system properties.
&lt;xml-file&gt;
Specifies a Jetty XML file relative to ${jetty.base}.
This file is in addition to the Jetty XML files resolved
from the [xml] sections of the enabled modules.</pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-modules"><a class="anchor" href="#og-modules"></a><a class="link" href="#og-modules">Jetty Modules</a></h3>
<div class="paragraph">
<p>A Jetty <em>module</em> provides one or more Java components that work together to implement one or more features.
Such features could be listening for clear-text HTTP/1.1 requests, exposing Jetty components to JMX, provide hot-deployment of web applications, etc.</p>
</div>
<div class="paragraph">
<p>Every Jetty feature is provided by a Jetty module.</p>
</div>
<div class="paragraph">
<p>A Jetty module is defined in a <code>&lt;name&gt;.mod</code> file, where <code>&lt;name&gt;</code> is the module name (see also the <a href="#og-modules-names">section about module names</a>).</p>
</div>
<div class="paragraph">
<p>Jetty module files are read from the typical <a href="#og-start-configure">configuration source directories</a>, under the <code>modules/</code> subdirectory; from higher priority to lower priority:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The <code>$JETTY_BASE/modules/</code> directory.</p>
</li>
<li>
<p>If a directory is specified with the <code>--include-jetty-dir</code> option, its <code>modules/</code> subdirectory.</p>
</li>
<li>
<p>The <code>$JETTY_HOME/modules/</code> directory.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The standard Jetty modules that Jetty provides out-of-the-box are under <code>$JETTY_HOME/modules/</code>.</p>
</div>
<div class="paragraph">
<p><a href="#og-modules-custom">Custom Jetty modules</a> should be put under <code>$JETTY_BASE/modules/</code>.</p>
</div>
<div class="sect3">
<h4 id="og-modules-names"><a class="anchor" href="#og-modules-names"></a><a class="link" href="#og-modules-names">Module Names</a></h4>
<div class="paragraph">
<p>A Jetty module has a unique name.
The module name is by default derived from the file name, so module file <code>acme.mod</code> identifies a module named <code>acme</code>.</p>
</div>
<div class="paragraph">
<p>However, a module file may specify a <a href="#og-modules-directive-provides">[provides]</a> directive for a <em>virtual</em> module, so that many modules may provide a different implementation for the same feature.</p>
</div>
<div class="paragraph">
<p>For example, among the standard modules provided by Jetty, the <code>server</code> module depends on the <code>logging</code> module, but there is no correspondent <code>logging.mod</code> file.</p>
</div>
<div class="paragraph">
<p>However, the <code>logging-jetty.mod</code> file has, among others, this section:</p>
</div>
<div class="listingblock">
<div class="title">logging-jetty.mod</div>
<div class="content">
<pre>[provides]
logging|default</pre>
</div>
</div>
<div class="paragraph">
<p>This section means that the <code>logging-jetty.mod</code> file provides the virtual module <code>logging</code>, and it is the default provider.</p>
</div>
<div class="paragraph">
<p>The <code>logging-log4j2.mod</code> file has a similar section:</p>
</div>
<div class="listingblock">
<div class="title">logging-log4j2.mod</div>
<div class="content">
<pre>[provides]
logging</pre>
</div>
</div>
<div class="paragraph">
<p>If there are no enabled modules that provide the <code>logging</code> virtual module, either explicitly or transitively, then the default provider is used, in this case <code>logging-jetty.mod</code>.</p>
</div>
<div class="paragraph">
<p>Otherwise, a module that provides the <code>logging</code> virtual module is explicitly or transitively enabled, and the default provider is not used.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-modules-components"><a class="anchor" href="#og-modules-components"></a><a class="link" href="#og-modules-components">Module Components</a></h4>
<div class="paragraph">
<p>A Jetty module may provide one or more Java components that implement a feature.
These Java components are nothing more than regular Java classes that are instantiated and configured via <a href="#og-xml">Jetty XML</a> files.</p>
</div>
<div class="paragraph">
<p>The Jetty XML file of a Jetty module may instantiate and assemble together its own components, or reference existing components from other Jetty modules to enhance or reconfigure them.</p>
</div>
<div class="paragraph">
<p>The Jetty module&#8217;s XML files are read from the typical <a href="#og-start-configure">configuration source directories</a>, under the <code>etc/</code> subdirectory; from higher priority to lower priority:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The <code>$JETTY_BASE/etc/</code> directory.</p>
</li>
<li>
<p>If a directory is specified with the <code>--include-jetty-dir</code> option, its <code>etc/</code> subdirectory.</p>
</li>
<li>
<p>The <code>$JETTY_HOME/etc/</code> directory.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The standard Jetty modules XML files that Jetty provides out-of-the-box are under <code>$JETTY_HOME/etc/</code>.</p>
</div>
<div class="paragraph">
<p>For example, a Jetty XML file that allocates Jetty&#8217;s <code>QueuedThreadPool</code> could be as simple as:</p>
</div>
<div class="listingblock">
<div class="title">jetty-threadpool.xml</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">threadPool</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.util.thread.QueuedThreadPool</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">maxThreads</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">int</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Property</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">jetty.threadPool.maxThreads</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">default</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">256</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how the Jetty XML file above is allocating (with the <code>&lt;New&gt;</code> element) a <code>QueuedThreadPool</code> instance, giving it the unique <code>id</code> of <code>threadPool</code> (so that other modules can reference it, if they need to).
It is then calling the setter method <code>QueuedThreadPool.setMaxThreads(int)</code> with the value defined by the <a href="#og-modules-properties">module property</a> <code>jetty.threadPool.maxThreads</code>; if the property value is not defined, it will have the default value of <code>256</code>.</p>
</div>
<div class="paragraph">
<p>This is nothing more than Java code in XML format with configurable properties support that can be leveraged by the <a href="#og-start">Jetty start mechanism</a>.</p>
</div>
<div class="paragraph">
<p>The Jetty module&#8217;s XML files make easy to instantiate and assemble Java components (just write the equivalent Java code in XML format), and make easy to configure them by declaring module properties that can be easily customized elsewhere (for example, in <code>*.ini</code> files as described in <a href="#og-start-configure-enable">this section</a>, or on the command line as described in <a href="#og-start-start">this section</a>).</p>
</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>Remember that the standard Jetty XML files in <code>$JETTY_HOME/etc/</code> should not be modified.</p>
</div>
<div class="paragraph">
<p>Even if you need to modify a standard Jetty component, write a new Jetty XML file, save it under <code>$JETTY_BASE/etc/</code>, and create a <a href="#og-modules-custom">custom Jetty module</a> so that it gets processed when Jetty starts.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="og-modules-properties"><a class="anchor" href="#og-modules-properties"></a><a class="link" href="#og-modules-properties">Module Properties</a></h4>
<div class="paragraph">
<p>A Jetty module property is declared in the <a href="#og-modules-components">module XML file(s)</a> via the <code>&lt;Property&gt;</code> element.
Modules properties are used to parametrize Jetty components so that you can customize their values when Jetty starts, rather than hard-coding it in the XML files.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
You can declare your own properties, but the <code>jetty.*</code> namespace is reserved.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>A module property can be given a value in a Jetty module <code>[ini]</code> section (see <a href="#og-modules-directive-ini">here</a>), in a <code>*.ini</code> file as described in <a href="#og-start-configure-enable">this section</a>, or on the command line as described in <a href="#og-start-start">this section</a>.</p>
</div>
<div class="paragraph">
<p>The syntax to specify a property value is the following:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">&lt;name&gt;=&lt;value&gt;</dt>
<dd>
<p>Sets the property value unconditionally.</p>
</dd>
<dt class="hdlist1">&lt;name&gt;+=&lt;value&gt;</dt>
<dd>
<p>Appends the value to the existing value.
This is useful to append a value to properties that accept a comma separated list of values, for example:</p>
<div class="listingblock">
<div class="content">
<pre>jetty.webapp.addServerClasses+=,com.acme</pre>
</div>
</div>
</dd>
<dt class="hdlist1">&lt;name&gt;?=&lt;value&gt;</dt>
<dd>
<p>Sets the property value only if it is not already set.
This is useful to define default values, for example for "version" properties, where the "version" property can be explicitly configured to a newer version, but if it is not explicitly configured it will have a default version (see also <a href="#og-start-configure-custom-module">here</a>).
For example:</p>
<div class="listingblock">
<div class="content">
<pre>conscrypt.version?=2.5.1
jetty.sslContext.provider?=Conscrypt</pre>
</div>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect3">
<h4 id="og-modules-directives"><a class="anchor" href="#og-modules-directives"></a><a class="link" href="#og-modules-directives">Module Directives</a></h4>
<div class="paragraph">
<p>Lines that start with <code>#</code> are comments.</p>
</div>
<div class="sect4">
<h5 id="og-modules-directive-description"><a class="anchor" href="#og-modules-directive-description"></a><a class="link" href="#og-modules-directive-description">[description]</a></h5>
<div class="paragraph">
<p>A text that describes the module.</p>
</div>
<div class="paragraph">
<p>This text will be shown by the <a href="#og-start-configure">Jetty start mechanism</a> when using the <code>--list-modules</code> command.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-tags"><a class="anchor" href="#og-modules-directive-tags"></a><a class="link" href="#og-modules-directive-tags">[tags]</a></h5>
<div class="paragraph">
<p>A list of words that characterize the module.</p>
</div>
<div class="paragraph">
<p>Modules that have the same tags will be shown by the Jetty start mechanism when using the <code>--list-modules=&lt;tag&gt;</code> command.</p>
</div>
<div class="listingblock">
<div class="title">example.mod</div>
<div class="content">
<pre>[tags]
demo
webapp
jsp</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-provides"><a class="anchor" href="#og-modules-directive-provides"></a><a class="link" href="#og-modules-directive-provides">[provides]</a></h5>
<div class="paragraph">
<p>A module name with an optional <code>default</code> specifier.</p>
</div>
<div class="paragraph">
<p>As explained in the <a href="#og-modules-names">module name section</a>, there can be many module files each providing a different implementation for the same feature.</p>
</div>
<div class="paragraph">
<p>The format is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[provides]
&lt;module_name&gt;[|default]</pre>
</div>
</div>
<div class="paragraph">
<p>where the <code>|default</code> part is optional and specifies that the module is the default provider.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-depends"><a class="anchor" href="#og-modules-directive-depends"></a><a class="link" href="#og-modules-directive-depends">[depends]</a></h5>
<div class="paragraph">
<p>A list of module names that this module depends on.</p>
</div>
<div class="paragraph">
<p>For example, the standard module <code>http</code> depends on module <code>server</code>.
Enabling the <code>http</code> module also enables, transitively, the <code>server</code> module, since the <code>http</code> module cannot work without the <code>server</code> module; when the <code>server</code> module is transitively enabled, the modules it depends on will be transitively enabled, and so on recursively.</p>
</div>
<div class="paragraph">
<p>The <code>[depends]</code> directive establishes a <a href="https://en.wikipedia.org/wiki/Partially_ordered_set"><em>partial order</em></a> relationship among modules so that enabled modules can be sorted and organized in a graph.
Circular dependencies are not allowed.</p>
</div>
<div class="paragraph">
<p>The order of the enabled modules is used to determine the processing of the configuration, for example the order of processing of the <a href="#og-modules-directive-files">[files]</a> section, the order of processing of XML files defined in the <a href="#og-modules-directive-xml">[xml]</a> section, etc.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-after"><a class="anchor" href="#og-modules-directive-after"></a><a class="link" href="#og-modules-directive-after">[after]</a></h5>
<div class="paragraph">
<p>This directive indicates that this module is ordered after the listed module names, if they are enabled.</p>
</div>
<div class="paragraph">
<p>For example, module <code>https</code> is <code>[after]</code> module <code>http2</code>.
Enabling the <code>https</code> module <em>does not</em> enable the <code>http2</code> module.</p>
</div>
<div class="paragraph">
<p>However, if the <code>http2</code> module is enabled (explicitly or transitively), then the <code>https</code> module is <a href="#og-modules-directive-depends">sorted</a> <em>after</em> the <code>http2</code> module.
In this way, you are guaranteed that the <code>https</code> module is processed after the <code>http2</code> module.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-before"><a class="anchor" href="#og-modules-directive-before"></a><a class="link" href="#og-modules-directive-before">[before]</a></h5>
<div class="paragraph">
<p>This directive indicates that this module is ordered before the listed module names, if they are enabled.</p>
</div>
<div class="paragraph">
<p>One use of this directive is to create a prerequisite module without the need to modify the <code>depends</code> directive of an existing module.
For example, to create a custom <code>org.eclipse.jetty.server.Server</code> subclass instance to be used by the standard <code>server</code> module, without modifying the existing <code>server.mod</code> file nor the <code>jetty.xml</code> file that it uses. This can be achieved by creating the <code>custom-server</code> <a href="#og-modules-custom">Jetty custom module</a>:</p>
</div>
<div class="listingblock">
<div class="title">custom-server.mod</div>
<div class="content">
<pre>[description]
This module creates a custom Server subclass instance.
[before]
server
[xml]
etc/custom-server.xml</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>custom-server.xml</code> file is the following:</p>
</div>
<div class="listingblock">
<div class="title">custom-server.xml</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Server</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">com.acme.server.CustomJettyServer</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The presence of the <code>[before]</code> directive in <code>custom-server.mod</code> causes the processing of the <code>custom-server.xml</code> file to happen before the processing of the standard <code>jetty.xml</code> file referenced by the standard <code>server.mod</code> Jetty module.</p>
</div>
<div class="paragraph">
<p>Thus, the instance assigned to the <code>Server</code> identifier is your custom <code>com.acme.server.CustomJettyServer</code> instance from the <code>custom-server.xml</code> file; this instance is then used while processing the <code>jetty.xml</code> file.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-files"><a class="anchor" href="#og-modules-directive-files"></a><a class="link" href="#og-modules-directive-files">[files]</a></h5>
<div class="paragraph">
<p>A list of paths (directories and/or files) that are necessary for the module, created or resolved when the module is enabled.</p>
</div>
<div class="paragraph">
<p>Each path may be of the following types:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Path Name</dt>
<dd>
<p>A path name representing a file, or a directory if the path name ends with <code>/</code>, such as <code>webapps/</code>.
The file or directory will be created relative to <code>$JETTY_BASE</code>, if not already present.</p>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[files]
logs/</pre>
</div>
</div>
</dd>
<dt class="hdlist1">Maven Artifact</dt>
<dd>
<p>An URI representing a Maven artifact to be downloaded from Maven Central, if not already present.
Property expansion is supported.</p>
<div class="paragraph">
<p>The format is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[files]
maven://&lt;groupId&gt;/&lt;artifactId&gt;/&lt;version&gt;[/&lt;type&gt;]|&lt;pathName&gt;</pre>
</div>
</div>
<div class="paragraph">
<p>where <code>&lt;type&gt;</code> is optional, and <code>&lt;pathName&gt;</code> after the <code>|</code> is the path under <code>$JETTY_BASE</code> where the downloaded file should be saved.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>[files]
maven://org.postgresql/postgresql/${postgresql-version}|lib/postgresql-${postgresql-version}.jar</code></pre>
</div>
</div>
</dd>
<dt class="hdlist1">BaseHome</dt>
<dd>
<p>An URI representing a <code>$JETTY_HOME</code> resource to be copied in <code>$JETTY_BASE</code>, if not already present.
URIs of this type are typically only used by standard Jetty modules; custom modules should not need to use it.</p>
<div class="paragraph">
<p>The format is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[files]
basehome:&lt;jettyHomePathName&gt;|&lt;pathName&gt;</pre>
</div>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[files]
basehome:modules/demo.d/demo-moved-context.xml|webapps/demo-moved-context.xml</pre>
</div>
</div>
</dd>
<dt class="hdlist1">HTTP URL</dt>
<dd>
<p>An <code>http://</code> or <code>https://</code> URL to be downloaded, if not already present.</p>
<div class="paragraph">
<p>The format is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[files]
&lt;httpURL&gt;|&lt;pathName&gt;</pre>
</div>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[files]
https://acme.com/favicon.ico|webapps/acme/favicon.ico</pre>
</div>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-libs"><a class="anchor" href="#og-modules-directive-libs"></a><a class="link" href="#og-modules-directive-libs">[libs]</a></h5>
<div class="paragraph">
<p>A list of paths, relative to the <a href="#og-start-configure">configuration source directories</a>, of <code>*.jar</code> library files and/or directories that are added to the server class-path (or module-path when <a href="#og-start-start-jpms">running in JPMS mode</a>).</p>
</div>
<div class="paragraph">
<p>The <code>[libs]</code> section if often used in conjunction with the <code>[files]</code> section.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[files]
maven://org.postgresql/postgresql/${postgresql-version}|lib/postgresql-${postgresql-version}.jar
[libs]
lib/postgresql-${postgresql-version}.jar</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>postgresql-&lt;version&gt;.jar</code> artifact is downloaded from Maven Central, if not already present, into the <code>$JETTY_BASE/lib/</code> directory when the module is enabled.</p>
</div>
<div class="paragraph">
<p>When Jetty starts, the <code>$JETTY_BASE/lib/postgresql-&lt;version&gt;.jar</code> will be in the server class-path (or module-path).</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-xml"><a class="anchor" href="#og-modules-directive-xml"></a><a class="link" href="#og-modules-directive-xml">[xml]</a></h5>
<div class="paragraph">
<p>A list of paths, relative to the <a href="#og-start-configure">configuration source directories</a>, of Jetty <code>*.xml</code> files that are passed as program arguments to be processed when Jetty starts (see the <a href="#og-start-start-xml">section about assembling Jetty components</a>).</p>
</div>
<div class="paragraph">
<p>Jetty XML files are read from the typical <a href="#og-start-configure">configuration source directories</a>, under the <code>etc/</code> subdirectory.
Standard Jetty XML files are under <code>$JETTY_HOME/etc/</code>, while custom Jetty XML files are typically under <code>$JETTY_BASE/etc/</code>.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[xml]
etc/custom/components.xml</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-ini"><a class="anchor" href="#og-modules-directive-ini"></a><a class="link" href="#og-modules-directive-ini">[ini]</a></h5>
<div class="paragraph">
<p>A list of program arguments to pass to the command line when Jetty is started.</p>
</div>
<div class="paragraph">
<p>The program arguments may include any command line option (see <a href="#og-start-reference">here</a> for the list of command line options), <a href="#og-modules-properties">module properties</a> and/or <a href="#og-modules-components">module XML files</a>.</p>
</div>
<div class="paragraph">
<p>A property defined in the <code>[ini]</code> section is available in the <code>*.mod</code> module file for property expansion, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[ini]
postgresql-version?=42.2.18
[lib]
lib/postgresql-${postgresql-version}.jar</pre>
</div>
</div>
<div class="paragraph">
<p>In the example above, the <code>[lib]</code> section contains <code>${postgresql-version}</code>, a reference to property <code>postgresql-version</code> whose value is defined in the <code>[ini]</code> section.
The expression <code>${&lt;property&gt;}</code> <em>expands</em> the property replacing the expression with the property value.</p>
</div>
<div class="paragraph">
<p>See also the <a href="#og-start-start-jpms">JPMS section</a> for additional examples about the <code>[ini]</code> section.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-ini-template"><a class="anchor" href="#og-modules-directive-ini-template"></a><a class="link" href="#og-modules-directive-ini-template">[ini-template]</a></h5>
<div class="paragraph">
<p>A list of properties to be copied in the <code>*.ini</code> file generated when <a href="#og-start-configure-enable">the module is enabled</a>.</p>
</div>
<div class="paragraph">
<p>The list of properties is derived from the <a href="#og-modules-components">module XML file(s)</a> that declare them.</p>
</div>
<div class="paragraph">
<p>The properties are typically assigned their default value and commented out, so that it is evident which properties have been uncommented and customized with a non-default value.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-exec"><a class="anchor" href="#og-modules-directive-exec"></a><a class="link" href="#og-modules-directive-exec">[exec]</a></h5>
<div class="paragraph">
<p>A list of JVM command line options and/or system properties passed to a forked JVM.</p>
</div>
<div class="paragraph">
<p>When the <code>[exec]</code> section is present, the JVM running the Jetty start mechanism will fork another JVM, passing the JVM command line options and system properties listed in the <code>[exec]</code> sections of the enabled modules.</p>
</div>
<div class="paragraph">
<p>This is necessary because JVM options such as <code>-Xmx</code> (that specifies the max JVM heap size) cannot be changed in a running JVM.
For an example, see <a href="#og-start-configure-custom-module-exec">this section</a>.</p>
</div>
<div class="paragraph">
<p>You can avoid that the Jetty start mechanism forks the second JVM, as explained in <a href="#og-start-configure-dry-run">this section</a>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-jpms"><a class="anchor" href="#og-modules-directive-jpms"></a><a class="link" href="#og-modules-directive-jpms">[jpms]</a></h5>
<div class="paragraph">
<p>A list of JVM command line options related to the Java Module System.</p>
</div>
<div class="paragraph">
<p>This section is processed only when Jetty is <a href="#og-start-start-jpms">started in JPMS mode</a>.</p>
</div>
<div class="paragraph">
<p>The directives are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">add-modules</dt>
<dd>
<p>Equivalent to the JVM option <code>--add-modules</code>.
The format is:</p>
<div class="listingblock">
<div class="content">
<pre>[jpms]
add-modules: &lt;module&gt;(,&lt;module&gt;)*</pre>
</div>
</div>
<div class="paragraph">
<p>where <code>module</code> is a JPMS module name.</p>
</div>
</dd>
<dt class="hdlist1">patch-module</dt>
<dd>
<p>Equivalent to the JVM option <code>--patch-module</code>.
The format is:</p>
<div class="listingblock">
<div class="content">
<pre>[jpms]
patch-module: &lt;module&gt;=&lt;file&gt;(:&lt;file&gt;)*</pre>
</div>
</div>
<div class="paragraph">
<p>where <code>module</code> is a JPMS module name.</p>
</div>
</dd>
<dt class="hdlist1">add-opens</dt>
<dd>
<p>Equivalent to the JVM option <code>--add-opens</code>.
The format is:</p>
<div class="listingblock">
<div class="content">
<pre>[jpms]
add-opens: &lt;module&gt;/&lt;package&gt;=&lt;target-module&gt;(,&lt;target-module&gt;)*</pre>
</div>
</div>
<div class="paragraph">
<p>where <code>module</code> and <code>target-module</code> are a JPMS module names.</p>
</div>
</dd>
<dt class="hdlist1">add-exports</dt>
<dd>
<p>Equivalent to the JVM option <code>--add-exports</code>.
The format is:</p>
<div class="listingblock">
<div class="content">
<pre>[jpms]
add-exports: &lt;module&gt;/&lt;package&gt;=&lt;target-module&gt;(,&lt;target-module&gt;)*</pre>
</div>
</div>
<div class="paragraph">
<p>where <code>module</code> and <code>target-module</code> are a JPMS module names.</p>
</div>
</dd>
<dt class="hdlist1">add-reads</dt>
<dd>
<p>Equivalent to the JVM option <code>--add-exports</code>.
The format is:</p>
<div class="listingblock">
<div class="content">
<pre>[jpms]
add-reads: &lt;module&gt;=&lt;target-module&gt;(,&lt;target-module&gt;)*</pre>
</div>
</div>
<div class="paragraph">
<p>where <code>module</code> and <code>target-module</code> are a JPMS module names.</p>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-license"><a class="anchor" href="#og-modules-directive-license"></a><a class="link" href="#og-modules-directive-license">[license]</a></h5>
<div class="paragraph">
<p>The license under which the module is released.</p>
</div>
<div class="paragraph">
<p>A Jetty module may be released under a license that is different from Jetty&#8217;s, or use libraries that require end-users to accept their licenses in order to be used.</p>
</div>
<div class="paragraph">
<p>You can put the license text in the <code>[license]</code> section, and when the Jetty module is enabled the license text will be printed on the terminal, and the user prompted to accept the license.
If the user does not accept the license, the module will not be enabled.</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[license]
Acme Project is an open source project hosted on GitHub
and released under the Apache 2.0 license.
https://www.apache.org/licenses/LICENSE-2.0.txt</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-directive-version"><a class="anchor" href="#og-modules-directive-version"></a><a class="link" href="#og-modules-directive-version">[version]</a></h5>
<div class="paragraph">
<p>The minimum Jetty version for which this module is valid.</p>
</div>
<div class="paragraph">
<p>For example, a module may only be valid for Jetty 10 and later, but not for earlier Jetty versions (because it references components that have been introduced in Jetty 10).</p>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[version]
10.0</pre>
</div>
</div>
<div class="paragraph">
<p>A Jetty module with such a section will only work for Jetty 10.0.x or later.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-modules-custom"><a class="anchor" href="#og-modules-custom"></a><a class="link" href="#og-modules-custom">Custom Jetty Modules</a></h4>
<div class="paragraph">
<p>In addition to the modules that come packaged with Jetty, you can create your own custom modules.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Make sure you have read the <a href="#og-modules">Jetty modules section</a> if you are not familiar with the concepts used in this section.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Custom modules can be used for a number of reasons&#8201;&#8212;&#8201;they can extend Jetty features, or add new features, or make additional libraries available to the server, etc.</p>
</div>
<div class="sect4">
<h5 id="og-modules-custom-modify"><a class="anchor" href="#og-modules-custom-modify"></a><a class="link" href="#og-modules-custom-modify">Modifying an Existing Module</a></h5>
<div class="paragraph">
<p>The standard Jetty modules typically come with a number of configurable properties that can be easily customized without the need of writing a custom module.</p>
</div>
<div class="paragraph">
<p>However, there may be cases where the customization is more complex than a simple property, and a custom module is necessary.</p>
</div>
<div class="paragraph">
<p>For example, let&#8217;s assume that you want to modify the order of the TLS cipher suites offered by the server when a client connects, using the <a href="https://www.openssl.org/docs/man1.1.0/man1/ciphers.html">OpenSSL cipher list format</a>.</p>
</div>
<div class="paragraph">
<p>The Jetty class that handles the TLS configuration is <code>SslContextFactory</code>, and it already has a method <code>setCipherComparator(Comparator&lt;String&gt;)</code>; however, you need to pass your custom implementation, which cannot be represented with a simple module property.</p>
</div>
<div class="paragraph">
<p>The <code>SslContextFactory</code> component is already allocated by the standard Jetty module <code>ssl</code>, so what you need to do is the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Write the custom cipher <code>Comparator</code> and package it into a <code>*.jar</code> file (exercise left to reader).</p>
</li>
<li>
<p>Write a custom Jetty XML file that calls the <code>SslContextFactory.setCipherComparator(Comparator&lt;String&gt;)</code> method.</p>
</li>
<li>
<p>Write a custom Jetty module file that depends on the standard <code>ssl</code> module.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Start with the custom Jetty XML file, <code>$JETTY_BASE/etc/custom-ssl.xml</code>:</p>
</div>
<div class="listingblock">
<div class="title">custom-ssl.xml</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">sslContextFactory</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">CipherComparator</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">com.acme.ssl.CustomCipherComparator</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;Property</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">com.acme.ssl.cipherList</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;Default&gt;</span>ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!ADH<span class="tag">&lt;/Default&gt;</span>
<span class="tag">&lt;/Property&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Ref&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Reference the existing <code>SslContextFactory</code> object created by the standard <code>ssl</code> module using its <code>id</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Call the <code>setCipherComparator()</code> method.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Instantiate your custom cipher comparator.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Pass to the constructor the ordering string in OpenSSL format, reading it from the module property <code>com.acme.ssl.cipherList</code>.</td>
</tr>
</table>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
The cipher list used above may not be secure&#8201;&#8212;&#8201;it&#8217;s just an example.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Then write your custom module in the <code>$JETTY_BASE/modules/custom-ssl.mod</code> file:</p>
</div>
<div class="listingblock">
<div class="title">custom-ssl.mod</div>
<div class="content">
<pre class="CodeRay highlight"><code>[description]
Customizes the standard ssl module.
[tags] <i class="conum" data-value="1"></i><b>(1)</b>
acme
[depends] <i class="conum" data-value="2"></i><b>(2)</b>
ssl
[lib] <i class="conum" data-value="3"></i><b>(3)</b>
lib/custom-cipher-comparator.jar
[xml] <i class="conum" data-value="4"></i><b>(4)</b>
etc/custom-ssl.xml
[ini-template] <i class="conum" data-value="5"></i><b>(5)</b>
## The cipher list in OpenSSL format.
# com.acme.ssl.cipherList=ECDH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS:!ADH</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>A tag that characterizes this custom module (see <a href="#og-modules-directive-tags">here</a>).</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>This custom module depends on the standard <code>ssl</code> module.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>The custom cipher comparator class is compiled and packaged into this <code>*.jar</code> file.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>The custom Jetty XML file from above.</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>The text that will be copied in the <code>custom-ssl.ini</code> file when this custom module will be enabled.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now you can <a href="#og-start-configure-enable">enable</a> the custom module with the following command issued from the <code>$JETTY_BASE</code> directory:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=https,custom-ssl</pre>
</div>
</div>
<div class="paragraph">
<p>The command above will produce the following <code>$JETTY_BASE</code> directory structure:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$JETTY_BASE
├── etc
│ └── custom-ssl.xml
├── modules
│ └── custom-ssl.mod
├── resources
│ └── jetty-logging.properties
└── start.d
├── https.ini
└── <mark>custom-ssl.ini</mark></code></pre>
</div>
</div>
<div class="paragraph">
<p>In the custom XML file you have used a custom module property to parametrize your custom cipher comparator.
This custom module property was then referenced in the <code>[ini-template]</code> section of the custom module file, so that when the custom module is enabled, a correspondent <code>custom-ssl.ini</code> file is created.</p>
</div>
<div class="paragraph">
<p>In this way, updating the cipher list won&#8217;t require you to update the XML file, but just the <code>custom-ssl.ini</code> file.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-modules-custom-create"><a class="anchor" href="#og-modules-custom-create"></a><a class="link" href="#og-modules-custom-create">Creating a New Module</a></h5>
<div class="paragraph">
<p>In the cases where you need to enhance Jetty with a custom functionality, you can write a new Jetty module that provides it.</p>
</div>
<div class="paragraph">
<p>For example, let&#8217;s assume that you need to add a custom auditing component that integrates with the auditing tools used by your company.
This custom auditing component should measure the HTTP request processing times and record them (how they are recorded is irrelevant here&#8201;&#8212;&#8201;could be in a local log file or sent via network to an external service).</p>
</div>
<div class="paragraph">
<p>The Jetty libraries already provide a way to measure HTTP request processing times via <a href="../programming-guide/index.html#pg-server-http-channel-events"><code>HttpChannel</code> events</a>: you write a custom component that implements the <code>HttpChannel.Listener</code> interface and add it as a bean to the server <code>Connector</code> that receives the HTTP requests.</p>
</div>
<div class="paragraph">
<p>The steps to create a Jetty module are similar to those necessary to <a href="#og-modules-custom-modify">modify an existing module</a>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Write the auditing component and package it into a <code>*.jar</code> file.</p>
</li>
<li>
<p>Write a custom Jetty XML file that wires the auditing component to the <code>ServerConnector</code>.</p>
</li>
<li>
<p>Write a custom Jetty module file that puts everything together.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Let&#8217;s start with the auditing component, sketched below:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="keyword">package</span> <span class="namespace">com.acme.audit</span>;
<span class="directive">public</span> <span class="type">class</span> <span class="class">AuditingHttpChannelListener</span> <span class="directive">implements</span> HttpChannel.Listener {
<span class="comment">// Auditing is implemented here.</span>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s assume that this class is compiled and packaged into <code>acme-audit.jar</code>, and that it has a dependency on <code>acme-util.jar</code>.
Both <code>*.jar</code> files will be put in the <code>$JETTY_BASE/lib/</code> directory.</p>
</div>
<div class="paragraph">
<p>Next, let&#8217;s write the Jetty XML file that wires the auditing component to the <code>ServerConnector</code>, <code>$JETTY_BASE/etc/acme-audit.xml</code>:</p>
</div>
<div class="listingblock">
<div class="title">acme-audit.xml</div>
<div class="content">
<pre class="CodeRay highlight nowrap"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">httpConnector</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">addBean</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">com.acme.audit.AuditingHttpChannelListener</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">someProperty</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Property</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">com.acme.audit.some.property</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">default</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">42</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Ref&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Reference the existing clear-text HTTP <code>ServerConnector</code> object created by the standard <code>http</code> module.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Call <code>addBean()</code> on the <code>ServerConnector</code> to wire the auditing component.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Instantiate the auditing component.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Configure the auditing component with a property.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The last step is to create the custom Jetty module file for the auditing component, <code>$JETTY_BASE/modules/acme-audit.mod</code>:</p>
</div>
<div class="listingblock">
<div class="title">acme-audit.mod</div>
<div class="content">
<pre>[description]
Adds auditing to the clear-text HTTP connector
[tags] <i class="conum" data-value="1"></i><b>(1)</b>
acme
audit
[depends] <i class="conum" data-value="2"></i><b>(2)</b>
http
[libs] <i class="conum" data-value="3"></i><b>(3)</b>
lib/acme-audit.jar
lib/acme-util.jar
[xml] <i class="conum" data-value="4"></i><b>(4)</b>
etc/acme-audit.xml
[ini-template] <i class="conum" data-value="5"></i><b>(5)</b>
## An auditing property.
# com.acme.audit.some.property=42</pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>The tags that characterize this custom module (see <a href="#og-modules-directive-tags">here</a>).</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>This custom module depends on the standard <code>http</code> module.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>The <code>*.jar</code> files that contains the custom auditing component, and its dependencies.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>The custom Jetty XML file from above.</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>The text that will be copied in the <code>acme-audit.ini</code> file when this custom module will be enabled.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now you can <a href="#og-start-configure-enable">enable</a> the custom auditing module with the following command issued from the <code>$JETTY_BASE</code> directory:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=http,acme-audit</pre>
</div>
</div>
<div class="paragraph">
<p>The command above will produce the following <code>$JETTY_BASE</code> directory structure:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$JETTY_BASE
├── etc
│ └── acme-audit.xml
├── modules
│ └── acme-audit.mod
├── resources
│ └── jetty-logging.properties
└── start.d
├── http.ini
└── <mark>acme-audit.ini</mark></code></pre>
</div>
</div>
<div class="paragraph">
<p>Enabling the custom auditing component will create the <code>$JETTY_BASE/start.d/acme-audit.ini</code> module configuration file that you can edit to configure auditing properties.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-modules-standard"><a class="anchor" href="#og-modules-standard"></a><a class="link" href="#og-modules-standard">Standard Modules</a></h4>
</div>
<div class="sect3">
<h4 id="og-module-alpn"><a class="anchor" href="#og-module-alpn"></a><a class="link" href="#og-module-alpn">Module <code>alpn</code></a></h4>
<div class="paragraph">
<p>The <code>alpn</code> module enables support for the ALPN negotiation mechanism of the TLS protocol.</p>
</div>
<div class="paragraph">
<p>You can configure the list of application protocols negotiated by the ALPN mechanism, as well as the default protocol to use if the ALPN negotiation fails (for example, the client does not support ALPN).</p>
</div>
<div class="paragraph">
<p>The module properties are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>## Specifies the ordered list of application protocols supported by the server.
## The default list is specified by the list of the protocol modules that have
## been enabled, and the order is specified by the module dependencies.
# jetty.alpn.protocols=h2,http/1.1
## Specifies the protocol to use when the ALPN negotiation fails.
# jetty.alpn.defaultProtocol=http/1.1</pre>
</div>
</div>
<div class="sect4">
<h5 id="og-module-bytebufferpool"><a class="anchor" href="#og-module-bytebufferpool"></a><a class="link" href="#og-module-bytebufferpool">Module <code>bytebufferpool</code></a></h5>
<div class="paragraph">
<p>The <code>bytebufferpool</code> module allows you to configure the server-wide <code>ByteBuffer</code> pool.
Pooling <code>ByteBuffer</code>s results in less memory usage and less pressure on the Garbage Collector.</p>
</div>
<div class="paragraph">
<p><code>ByteBuffer</code>s are pooled in <em>buckets</em>; each bucket as a capacity that is a multiple of a capacity factor that you can configure.
For example, if a request for a <code>ByteBuffer</code> of capacity 2000 is requested, and the capacity factor is 1024, then the pool will allocate a buffer from the second bucket, of capacity 2048 (1024 * 2).</p>
</div>
<div class="paragraph">
<p>Applications that need to sustain many concurrent requests&#8201;&#8212;&#8201;or load spikes&#8201;&#8212;&#8201;may require many buffers during peak load. These buffers will remain pooled once the system transitions to a lighter load (or becomes idle), and it may be undesirable to retain a lot of memory for an idle system.</p>
</div>
<div class="paragraph">
<p>It is possible to configure the max heap memory and the max direct memory that the pool retains.
Excess buffers will not be pooled and will be eventually garbage collected.</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>[description]
Configures the ByteBufferPool used by ServerConnectors.
[depends]
logging
[xml]
etc/jetty-bytebufferpool.xml
[ini-template]
## Minimum capacity of a single ByteBuffer.
#jetty.byteBufferPool.minCapacity=0
## Maximum capacity of a single ByteBuffer.
## Requests for ByteBuffers larger than this value results
## in the ByteBuffer being allocated but not pooled.
#jetty.byteBufferPool.maxCapacity=65536
## Bucket capacity factor.
## ByteBuffers are allocated out of buckets that have
## a capacity that is multiple of this factor.
#jetty.byteBufferPool.factor=1024
## Maximum queue length for each bucket (-1 for unbounded).
#jetty.byteBufferPool.maxQueueLength=-1
## Maximum heap memory retainable by the pool (-1 for unlimited).
#jetty.byteBufferPool.maxHeapMemory=-1
## Maximum direct memory retainable by the pool (-1 for unlimited).
#jetty.byteBufferPool.maxDirectMemory=-1</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.byteBufferPool.maxHeapMemory</code></dt>
<dd>
<p>This property allows you to cap the max heap memory retained by the pool.</p>
</dd>
<dt class="hdlist1"><code>jetty.byteBufferPool.maxDirectMemory</code></dt>
<dd>
<p>This property allows you to cap the max direct memory retained by the pool.</p>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-module-deploy"><a class="anchor" href="#og-module-deploy"></a><a class="link" href="#og-module-deploy">Module <code>deploy</code></a></h5>
<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>[description]
Enables web application deployment from the $JETTY_BASE/webapps/ directory.
[depend]
webapp
[lib]
lib/jetty-deploy-${jetty.version}.jar
[files]
webapps/
[xml]
etc/jetty-deploy.xml
[ini-template]
# Monitored directory name (relative to $jetty.base)
# jetty.deploy.monitoredDir=webapps
# - OR -
# Monitored directory path (fully qualified)
# jetty.deploy.monitoredPath=/var/www/webapps
# Defaults Descriptor for all deployed webapps
# jetty.deploy.defaultsDescriptorPath=${jetty.base}/etc/webdefault.xml
# Monitored directory scan period (seconds)
# jetty.deploy.scanInterval=1
# Whether to extract *.war files
# jetty.deploy.extractWars=true</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.deploy.monitoredDir</code></dt>
<dd>
<p>The name of the monitored directory.</p>
</dd>
<dt class="hdlist1"><code>jetty.deploy.scanInterval</code></dt>
<dd>
<p>The scan period in seconds, 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>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-module-http"><a class="anchor" href="#og-module-http"></a><a class="link" href="#og-module-http">Module <code>http</code></a></h5>
<div class="paragraph">
<p>The <code>http</code> module provides the clear-text connector and 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 properties to configure the clear-text connector are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>### Clear-Text HTTP Connector Configuration
## The host/address to bind the connector to.
# jetty.http.host=0.0.0.0
## The port the connector listens on.
# jetty.http.port=8080
## The connector idle timeout, in milliseconds.
# jetty.http.idleTimeout=30000
## The number of acceptors (-1 picks a default value based on number of cores).
# jetty.http.acceptors=1
## The number of selectors (-1 picks a default value based on number of cores).
# jetty.http.selectors=-1
## The ServerSocketChannel accept queue backlog (0 picks the platform default).
# jetty.http.acceptQueueSize=0
## The thread priority delta to give to acceptor threads.
# jetty.http.acceptorPriorityDelta=0
## Whether to enable the SO_REUSEADDR socket option.
# jetty.http.reuseAddress=true
## Whether to enable the SO_REUSEPORT socket option.
# jetty.http.reusePort=false
## Whether to enable the TCP_NODELAY socket option on accepted sockets.
# jetty.http.acceptedTcpNoDelay=true
## The SO_RCVBUF socket option to set on accepted sockets.
## A value of -1 indicates that the platform default is used.
# jetty.http.acceptedReceiveBufferSize=-1
## The SO_SNDBUF socket option to set on accepted sockets.
## A value of -1 indicates that the platform default is used.
# jetty.http.acceptedSendBufferSize=-1</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.http.port</code></dt>
<dd>
<p>The network port that Jetty listens to for clear-text HTTP/1.1 connections&#8201;&#8212;&#8201;default <code>8080</code>.</p>
</dd>
<dt class="hdlist1"><code>jetty.http.idleTimeout</code></dt>
<dd>
<p>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&#8201;&#8212;&#8201;default <code>30</code> seconds.</p>
</dd>
<dt class="hdlist1"><code>jetty.http.acceptors</code></dt>
<dd>
<p>The number of threads that compete to accept connections&#8201;&#8212;&#8201;default 1. Use -1 to let the accept heuristic decides the value; the current heuristic calculates a value based on the number of cores).
Refer to <a href="#og-module-http-acceptors">this section</a> for more information about acceptor threads.</p>
</dd>
<dt class="hdlist1"><code>jetty.http.selectors</code></dt>
<dd>
<p>The number of NIO selectors (with an associated thread) that manage connections&#8201;&#8212;&#8201;default -1 (i.e. a select heuristic decides the value; the current heuristic calculates a value based on the number of cores).</p>
</dd>
</dl>
</div>
<div class="sect5">
<h6 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></h6>
<div class="paragraph">
<p>Accepting connections from remote clients may be configured as a blocking operation, or a non-blocking operation.</p>
</div>
<div class="paragraph">
<p>When accepting connections is configured as a blocking operation (the number of acceptors is greater than zero), a thread is blocked in the <code>accept()</code> call until a connection is accepted, and other acceptor threads (if any) are blocked on the lock acquired by the accepting thread 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, so that when one acceptor thread processes a just accepted connection, another acceptor thread can immediately take over accepting connections.</p>
</div>
<div class="paragraph">
<p>When accepting connections is configured as a non-blocking operation (the number of acceptors is zero), then the server socket is set in non-blocking mode and added to a NIO selector.
In this way, no dedicated acceptor threads exist: the work of accepting connections is performed by the selector thread.</p>
</div>
</div>
<div class="sect5">
<h6 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></h6>
<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="sect4">
<h5 id="og-module-http2"><a class="anchor" href="#og-module-http2"></a><a class="link" href="#og-module-http2">Module <code>http2</code></a></h5>
<div class="paragraph">
<p>The <code>http2</code> module enables support for the secure HTTP/2 protocol.</p>
</div>
<div class="paragraph">
<p>The module properties are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>## Specifies the maximum number of concurrent requests per session.
# jetty.http2.maxConcurrentStreams=128
## Specifies the initial stream receive window (client to server) in bytes.
# jetty.http2.initialStreamRecvWindow=524288
## Specifies the initial session receive window (client to server) in bytes.
# jetty.http2.initialSessionRecvWindow=1048576
## Specifies the maximum number of keys in all SETTINGS frames received by a session.
# jetty.http2.maxSettingsKeys=64
## Specifies the maximum number of bad frames and pings per second,
## after which a session is closed to avoid denial of service attacks.
# jetty.http2.rateControl.maxEventsPerSecond=50</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>jetty.http2.rateControl.maxEventsPerSecond</code> property controls the number of "bad" or "unnecessary" frames that a client may send before the server closes the connection (with code <a href="https://tools.ietf.org/html/rfc7540#section-7"><code>ENHANCE_YOUR_CALM</code></a>) to avoid a denial of service.</p>
</div>
<div class="paragraph">
<p>For example, an attacker may send empty <code>SETTINGS</code> frames to a server in a tight loop.
While the <code>SETTINGS</code> frames don&#8217;t change the server configuration and each of them is somehow harmless, the server will be very busy processing them because they are sent by the attacker one after the other, causing a CPU spike and eventually a denial of service (as all CPUs will be busy processing empty <code>SETTINGS</code> frames).</p>
</div>
<div class="paragraph">
<p>The same attack may be performed with <code>PRIORITY</code> frames, empty <code>DATA</code> frames, <code>PING</code> frames, etc.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-module-http2c"><a class="anchor" href="#og-module-http2c"></a><a class="link" href="#og-module-http2c">Module <code>http2c</code></a></h5>
<div class="paragraph">
<p>The <code>http2c</code> module enables support for the clear-text HTTP/2 protocol.</p>
</div>
<div class="paragraph">
<p>The module properties are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>## Specifies the maximum number of concurrent requests per session.
# jetty.http2c.maxConcurrentStreams=128
## Specifies the initial stream receive window (client to server) in bytes.
# jetty.http2c.initialStreamRecvWindow=524288
## Specifies the initial session receive window (client to server) in bytes.
# jetty.http2c.initialSessionRecvWindow=1232896
## Specifies the maximum number of keys in all SETTINGS frames received by a session.
# jetty.http2c.maxSettingsKeys=64
## Specifies the maximum number of bad frames and pings per second,
## after which a session is closed to avoid denial of service attacks.
# jetty.http2c.rateControl.maxEventsPerSecond=50</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>jetty.http2.rateControl.maxEventsPerSecond</code> property controls the number of "bad" or "unnecessary" frames that a client may send before the server closes the connection (with code <a href="https://tools.ietf.org/html/rfc7540#section-7"><code>ENHANCE_YOUR_CALM</code></a>) to avoid a denial of service.</p>
</div>
<div class="paragraph">
<p>For example, an attacker may send empty <code>SETTINGS</code> frames to a server in a tight loop.
While the <code>SETTINGS</code> frames don&#8217;t change the server configuration and each of them is somehow harmless, the server will be very busy processing them because they are sent by the attacker one after the other, causing a CPU spike and eventually a denial of service (as all CPUs will be busy processing empty <code>SETTINGS</code> frames).</p>
</div>
<div class="paragraph">
<p>The same attack may be performed with <code>PRIORITY</code> frames, empty <code>DATA</code> frames, <code>PING</code> frames, etc.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-module-http-forwarded"><a class="anchor" href="#og-module-http-forwarded"></a><a class="link" href="#og-module-http-forwarded">Module <code>http-forwarded</code></a></h5>
<div class="paragraph">
<p>The <code>http-forwarded</code> module provides support for processing the <code>Forwarded</code> HTTP header (defined in <a href="https://tools.ietf.org/html/rfc7239">RFC 7239</a>) and the now obsoleted <code>X-Forwarded-*</code> HTTP headers.</p>
</div>
<div class="paragraph">
<p>The module properties are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>### ForwardedRequestCustomizer Configuration
## Whether to process only the RFC7239 "Forwarded" header.
## "X-Forwarded-*" headers are not processed.
# jetty.httpConfig.forwardedOnly=false
## Whether the address obtained from "Forwarded: by=" or
## "X-Forwarded-Server" is used in the request authority.
# jetty.httpConfig.forwardedProxyAsAuthority=false
## Whether the "X-Forwarded-Port" header is used in the request authority,
## or else it is the remote client port.
# jetty.httpConfig.forwardedPortAsAuthority=true
## The name of the RFC 7239 HTTP header.
# jetty.httpConfig.forwardedHeader=Forwarded
## The name of the obsolete forwarded host HTTP header.
# jetty.httpConfig.forwardedHostHeader=X-Forwarded-Host
## The name of the obsolete forwarded server HTTP header.
# jetty.httpConfig.forwardedServerHeader=X-Forwarded-Server
## The name of the obsolete forwarded scheme HTTP header.
# jetty.httpConfig.forwardedProtoHeader=X-Forwarded-Proto
## The name of the obsolete forwarded for HTTP header.
# jetty.httpConfig.forwardedForHeader=X-Forwarded-For
## The name of the obsolete forwarded port HTTP header.
# jetty.httpConfig.forwardedPortHeader=X-Forwarded-Port
## The name of the obsolete forwarded https HTTP header.
# jetty.httpConfig.forwardedHttpsHeader=X-Proxied-Https
## The name of the obsolete forwarded SSL session ID HTTP header.
# jetty.httpConfig.forwardedSslSessionIdHeader=Proxy-ssl-id
## The name of the obsolete forwarded SSL cipher HTTP header.
# jetty.httpConfig.forwardedCipherSuiteHeader=Proxy-auth-cert</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-module-https"><a class="anchor" href="#og-module-https"></a><a class="link" href="#og-module-https">Module <code>https</code></a></h5>
<div class="paragraph">
<p>The <code>https</code> module provides the HTTP/1.1 protocol to the <a href="#og-module-ssl"><code>ssl</code> module</a>.</p>
</div>
<div class="paragraph">
<p>The module file is <code>$JETTY_HOME/modules/https.mod</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre># DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Adds HTTPS protocol support to the TLS(SSL) Connector.
[tags]
connector
https
http
ssl
[depend]
ssl
[after]
alpn
http2
http-forwarded
[xml]
etc/jetty-https.xml</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-module-jmx-remote"><a class="anchor" href="#og-module-jmx-remote"></a><a class="link" href="#og-module-jmx-remote">Module <code>jmx-remote</code></a></h5>
<div class="paragraph">
<p>The <code>jmx-remote</code> module provides remote access to JMX clients.</p>
</div>
<div class="paragraph">
<p>The module properties to configure remote JMX connector are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>## The host/address to bind the RMI server to.
# jetty.jmxremote.rmiserverhost=localhost
## The port the RMI server listens to (0 means a random port is chosen).
# jetty.jmxremote.rmiserverport=1099
## The host/address to bind the RMI registry to.
# jetty.jmxremote.rmiregistryhost=localhost
## The port the RMI registry listens to.
# jetty.jmxremote.rmiregistryport=1099
## The host name exported in the RMI stub.
-Djava.rmi.server.hostname=localhost</pre>
</div>
</div>
<div class="paragraph">
<p>The system property <code>java.rmi.server.hostname</code> is specified with the usual notation, prepending a <code>-D</code> in front of the system property name.</p>
</div>
<div class="paragraph">
<p>The system property <code>java.rmi.server.hostname</code> is uncommented because it is necessary in the default configuration&#8201;&#8212;&#8201;most systems do not have the local name resolution configured properly for remote access.</p>
</div>
<div class="paragraph">
<p>As an example, in a Linux machine named <code>beryl</code>, the <code>/etc/hosts</code> file may contain these entries:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>127.0.0.1 localhost
127.0.1.1 beryl</pre>
</div>
</div>
<div class="paragraph">
<p>If the system property <code>java.rmi.server.hostname</code> is not specified, the RMI implementation uses the host name <code>beryl</code> to figure out the IP address to store in the RMI stub, in this case <code>127.0.1.1</code>.
However, we the RMI server is configured to bind to <code>localhost</code>, i.e. <code>127.0.0.1</code>.</p>
</div>
<div class="paragraph">
<p>If the system property <code>java.rmi.server.hostname</code> is not specified, the RMI client will try to connect to <code>127.0.1.1</code> (because that&#8217;s what in the RMI stub) and fail because nothing is listening on that address.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-module-server"><a class="anchor" href="#og-module-server"></a><a class="link" href="#og-module-server">Module <code>server</code></a></h5>
<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="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>server</code> module configures the shared parameters for generic HTTP handline, but does not enable any specific network protocol. You have to explicitly enable the protocols you want to support by enabling, for example, the <a href="#og-module-http"><code>http</code> module</a> for clear-text HTTP/1.1 support, or the <a href="#og-module-http2"><code>http2</code> module</a> for secure HTTP/2 support, etc.</p>
</div>
<div class="paragraph">
<p>See also the <a href="#og-protocols">protocols section</a> for more information about the supported protocols.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="sect5">
<h6 id="og-module-server-http-config"><a class="anchor" href="#og-module-server-http-config"></a><a class="link" href="#og-module-server-http-config">HTTP Configuration Properties</a></h6>
<div class="paragraph">
<p>The module properties to configure generic HTTP properties are listed below. Mostly they frequently apply to both HTTP/1 and HTTP/2, but some parameters are version specific:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>### Common HTTP configuration
## Scheme to use to build URIs for secure redirects
# jetty.httpConfig.secureScheme=https
## Port to use to build URIs for secure redirects
# jetty.httpConfig.securePort=8443
## Response content buffer size (in bytes)
# jetty.httpConfig.outputBufferSize=32768
## Max response content write length that is buffered (in bytes)
# jetty.httpConfig.outputAggregationSize=8192
## Max request headers size (in bytes)
# jetty.httpConfig.requestHeaderSize=8192
## Max response headers size (in bytes)
# jetty.httpConfig.responseHeaderSize=8192
## Whether to send the Server: header
# jetty.httpConfig.sendServerVersion=true
## Whether to send the Date: header
# jetty.httpConfig.sendDateHeader=false
## Max per-connection header cache size (in nodes)
# jetty.httpConfig.headerCacheSize=1024
## Whether, for requests with content, delay dispatch until some content has arrived
# jetty.httpConfig.delayDispatchUntilContent=true
## Maximum number of error dispatches to prevent looping
# jetty.httpConfig.maxErrorDispatches=10
## Relative Redirect Locations allowed
# jetty.httpConfig.relativeRedirectAllowed=false
## Whether to use direct ByteBuffers for reading or writing
# jetty.httpConfig.useInputDirectByteBuffers=true
# jetty.httpConfig.useOutputDirectByteBuffers=true</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.httpConfig.headerCacheSize</code></dt>
<dd>
<p>The header cache is used when parsing HTTP/1 to more efficiently handle fields that are repeated in every request on a connection. If the server does not receive persistent connection or infrequent repeated fields, then there may be a performance gain in reducing the cache size. If large fields are frequently repeated, then a large cache may be beneficial.</p>
</dd>
<dt class="hdlist1"><code>jetty.httpConfig.delayDispatchUntilContent</code></dt>
<dd>
<p>It is not uncommon for the network packets containing a request header to arrive before packets that contain the data of any request body. In such cases it may be beneficial for overall performance to delay dispatching the request to be handled until the first data packet arrives, as this may avoid blocking the handling thread. However, if minimum latency for receiving the request without content is important, then this parameter can be set to false.</p>
</dd>
<dt class="hdlist1"><code>jetty.httpConfig.sendServerVersion</code></dt>
<dd>
<p>Whether you want to send the <code>Server</code> header in every HTTP response:</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="screen">HTTP/1.1 200 OK
Content-Length: 0
Server: Jetty(10.0.7)</code></pre>
</div>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect5">
<h6 id="og-module-server-config"><a class="anchor" href="#og-module-server-config"></a><a class="link" href="#og-module-server-config">Server Configuration Properties</a></h6>
<div class="paragraph">
<p>The module properties to configure the Jetty server are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>### Server configuration
## Whether ctrl+c on the console gracefully stops the Jetty server
# jetty.server.stopAtShutdown=true
## Timeout in ms to apply when stopping the server gracefully
# jetty.server.stopTimeout=5000
## Dump the state of the Jetty server, components, and webapps after startup
# jetty.server.dumpAfterStart=false
## Dump the state of the Jetty server, components, and webapps before shutdown
# jetty.server.dumpBeforeStop=false</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.server.dumpAfterStart</code></dt>
<dd>
<p>Whether to perform a <code>Server.dump()</code> operation after the <code>Server</code> has started.
The output of the dump operation is sent to <code>System.err</code>.
See also the <a href="#og-troubleshooting-dump">Jetty Server Dump</a> section for more information.</p>
</dd>
<dt class="hdlist1"><code>jetty.server.dumpBeforeStop</code></dt>
<dd>
<p>Whether to perform a <code>Server.dump()</code> operation before the <code>Server</code> stops.
The output of the dump operation is sent to <code>System.err</code>.
See also the <a href="#og-troubleshooting-dump">Jetty Server Dump</a> section for more information.</p>
</dd>
<dt class="hdlist1"><code>jetty.server.stopAtShutdown</code></dt>
<dd>
<p>Whether to call <code>Server.stop()</code> through a JVM shutdown hook when the JVM exits.</p>
</dd>
</dl>
</div>
</div>
<div class="sect5">
<h6 id="og-module-server-compliance"><a class="anchor" href="#og-module-server-compliance"></a><a class="link" href="#og-module-server-compliance">Server Compliance Properties</a></h6>
<div class="paragraph">
<p>The Jetty server strives to keep up with the latest <a href="https://en.wikipedia.org/wiki/Request_for_Comments">IETF RFC</a>s for compliance with internet specifications, which are periodically updated. When possible, Jetty will support backwards compatibility by providing compliance modes that can be configured to allow violations of the current specifications that may have been allowed in obsoleted specifications.
The module properties to configure the Jetty server compliance are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>## HTTP Compliance: RFC7230, RFC7230_LEGACY, RFC2616, RFC2616_LEGACY, LEGACY
# jetty.httpConfig.compliance=RFC7230
## URI Compliance: DEFAULT, LEGACY, RFC3986, RFC3986_UNAMBIGUOUS, UNSAFE
# jetty.httpConfig.uriCompliance=DEFAULT
## Cookie compliance mode for parsing request Cookie headers: RFC2965, RFC6265
# jetty.httpConfig.requestCookieCompliance=RFC6265
## Cookie compliance mode for generating response Set-Cookie: RFC2965, RFC6265
# jetty.httpConfig.responseCookieCompliance=RFC6265</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.httpConfig.compliance</code></dt>
<dd>
<p>Configures the compliance to HTTP specifications.
The value could be:</p>
<div class="ulist">
<ul>
<li>
<p>One of the predefined <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/http/HttpCompliance.html"><code>HttpCompliance</code></a> constants, such as <code>RFC7230</code> or <code>RFC2616</code>.
For example: <code>jetty.httpConfig.compliance=RFC2616</code>.</p>
</li>
<li>
<p>A comma-separated list of violations to allow or forbid, as specified by the <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/http/HttpCompliance.html#from(java.lang.String)"><code>HttpCompliance.from(String)</code></a> method.
For example, <code>jetty.httpConfig.compliance=RFC7230,MULTIPLE_CONTENT_LENGTHS</code> means that the HTTP compliance is that defined by <code>RFC7230</code>, but also allows the <code>HttpCompliance.Violation.MULTIPLE_CONTENT_LENGTHS</code>, so that requests that have multiple <code>Content-Length</code> headers are accepted (they would be rejected when using just <code>HttpCompliance.RFC7230</code>).</p>
<div class="paragraph">
<p>For more information about <code>HttpCompliance</code> see also <a href="../programming-guide/index.html#pg-server-compliance-http">this section</a>.</p>
</div>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1"><code>jetty.httpConfig.uriCompliance</code></dt>
<dd>
<p>Configures the compliance to URI specifications.
The value could be:</p>
<div class="ulist">
<ul>
<li>
<p>One of the predefined <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/http/UriCompliance.html"><code>UriCompliance</code></a> constants, such as <code>DEFAULT</code> or <code>RFC3986</code>.
For example: <code>jetty.httpConfig.compliance=RFC3986</code>.</p>
</li>
<li>
<p>A comma-separated list of violations to allow or forbid, as specified by the <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/http/UriCompliance.html#from(java.lang.String)"><code>UriCompliance.from(String)</code></a> method.
For example, <code>jetty.httpConfig.uriCompliance=RFC3986,-AMBIGUOUS_PATH_SEPARATOR</code> means that the URI compliance is that defined by <code>RFC3986</code>, but also does not allow the <code>UriCompliance.Violation.AMBIGUOUS_PATH_SEPARATOR</code>, so that requests that have URIs such as <code>/foo/bar%2Fbaz</code> (where <code>%2F</code> is the URL-encoded <code>/</code> character) are rejected (they would be accepted when using just <code>UriCompliance.RFC3986</code>).</p>
<div class="paragraph">
<p>For more information about <code>UriCompliance</code> see also <a href="../programming-guide/index.html#pg-server-compliance-uri">this section</a>.</p>
</div>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1"><code>jetty.httpConfig.requestCookieCompliance</code></dt>
<dt class="hdlist1"><code>jetty.httpConfig.responseCookieCompliance</code></dt>
<dd>
<p>Configures the compliance to HTTP cookie specifications.
The value could be:</p>
<div class="ulist">
<ul>
<li>
<p>One of the predefined <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/http/CookieCompliance.html"><code>CookieCompliance</code></a> constants, such as <code>RFC6265</code>.
For example: <code>jetty.httpConfig.compliance=RFC6265</code>.</p>
</li>
<li>
<p>A comma-separated list of violations to allow or forbid, as specified by the <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/http/CookieCompliance.html#from(java.lang.String)"><code>CookieCompliance.from(String)</code></a> method.
For example, <code>jetty.httpConfig.requestCookieCompliance=RFC6265,-RESERVED_NAMES_NOT_DOLLAR_PREFIXED</code> means that the cookie compliance is that defined by <code>RFC6265</code>, but also does not allow the <code>CookieCompliance.Violation.RESERVED_NAMES_NOT_DOLLAR_PREFIXED</code>, so that requests that have cookie headers such as <code>Cookie: $foo=bar</code> are rejected (they would be accepted when using just <code>CookieCompliance.RFC6265</code>).</p>
<div class="paragraph">
<p>For more information about <code>CookieCompliance</code> see also <a href="../programming-guide/index.html#pg-server-compliance-cookie">this section</a>.</p>
</div>
</li>
</ul>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect5">
<h6 id="og-module-scheduler-config"><a class="anchor" href="#og-module-scheduler-config"></a><a class="link" href="#og-module-scheduler-config">Server Scheduler Configuration Properties</a></h6>
<div class="paragraph">
<p>The module properties to configure the Jetty server scheduler are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>### Server Scheduler Configuration
## The scheduler thread name, defaults to "Scheduler-{hashCode()}" if blank.
# jetty.scheduler.name=
## Whether the server scheduler threads are daemon.
# jetty.scheduler.daemon=false
## The number of server scheduler threads.
# jetty.scheduler.threads=1</pre>
</div>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-module-ssl"><a class="anchor" href="#og-module-ssl"></a><a class="link" href="#og-module-ssl">Module <code>ssl</code></a></h5>
<div class="paragraph">
<p>The <code>ssl</code> module provides the secure connector, and allows you to configure the KeyStore properties and the TLS parameters, and depends on the <a href="#og-module-server"><code>server</code> module</a>.</p>
</div>
<div class="sect5">
<h6 id="og-module-ssl-connector"><a class="anchor" href="#og-module-ssl-connector"></a><a class="link" href="#og-module-ssl-connector">Secure Connector Properties</a></h6>
<div class="paragraph">
<p>The module properties to configure the secure connector are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>### TLS (SSL) Connector Configuration
## The host/address to bind the connector to.
# jetty.ssl.host=0.0.0.0
## The port the connector listens on.
# jetty.ssl.port=8443
## The connector idle timeout, in milliseconds.
# jetty.ssl.idleTimeout=30000
## The number of acceptors (-1 picks a default value based on number of cores).
# jetty.ssl.acceptors=1
## The number of selectors (-1 picks a default value based on number of cores).
# jetty.ssl.selectors=-1
## The ServerSocketChannel accept queue backlog (0 picks the platform default).
# jetty.ssl.acceptQueueSize=0
## The thread priority delta to give to acceptor threads.
# jetty.ssl.acceptorPriorityDelta=0
## Whether to enable the SO_REUSEADDR socket option.
# jetty.ssl.reuseAddress=true
## Whether to enable the SO_REUSEPORT socket option.
# jetty.ssl.reusePort=false
## Whether to enable the TCP_NODELAY socket option on accepted sockets.
# jetty.ssl.acceptedTcpNoDelay=true
## The SO_RCVBUF socket option to set on accepted sockets.
## A value of -1 indicates that the platform default is used.
# jetty.ssl.acceptedReceiveBufferSize=-1
## The SO_SNDBUF socket option to set on accepted sockets.
## A value of -1 indicates that the platform default is used.
# jetty.ssl.acceptedSendBufferSize=-1
## Whether client SNI data is required for all secure connections.
## When SNI is required, clients that do not send SNI data are rejected with an HTTP 400 response.
# jetty.ssl.sniRequired=false
## Whether client SNI data is checked to match CN and SAN in server certificates.
## When SNI is checked, if the match fails the connection is rejected with an HTTP 400 response.
# jetty.ssl.sniHostCheck=true
## The max age, in seconds, for the Strict-Transport-Security response header.
# jetty.ssl.stsMaxAgeSeconds=31536000
## Whether to include the subdomain property in any Strict-Transport-Security header.
# jetty.ssl.stsIncludeSubdomains=true</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.ssl.port</code></dt>
<dd>
<p>The network port that Jetty listens to for secure connections&#8201;&#8212;&#8201;default <code>8443</code>.</p>
</dd>
<dt class="hdlist1"><code>jetty.ssl.idleTimeout</code></dt>
<dd>
<p>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&#8201;&#8212;&#8201;default <code>30000</code> milliseconds.</p>
</dd>
<dt class="hdlist1"><code>jetty.ssl.acceptors</code></dt>
<dd>
<p>The number of threads that compete to accept connections&#8201;&#8212;&#8201;default 1. Use -1 to let the accept heuristic decides the value; the current heuristic calculates a value based on the number of cores).
Refer to <a href="#og-module-http-acceptors">this section</a> for more information about acceptor threads.</p>
</dd>
<dt class="hdlist1"><code>jetty.ssl.selectors</code></dt>
<dd>
<p>The number of NIO selectors (with an associated thread) that manage connections&#8201;&#8212;&#8201;default -1 (i.e. a select heuristic decides the value; the current heuristic calculates a value based on the number of cores).
Refer to <a href="#og-module-http-selectors">this section</a> for more information about selector threads.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The module properties to configure the KeyStore and TLS parameters are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>### SslContextFactory Configuration
## Note that OBF passwords are not secure, just protected from casual observation.
## Whether client SNI data is required for all secure connections.
## When SNI is required, clients that do not send SNI data are rejected with a TLS handshake error.
# jetty.sslContext.sniRequired=false
## The Endpoint Identification Algorithm.
## Same as javax.net.ssl.SSLParameters#setEndpointIdentificationAlgorithm(String).
# jetty.sslContext.endpointIdentificationAlgorithm=
## The JSSE Provider.
# jetty.sslContext.provider=
## The KeyStore file path (relative to $JETTY_BASE).
# jetty.sslContext.keyStorePath=etc/keystore.p12
## The KeyStore absolute file path.
# jetty.sslContext.keyStoreAbsolutePath=${jetty.base}/etc/keystore.p12
## The TrustStore file path (relative to $JETTY_BASE).
# jetty.sslContext.trustStorePath=etc/keystore.p12
## The TrustStore absolute file path.
# jetty.sslContext.trustStoreAbsolutePath=${jetty.base}/etc/keystore.p12
## The KeyStore password.
# jetty.sslContext.keyStorePassword=
## The Keystore type.
# jetty.sslContext.keyStoreType=PKCS12
## The KeyStore provider.
# jetty.sslContext.keyStoreProvider=
## The KeyManager password.
# jetty.sslContext.keyManagerPassword=
## The TrustStore password.
# jetty.sslContext.trustStorePassword=
## The TrustStore type.
# jetty.sslContext.trustStoreType=PKCS12
## The TrustStore provider.
# jetty.sslContext.trustStoreProvider=
## Whether client certificate authentication is required.
# jetty.sslContext.needClientAuth=false
## Whether client certificate authentication is desired, but not required.
# jetty.sslContext.wantClientAuth=false
## Whether cipher order is significant.
# jetty.sslContext.useCipherSuitesOrder=true
## The SSLSession cache size.
# jetty.sslContext.sslSessionCacheSize=-1
## The SSLSession cache timeout (in seconds).
# jetty.sslContext.sslSessionTimeout=-1
## Whether TLS renegotiation is allowed.
# jetty.sslContext.renegotiationAllowed=true
## The max number of TLS renegotiations per connection.
# jetty.sslContext.renegotiationLimit=5</pre>
</div>
</div>
</div>
<div class="sect5">
<h6 id="og-module-ssl-keystore-tls"><a class="anchor" href="#og-module-ssl-keystore-tls"></a><a class="link" href="#og-module-ssl-keystore-tls">KeyStore Properties and TLS Properties</a></h6>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.sslContext.keyStorePath</code></dt>
<dd>
<p>The KeyStore path on the file system relative to <code>$JETTY_BASE</code>&#8201;&#8212;&#8201;defaults to <code>$JETTY_BASE/etc/keystore.p12</code>.</p>
</dd>
<dt class="hdlist1"><code>jetty.sslContext.keyStorePassword</code></dt>
<dd>
<p>The KeyStore password, which you want to explicitly configure.
The password may be obfuscated with the <a href="#og-password">Jetty Password Tool</a>.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>If you need to configure client certificate authentication, you want to configure one of these properties (they are mutually exclusive):</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.sslContext.needClientAuth</code></dt>
<dd>
<p>Whether client certificate authentication should be required.</p>
</dd>
<dt class="hdlist1"><code>jetty.sslContext.wantClientAuth</code></dt>
<dd>
<p>Whether client certificate authentication should be requested.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>If you configure client certificate authentication, you need to configure and distribute a client KeyStore as explained in <a href="#og-keystore-client-authn">this section</a>.</p>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-module-ssl-reload"><a class="anchor" href="#og-module-ssl-reload"></a><a class="link" href="#og-module-ssl-reload">Module <code>ssl-reload</code></a></h5>
<div class="paragraph">
<p>The <code>ssl-reload</code> module provides a periodic scanning of the directory where the KeyStore file resides.
When the scanning detects a change to the KeyStore file, the correspondent <code>SslContextFactory.Server</code> component is reloaded with the new KeyStore configuration.</p>
</div>
<div class="paragraph">
<p>The module properties are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre># Monitored directory scan period, in seconds.
# jetty.sslContext.reload.scanInterval=1</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-module-test-keystore"><a class="anchor" href="#og-module-test-keystore"></a><a class="link" href="#og-module-test-keystore">Module <code>test-keystore</code></a></h5>
<div class="paragraph">
<p>The <code>test-keystore</code> module creates on-the-fly a KeyStore containing a self-signed certificate for domain <code>localhost</code>.
The KeyStore file is automatically deleted when the JVM exits, and re-created when you restart Jetty, to enforce the fact that it is a <em>test</em> KeyStore that should not be reused if not for testing.</p>
</div>
<div class="paragraph">
<p>The module file is <code>$JETTY_HOME/modules/test-keystore.mod</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>[description]
Test keystore with self-signed SSL Certificate.
DO NOT USE IN PRODUCTION!!!
[tags]
demo
ssl
[depend]
ssl
[files]
maven://org.bouncycastle/bcpkix-jdk15on/${bouncycastle.version}|lib/bouncycastle/bcpkix-jdk15on-${bouncycastle.version}.jar
maven://org.bouncycastle/bcprov-jdk15on/${bouncycastle.version}|lib/bouncycastle/bcprov-jdk15on-${bouncycastle.version}.jar
[lib]
lib/jetty-keystore-${jetty.version}.jar
lib/bouncycastle/bcpkix-jdk15on-${bouncycastle.version}.jar
lib/bouncycastle/bcprov-jdk15on-${bouncycastle.version}.jar
[xml]
etc/jetty-test-keystore.xml
[ini]
bouncycastle.version?=1.62
jetty.webapp.addServerClasses+=,${jetty.base.uri}/lib/bouncycastle/
jetty.sslContext.keyStorePath?=etc/test-keystore.p12
jetty.sslContext.keyStoreType?=PKCS12
jetty.sslContext.keyStorePassword?=OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4</pre>
</div>
</div>
<div class="paragraph">
<p>Note how properties <code>jetty.sslContext.keyStorePath</code> and <code>jetty.sslContext.keyStorePassword</code> are configured, only if not already set (via the <code>?=</code> operator), directly in the module file, rather than in a <code>*.ini</code> file.
This is done to avoid that these properties accidentally overwrite a real KeyStore configuration.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-module-threadpool"><a class="anchor" href="#og-module-threadpool"></a><a class="link" href="#og-module-threadpool">Module <code>threadpool</code></a></h5>
<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 thread pool creates threads on demand up to <code>maxThreads</code>, and idle them out if they are not used.</p>
</div>
<div class="paragraph">
<p>Since Jetty uses the thread pool internally to execute critical tasks, it is not recommended to constrain the thread pool to small values of <code>maxThreads</code> with the purpose of limiting HTTP request concurrency, as this could very likely cause a server lockup when Jetty needs to run a critical task but there are no threads available.
Start with the default value of <code>maxThreads</code>, and tune for larger values if needed.</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>[description]
Enables and configures the Server ThreadPool.
[depends]
logging
[xml]
etc/jetty-threadpool.xml
[ini-template]
## Minimum number of pooled threads.
#jetty.threadPool.minThreads=10
## Maximum number of pooled threads.
#jetty.threadPool.maxThreads=200
## Number of reserved threads (-1 for heuristic).
#jetty.threadPool.reservedThreads=-1
## Thread idle timeout (in milliseconds).
#jetty.threadPool.idleTimeout=60000
## Whether to output a detailed dump.
#jetty.threadPool.detailedDump=false</pre>
</div>
</div>
<div class="paragraph">
<p>Among the configurable properties, the most relevant are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.threadPool.detailedDump</code></dt>
<dd>
<p>Whether the thread pool should dump the whole stack trace of each thread, or just the topmost stack frame&#8201;&#8212;&#8201;defaults to <code>false</code>.</p>
</dd>
<dt class="hdlist1"><code>jetty.threadPool.idleTimeout</code></dt>
<dd>
<p>The time, in milliseconds, after which an idle thread is released from the pool&#8201;&#8212;&#8201;defaults to 60000, i.e. 60 seconds.</p>
</dd>
<dt class="hdlist1"><code>jetty.threadPool.maxThreads</code></dt>
<dd>
<p>The max number of threads pooled by the thread pool&#8201;&#8212;&#8201;defaults to 200.</p>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-module-console-capture"><a class="anchor" href="#og-module-console-capture"></a><a class="link" href="#og-module-console-capture">Module <code>console-capture</code></a></h5>
<div class="paragraph">
<p>The <code>console-capture</code> module captures <code>System.out</code> and <code>System.err</code> output and appends it to a rolling file.</p>
</div>
<div class="paragraph">
<p>The file is rolled every day at the midnight of the configured timezone.
Old, rolled files are kept for the number of days specified by the <code>jetty.console-capture.retainDays</code> property.</p>
</div>
<div class="paragraph">
<p>The module properties are:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>## Logging directory (relative to $JETTY_BASE).
# jetty.console-capture.dir=./logs
## Whether to append to existing file.
# jetty.console-capture.append=true
## How many days to retain old log files.
# jetty.console-capture.retainDays=90
## Timezone ID of the log timestamps, as specified by java.time.ZoneId.
# jetty.console-capture.timezone=GMT</pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-deploy"><a class="anchor" href="#og-deploy"></a><a class="link" href="#og-deploy">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="CodeRay 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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/wiki<span class="tag">&lt;/Set&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/myapps/myapp.war<span class="tag">&lt;/Set&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;/Configure&gt;</span></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="https://www.eclipse.org/jetty/javadoc/jetty-10/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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/wiki<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span><span class="tag">&lt;SystemProperty</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">myapps.dir</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>/myapp.war<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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 a <a href="#og-jndi-xml">Jetty XML file</a>, for example a context XML like so:</p>
</div>
<div class="listingblock">
<div class="title">mywebapp.xml</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;<a href="https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt" class="bare">https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt</a>;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">wac</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/mywebapp<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/webapps/mywebapp.war<span class="tag">&lt;/Set&gt;</span>
<mark><span class="entity">&nbsp;</span><span class="entity">&nbsp;</span><span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Resource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">wac</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>jdbc/myds<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">com.mysql.cj.jdbc.MysqlConnectionPoolDataSource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">url</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>jdbc:mysql://localhost:3306/databasename<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">user</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>user<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">password</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>password<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span></mark>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>For more information and examples on how to use JNDI in Jetty, refer to the <a href="#og-jndi">JNDI</a> feature section.</p>
</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 on the server&#8217;s classpath .</p>
</div>
<div class="paragraph">
<p>If the class is instead present <em>within</em> the web application, then the JNDI entry must be declared in a <code>WEB-INF/jetty-env.xml</code> file - see the <a href="#og-jndi">JNDI</a> feature section for more information and examples.</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="https://www.eclipse.org/jetty/javadoc/jetty-10/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 server <code>Connector</code> name to indicate that a web application should handle requests received on the server <code>Connector</code> with that name, and therefore received on a specific socket address (either an IP port for <code>ServerConnector</code>, or a Unix-Domain path for <code>UnixDomainServerConnector</code>).
A server <code>Connector</code> name can be set via <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/server/AbstractConnector.html#setName(java.lang.String)" class="bare">https://www.eclipse.org/jetty/javadoc/jetty-10/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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/mywebapp<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/webapps/mywebapp.war<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">virtualHosts</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Array</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Item&gt;</span>mywebapp.com<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>www.mywebapp.com<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>mywebapp.net<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>www.mywebapp.net<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Array&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/webapps/domain.war<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">virtualHosts</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Array</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Item&gt;</span>domain.biz<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Array&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">hobby.xml</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/webapps/hobby.war<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">virtualHosts</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Array</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Item&gt;</span>hobby.net<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Array&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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 socket addresses (either different IP ports, or different Unix-Domain paths), and therefore from different server <code>Connector</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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/webapps/domain.war<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">virtualHosts</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Array</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Item&gt;</span>@port8080<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Array&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">hobby.xml</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/webapps/hobby.war<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">virtualHosts</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Array</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Item&gt;</span>@port9090<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Array&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/mywebapp<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/webapps/mywebapp.war<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">extractWAR</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>false<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/mywebapp<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/webapps/mywebapp.war<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">overrideDescriptor</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/webapps/mywebapp-web.xml<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><table class="CodeRay"><tr>
<td class="line-numbers"><pre>1
2
3
4
5
6
7
8
9
<strong class="highlighted">10</strong>
<strong class="highlighted">11</strong>
12
13
</pre></td>
<td class="code"><pre><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="tag">&lt;web-app</span> <span class="attribute-name">xmlns</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">http://xmlns.jcp.org/xml/ns/javaee</span><span class="delimiter">&quot;</span></span>
<span class="attribute-name">xmlns:xsi</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">http://www.w3.org/2001/XMLSchema-instance</span><span class="delimiter">&quot;</span></span>
<span class="attribute-name">xsi:schemaLocation</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd</span><span class="delimiter">&quot;</span></span>
<span class="attribute-name">version</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">4.0</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;servlet&gt;</span>
<span class="tag">&lt;servlet-name&gt;</span>my-servlet<span class="tag">&lt;/servlet-name&gt;</span>
<span class="tag">&lt;init-param&gt;</span>
<span class="tag">&lt;param-name&gt;</span>host<span class="tag">&lt;/param-name&gt;</span>
<span class="tag">&lt;param-value&gt;</span>192.168.0.13<span class="tag">&lt;/param-value&gt;</span>
<span class="tag">&lt;/init-param&gt;</span>
<span class="tag">&lt;/servlet&gt;</span>
<span class="tag">&lt;/web-app&gt;</span></pre></td>
</tr></table></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">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">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="CodeRay 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="CodeRay 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">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 class="CodeRay highlight nowrap"><code>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</code></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="CodeRay 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 creates on-the-fly 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 class="CodeRay highlight nowrap"><code>INFO : test-keystore initialized in ${jetty.base}/start.d/test-keystore.ini
INFO : mkdir ${jetty.base}/lib/bouncycastle
INFO : copy /path/to/maven.repository/org/bouncycastle/bcpkix-jdk15on/1.62/bcpkix-jdk15on-1.62.jar to ${jetty.base}/lib/bouncycastle/bcpkix-jdk15on-1.62.jar
INFO : copy /path/to/maven.repository/org/bouncycastle/bcprov-jdk15on/1.62/bcprov-jdk15on-1.62.jar to ${jetty.base}/lib/bouncycastle/bcprov-jdk15on-1.62.jar
INFO : Base directory was modified</code></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="CodeRay 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="CodeRay highlight nowrap"><code><strong>2021-10-06 14:48:22.408:</strong>WARN :oejk.KeystoreGenerator:main: Generating Test Keystore: DO NOT USE IN PRODUCTION!
<strong>2021-10-06 14:48:23.051:</strong>INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17+35
<strong>2021-10-06 14:48:23.160:</strong>INFO :oejus.SslContextFactory:main: x509=X509@7975d1d8(jetty-test-keystore,h=[localhost],a=[],w=[]) for Server@24105dc5[provider=null,keyStore=file:///path/to/jetty.base/etc/test-keystore.p12,trustStore=null]
<strong>2021-10-06 14:48:23.267:</strong>INFO :oejs.AbstractConnector:main: Started ServerConnector@5c45d770<mark>{SSL, (ssl, http/1.1)}{0.0.0.0:8443}</mark>
<strong>2021-10-06 14:48:23.282:</strong>INFO :oejs.Server:main: Started Server@72c8e7b{STARTING}[10.0.7,sto=5000] @1919ms</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="images/diag-e2488cc783b3434076c5a44ee7f19a2b.png" alt="Diagram" width="376" 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="images/diag-8a7fb4bb9c84453a4bf01a24558e8026.png" alt="Diagram" width="413" 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="images/diag-7387dfbb6f9fb9cfa951a697aca488a8.png" alt="Diagram" width="135" height="284">
</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="images/diag-70817cc5c7137abc9759cdcd3edbb658.png" alt="Diagram" width="219" height="397">
</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="images/diag-2830e38460d606111888c5df2a645163.png" alt="Diagram" width="332" height="623">
</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">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 creates on-the-fly 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="CodeRay highlight nowrap"><code><strong>2021-10-06 14:48:25.851:</strong>WARN :oejk.KeystoreGenerator:main: Generating Test Keystore: DO NOT USE IN PRODUCTION!
<strong>2021-10-06 14:48:26.408:</strong>INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17+35
<strong>2021-10-06 14:48:26.537:</strong>INFO :oejus.SslContextFactory:main: x509=X509@7bf3a5d8(jetty-test-keystore,h=[localhost],a=[],w=[]) for Server@39b43d60[provider=null,keyStore=file:///path/to/jetty.base/etc/test-keystore.p12,trustStore=null]
<strong>2021-10-06 14:48:26.664:</strong>INFO :oejs.AbstractConnector:main: Started ServerConnector@414cb560<mark>{SSL, (ssl, alpn, h2, http/1.1)}{0.0.0.0:8443}</mark>
<strong>2021-10-06 14:48:26.681:</strong>INFO :oejs.Server:main: Started Server@730d2164{STARTING}[10.0.7,sto=5000] @1930ms</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">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="CodeRay highlight nowrap"><code><strong>2021-10-06 14:48:28.384:</strong>INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17+35
<strong>2021-10-06 14:48:28.443:</strong>INFO :oejs.AbstractConnector:main: Started ServerConnector@40e233c3<mark>{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:8080}</mark>
<strong>2021-10-06 14:48:28.458:</strong>INFO :oejs.Server:main: Started Server@45b9a632{STARTING}[10.0.7,sto=5000] @874ms</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, HTTP/2 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> (or <code>tls+http/2</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 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>The <a href="#og-module-ssl"><code>ssl</code> Jetty module</a> allows you to configure a secure network connector; 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.
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.
If you enable <em>both</em> the <code>https</code> and the <code>http2</code> module, you will have a single secure connector that will be able to interpret both HTTP/1.1 and HTTP/2.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
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.
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="og-protocols-ssl-customize"><a class="anchor" href="#og-protocols-ssl-customize"></a><a class="link" href="#og-protocols-ssl-customize">Customizing KeyStore and SSL/TLS Configuration</a></h5>
<div class="paragraph">
<p>Secure protocols have a slightly more complicated configuration since they require to configure a <em>KeyStore</em>.
Refer to the <a href="#og-keystore">KeyStore section</a> for more information about how to create and manage a KeyStore.</p>
</div>
<div class="paragraph">
<p>For simple cases, you only need to configure the KeyStore path and KeyStore password as explained in <a href="#og-module-ssl-keystore-tls">this section</a>.</p>
</div>
<div class="paragraph">
<p>For more advanced configuration you may want to configure the TLS protocol versions, or the ciphers to include/exclude, etc.
The correct way of doing this is to create a custom <a href="#og-xml">Jetty XML file</a> and reference it in <code>$JETTY_BASE/start.d/ssl.ini</code>:</p>
</div>
<div class="listingblock">
<div class="title">ssl.ini</div>
<div class="content">
<pre class="CodeRay highlight"><code>jetty.sslContext.keyStorePassword=my_passwd! <i class="conum" data-value="1"></i><b>(1)</b>
etc/tls-config.xml <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>Configures the <code>jetty.sslContext.keyStorePassword</code> property with the KeyStore password.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>References your newly created <code>$JETTY_BASE/etc/tls-config.xml</code>.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The <code>ssl.ini</code> file above only shows the lines that are not commented out (you can leave the lines that are commented unmodified for future reference).</p>
</div>
<div class="paragraph">
<p>You want to create the <code>$JETTY_BASE/etc/tls-config.xml</code> with the following template content:</p>
</div>
<div class="listingblock">
<div class="title">tls-config.xml</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;http://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">sslContextFactory</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
... <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;/Ref&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Here goes your advanced configuration.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The <code>tls-config.xml</code> file references the <code>sslContextFactory</code> component (created by the <code>ssl</code> Jetty module) that configures the KeyStore and TLS parameters, so that you can now call its APIs via XML, and you will have full flexibility for any advanced configuration you want (see below for few examples).</p>
</div>
<div class="paragraph">
<p>Refer to the <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/util/ssl/SslContextFactory.html">SslContextFactory javadocs</a> for the list of methods that you can call through the Jetty XML file.</p>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
Use module properties whenever possible, and only resort to use a Jetty XML file for advanced configuration that you cannot do using module properties.
</td>
</tr>
</table>
</div>
<div class="sect5">
<h6 id="og-protocols-ssl-customize-versions"><a class="anchor" href="#og-protocols-ssl-customize-versions"></a><a class="link" href="#og-protocols-ssl-customize-versions">Customizing SSL/TLS Protocol Versions</a></h6>
<div class="paragraph">
<p>By default, the SSL protocols (SSL, SSLv2, SSLv3, etc.) are already excluded because they are vulnerable.
To explicitly add the exclusion of TLSv1.0 and TLSv1.1 (that are also vulnerable&#8201;&#8212;&#8201;which leaves only TLSv1.2 and TLSv1.3 available), you want to use this XML:</p>
</div>
<div class="listingblock">
<div class="title">tls-config.xml</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;http://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">sslContextFactory</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">addExcludeProtocols</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;Array</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Item&gt;</span>TLSv1.0<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>TLSv1.1<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Array&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Ref&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect5">
<h6 id="og-protocols-ssl-customize-ciphers"><a class="anchor" href="#og-protocols-ssl-customize-ciphers"></a><a class="link" href="#og-protocols-ssl-customize-ciphers">Customizing SSL/TLS Ciphers</a></h6>
<div class="paragraph">
<p>You can precisely set the list of excluded ciphers, completely overriding Jetty&#8217;s default, with this XML:</p>
</div>
<div class="listingblock">
<div class="title">tls-config.xml</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;http://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">sslContextFactory</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">ExcludeCipherSuites</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Array</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Item&gt;</span>^TLS_RSA_.*$<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>^.*_RSA_.*_(MD5|SHA|SHA1)$<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>^.*_DHE_RSA_.*$<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>SSL_RSA_WITH_DES_CBC_SHA<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>SSL_DHE_RSA_WITH_DES_CBC_SHA<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>SSL_DHE_DSS_WITH_DES_CBC_SHA<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>SSL_RSA_EXPORT_WITH_RC4_40_MD5<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Array&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Ref&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how each array item specifies a <em>regular expression</em> that matches multiple ciphers, or specifies a precise cipher to exclude.</p>
</div>
<div class="paragraph">
<p>You can choose to create multiple XML files, and reference them all from <code>$JETTY_BASE/start.d/ssl.ini</code>, or put all your custom configurations in a single XML file.</p>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-protocols-ssl-renew"><a class="anchor" href="#og-protocols-ssl-renew"></a><a class="link" href="#og-protocols-ssl-renew">Renewing the Certificates</a></h5>
<div class="paragraph">
<p>When you create a certificate, you must specify for how many days it is valid.</p>
</div>
<div class="paragraph">
<p>The typical validity is 90 days, and while this period may seem short, it has two advantages:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Reduces the risk in case of compromised/stolen keys.</p>
</li>
<li>
<p>Encourages automation, i.e. certificate renewal performed by automated tools (rather than manually) at scheduled times.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>To renew a certificate, you must go through the <a href="#og-keystore-create">same steps</a> you followed to create the certificate the first time, and then you can <a href="#og-protocols-ssl-reload">reload the KeyStore</a> without the need to stop Jetty.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-protocols-ssl-reload"><a class="anchor" href="#og-protocols-ssl-reload"></a><a class="link" href="#og-protocols-ssl-reload">Watching and Reloading the KeyStore</a></h5>
<div class="paragraph">
<p>Jetty can be configured to monitor the directory of the KeyStore file, and reload the <code>SslContextFactory</code> component if the KeyStore file changed.</p>
</div>
<div class="paragraph">
<p>This feature can be enabled by activating the <code>ssl-reload</code> Jetty module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=ssl-reload</pre>
</div>
</div>
<div class="paragraph">
<p>For more information about the configuration of the <code>ssl-reload</code> Jetty module, see <a href="#og-module-ssl-reload">this section</a>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-protocols-ssl-conscrypt"><a class="anchor" href="#og-protocols-ssl-conscrypt"></a><a class="link" href="#og-protocols-ssl-conscrypt">Using Conscrypt as SSL/TLS Provider</a></h5>
<div class="paragraph">
<p>By default, the standard TLS provider that comes with the JDK is used.</p>
</div>
<div class="paragraph">
<p>The standard TLS provider from OpenJDK is implemented in Java (no native code), and its performance is not optimal, both in CPU usage and memory usage.</p>
</div>
<div class="paragraph">
<p>A faster alternative, implemented natively, is Google&#8217;s <a href="https://github.com/google/conscrypt/">Conscrypt</a>, which is built on <a href="https://boringssl.googlesource.com/boringssl/">BoringSSL</a>, which is Google&#8217;s fork of <a href="https://www.openssl.org/">OpenSSL</a>.</p>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
As Conscrypt eventually binds to a native library, there is a higher risk that a bug in Conscrypt or in the native library causes a JVM crash, while the Java implementation will not cause a JVM crash.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>To use Conscrypt as the TLS provider just enable the <code>conscrypt</code> Jetty module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=conscrypt</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-protocols-ssl-sni"><a class="anchor" href="#og-protocols-ssl-sni"></a><a class="link" href="#og-protocols-ssl-sni">Configuring SNI</a></h5>
<div class="paragraph">
<p>Server Name Indication (SNI) is a TLS extension that clients send to indicate what domain they want to connect to during the initial TLS handshake.</p>
</div>
<div class="paragraph">
<p>Modern TLS clients (e.g. browsers) always send the SNI extension; however, older TLS clients may not send the SNI extension.</p>
</div>
<div class="paragraph">
<p>Being able to handle the SNI is important when you have <a href="#og-deploy-virtual-hosts">virtual hosts</a> and a KeyStore with multiple certificates, one for each domain.</p>
</div>
<div class="paragraph">
<p>For example, you may have deployed over a secure connector two web applications, both at context path <code>/</code>, one at virtual host <code>one.com</code> and one at virtual host <code>two.net</code>.
The KeyStore contains two certificates, one for <code>one.com</code> and one for <code>two.net</code>.</p>
</div>
<div class="paragraph">
<p>There are three <code>ssl</code> module properties that control the SNI behavior on the server: one that works at the TLS level, and two that works at the HTTP level.</p>
</div>
<div class="paragraph">
<p>The property that works at the TLS level is:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.sslContext.sniRequired</code></dt>
<dd>
<p>Whether SNI is required at the TLS level, defaults to <code>false</code>.
Its behavior is explained by the following table:</p>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. Behavior of the <code>jetty.sslContext.sniRequired</code> property</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>sniRequired=false</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>sniRequired=true</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>SNI = <code>null</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>client receives default certificate</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>client receives TLS failure</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>SNI = <code>wrong.org</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>client receives default certificate</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>client receives TLS failure</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>SNI = <code>one.com</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>client receives <code>one.com</code> certificate</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>client receives <code>one.com</code> certificate</p>
</div></div></td>
</tr>
</tbody>
</table>
<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>The <em>default certificate</em> is the certificate returned by the TLS implementation in case there is no SNI match, and you should not rely on this certificate to be the same across Java vendors and versions, or Jetty versions, or TLS provider vendors and versions.</p>
</div>
<div class="paragraph">
<p>In the example above it could be either the <code>one.com</code> certificate or the <code>two.net</code> certificate.</p>
</div>
</td>
</tr>
</table>
</div>
</dd>
</dl>
</div>
<div class="paragraph">
<p>When <code>jetty.sslContext.sniRequired=true</code>, clients that don&#8217;t send a valid SNI receive a TLS failure, and their attempt to connect to the server fails.
The details of this failure may not be reported and could be difficult to figure out that the failure is related to an invalid SNI.</p>
</div>
<div class="paragraph">
<p>For this reason, other two properties are defined at the HTTP level, so that clients can received an HTTP 400 response with more details about what went wrong while trying to connect to the server:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.ssl.sniRequired</code></dt>
<dd>
<p>Whether SNI is required at the HTTP level, defaults to <code>false</code>.
Its behavior is similar to the <code>jetty.sslContext.sniRequired</code> property above, and is explained by the following table:</p>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 2. Behavior of the <code>jetty.ssl.sniRequired</code> property</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>sniRequired=false</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>sniRequired=true</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>SNI = <code>null</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Accept</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Reject: 400 Bad Request</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>SNI = <code>wrong.org</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Accept</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Reject: 400 Bad Request</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>SNI = <code>one.com</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Accept</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Accept</p>
</div></div></td>
</tr>
</tbody>
</table>
</dd>
</dl>
</div>
<div class="paragraph">
<p>When <code>jetty.ssl.sniRequired=true</code>, the SNI is matched against the certificate sent to the client, and only if there is a match the request is accepted.</p>
</div>
<div class="paragraph">
<p>When the request is accepted, there could be an additional check controlled by the following property:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>jetty.ssl.sniHostCheck</code></dt>
<dd>
<p>Whether the certificate sent to the client matches the <code>Host</code> header, defaults to <code>true</code>.
Its behavior is explained by the following table:</p>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 3. Behavior of the <code>jetty.ssl.sniHostCheck</code> property</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>sniHostCheck=false</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p><code>sniHostCheck=true</code></p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>certificate = <code>one.com</code><br>
<code>Host: wrong.org</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Accept</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Reject: 400 Bad Request</p>
</div></div></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>certificate = <code>one.com</code><br>
<code>Host: one.com</code></p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Accept</p>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph">
<p>Accept</p>
</div></div></td>
</tr>
</tbody>
</table>
</dd>
</dl>
</div>
<div class="paragraph">
<p>In the normal case with the default server configuration, for a TLS clients that sends SNI, and then sends an HTTP request with the correct <code>Host</code> header, Jetty will pick the correct certificate from the KeyStore based on the SNI received from the client, and accept the request.</p>
</div>
<div class="paragraph">
<p>Accepting the request does not mean that the request is responded with an HTTP 200 OK, but just that the request passed successfully the SNI checks and will be processed by the server.
If the request URI is for a resource that does not exist, the response will likely be a 404 Not Found.</p>
</div>
<div class="paragraph">
<p>You may modify the default values of the SNI properties if you want stricter control over old/broken TLS clients or bad HTTP requests.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-protocols-proxy"><a class="anchor" href="#og-protocols-proxy"></a><a class="link" href="#og-protocols-proxy">Jetty Behind a Load Balancer or Reverse Proxy</a></h4>
<div class="paragraph">
<p>You may need to configure one or more Jetty instances behind an <em>intermediary</em>, typically a load balancer such as <a href="https://haproxy.org">HAProxy</a>, or a reverse proxy such as <a href="https://httpd.apache.org">Apache HTTP Server</a> or <a href="https://nginx.org">Nginx</a>.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/diag-9f323b812fd1edc8217715ca0c2ba8e9.png" alt="Diagram" width="247" height="405">
</div>
</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>HAProxy can communicate either HTTP/1.1 or HTTP/2 to backend servers such as Jetty.</p>
</div>
<div class="paragraph">
<p>Apache HTTP Server and Nginx can only speak HTTP/1.1 to backend servers such as Jetty, and have no plans to support HTTP/2 towards backend servers.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>In these setups, typically the proxy performs TLS offloading, and the communication with backend servers happens in clear-text.
It is possible, however, to configure the proxy so that all the bytes arriving from the client are tunnelled opaquely to the backend Jetty server (that therefore needs to perform the TLS offloading) and viceversa the bytes arriving from the Jetty server are tunnelled opaquely to the client.</p>
</div>
<div class="paragraph">
<p>Also in these setups, the TCP/IP connection terminating on the Jetty servers does not originate from the client, but from the proxy, so that the remote IP address and port number may be reported incorrectly in backend server logs, or worse applications may not work because they need to be able to differentiate different clients based on the client IP address.</p>
</div>
<div class="paragraph">
<p>For this reason, intermediaries typically implement at least one of several <em>de facto</em> standards to communicate information about the original client connection to the backend Jetty server.</p>
</div>
<div class="paragraph">
<p>Jetty supports two methods to process client information sent by intermediaries:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The <code>Forwarded</code> HTTP header, defined in <a href="https://tools.ietf.org/html/rfc7239">RFC 7239</a> and replacing the old <code>X-Forwarded-*</code> headers, defined in <a href="#og-protocols-proxy-forwarded">this section</a>.</p>
</li>
<li>
<p>The <a href="https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt">Proxy Protocol</a>, defined in <a href="#og-protocols-proxy-protocol">this section</a>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>In both methods, web applications that call <code>HttpServletRequest.getRemoteAddr()</code> will receive the remote client IP address as specified by the client information sent by the intermediary, not the physical IP address of TCP connection with the intermediary.
Likewise, <code>HttpServletRequest.getRemotePort()</code> will return the remote client IP port as specified by the client information sent by the intermediary, and <code>HttpServletRequest.isSecure()</code> will return whether the client made a secure request using the <code>https</code> scheme as specified by the client information sent by the intermediary.</p>
</div>
<div class="sect4">
<h5 id="og-protocols-proxy-forwarded"><a class="anchor" href="#og-protocols-proxy-forwarded"></a><a class="link" href="#og-protocols-proxy-forwarded">Configuring the Forwarded Header</a></h5>
<div class="paragraph">
<p>The <code>Forwarded</code> HTTP header is added by the intermediary with information about the client and the client request, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>GET / HTTP/1.1
Host: domain.com
Forwarded: for=2.36.72.144:21216;proto=https</pre>
</div>
</div>
<div class="paragraph">
<p>In the example above, the intermediary added the <code>Forwarded</code> header specifying that the client remote address is <code>2.36.72.144:21216</code> and that the request was made with the <code>https</code> scheme.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s assume you have already configured Jetty with the HTTP/1.1 protocol 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="paragraph">
<p>Support for the <code>Forwarded</code> HTTP header (and its predecessor <code>X-Forwarded-*</code> headers) is enabled with the <code>http-forwarded</code> Jetty module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=http-forwarded</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>INFO : http-forwarded initialized in ${jetty.base}/start.d/http-forwarded.ini
INFO : Base directory was modified</code></pre>
</div>
</div>
<div class="paragraph">
<p>With the <code>http-forwarded</code> Jetty module enabled, Jetty interprets the <code>Forwarded</code> header and makes its information available to web applications via the standard Servlet APIs.</p>
</div>
<div class="paragraph">
<p>For further information about configuring the <code>http-forwarded</code> Jetty module, see <a href="#og-module-http-forwarded">this section</a>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-protocols-proxy-protocol"><a class="anchor" href="#og-protocols-proxy-protocol"></a><a class="link" href="#og-protocols-proxy-protocol">Configuring the Proxy Protocol</a></h5>
<div class="paragraph">
<p>The <a href="https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt">Proxy Protocol</a> is the <em>de facto</em> standard, introduced by <a href="https://haproxy.org">HAProxy</a>, to communicate client information to backend servers via the TCP connection, rather than via HTTP headers.</p>
</div>
<div class="paragraph">
<p>The information about the client connection is sent as a small data frame on each newly established connection.
This mechanism is therefore independent of any protocol, so it can be used for TLS, HTTP/1.1, HTTP/2, etc.</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>There are 2 versions of the proxy protocol: v1 and v2, both supported by Jetty.</p>
</div>
<div class="paragraph">
<p>Proxy protocol v1 is human readable, but it only carries information about the client TCP connection (IP address and IP port).</p>
</div>
<div class="paragraph">
<p>Proxy protocol v2 has a binary format, carries the information about the client TCP connection, and can carry additional arbitrary information encoded in pairs <code>(type, value)</code> where <code>type</code> is a single byte that indicates the value&#8217;s meaning, and <code>value</code> is a variable length byte array that can encode user-defined data.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Support for the proxy protocol can be enabled for the clear-text connector or for the secure connector (or both).</p>
</div>
<div class="paragraph">
<p>Let&#8217;s assume you have already configured Jetty with the HTTP/1.1 clear-text protocol 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="paragraph">
<p>To enable proxy protocol support for the clear-text connector, enable the <code>proxy-protocol</code> Jetty module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=proxy-protocol</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>INFO : proxy-protocol initialized in ${jetty.base}/start.d/proxy-protocol.ini
INFO : Base directory was modified</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="CodeRay highlight nowrap"><code><strong>2021-10-06 14:48:31.734:</strong>INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17+35
<strong>2021-10-06 14:48:31.784:</strong>INFO :oejs.AbstractConnector:main: Started ServerConnector@bef2d72<mark>{[proxy], ([proxy], http/1.1)}{0.0.0.0:8080}</mark>
<strong>2021-10-06 14:48:31.797:</strong>INFO :oejs.Server:main: Started Server@b62fe6d{STARTING}[10.0.7,sto=5000] @815ms</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how in the example above the list of protocols for the clear-text connector is first <code>proxy</code> and then <code>http/1.1</code>.
For every new TCP connection, Jetty first interprets the proxy protocol bytes with the client information; after this initial proxy protocol processing, Jetty interprets the incoming bytes as HTTP/1.1 bytes.</p>
</div>
<div class="paragraph">
<p>Enabling proxy protocol support for the secure connector is similar.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s assume you have already configured Jetty with the HTTP/1.1 secure protocol and the test KeyStore 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=https,test-keystore</pre>
</div>
</div>
<div class="paragraph">
<p>Enable the <code>proxy-protocol-ssl</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=proxy-protocol-ssl</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>INFO : proxy-protocol-ssl initialized in ${jetty.base}/start.d/proxy-protocol-ssl.ini
INFO : Base directory was modified</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="CodeRay highlight nowrap"><code><strong>2021-10-06 14:48:34.697:</strong>WARN :oejk.KeystoreGenerator:main: Generating Test Keystore: DO NOT USE IN PRODUCTION!
<strong>2021-10-06 14:48:35.293:</strong>INFO :oejs.Server:main: jetty-10.0.7; built: 2021-10-06T19:34:02.766Z; git: da8a4553af9dd84080931fa0f8c678cd2d60f3d9; jvm 17+35
<strong>2021-10-06 14:48:35.409:</strong>INFO :oejus.SslContextFactory:main: x509=X509@7d7758be(jetty-test-keystore,h=[localhost],a=[],w=[]) for Server@5f9edf14[provider=null,keyStore=file:///path/to/jetty.base/etc/test-keystore.p12,trustStore=null]
<strong>2021-10-06 14:48:35.520:</strong>INFO :oejs.AbstractConnector:main: Started ServerConnector@332729ad<mark>{[proxy], ([proxy], ssl, http/1.1)}{0.0.0.0:8443}</mark>
<strong>2021-10-06 14:48:35.535:</strong>INFO :oejs.Server:main: Started Server@4d14b6c2{STARTING}[10.0.7,sto=5000] @1882ms</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note how in the example above the list of protocols for the secure connector is first <code>proxy</code>, then <code>ssl</code> and then <code>http/1.1</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-protocols-proxy-haproxy"><a class="anchor" href="#og-protocols-proxy-haproxy"></a><a class="link" href="#og-protocols-proxy-haproxy">HAProxy and Jetty with HTTP/1.1 and HTTP/2</a></h5>
<div class="paragraph">
<p><a href="https://haproxy.org">HAProxy</a> is an open source solution that offers load balancing and proxying for TCP and HTTP based application, and can be used as a replacement for Apache or Nginx when these are used as reverse proxies.</p>
</div>
<div class="paragraph">
<p>The deployment proposed here has HAProxy playing the role that Apache and Nginx usually do: to perform the TLS offloading (that is, decrypt incoming bytes and encrypt outgoing bytes) and then forwarding the now clear-text traffic to a backend Jetty server, speaking either HTTP/1.1 or HTTP/2.
Since HAProxy&#8217;s TLS offloading is based on OpenSSL, it is much more efficient than the Java implementation shipped with OpenJDK.</p>
</div>
<div class="paragraph">
<p>After you have installed HAProxy on your system, you want to configure it so that it can perform TLS offloading.</p>
</div>
<div class="paragraph">
<p>HAProxy will need a single file containing the X509 certificates and the private key, all in <a href="https://en.wikipedia.org/wiki/X.509">PEM format</a>, with the following order:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>The site certificate; this certificate&#8217;s Common Name refers to the site domain (for example: CN=*.webtide.com) and is signed by Certificate Authority #1.</p>
</li>
<li>
<p>The Certificate Authority #1 certificate; this certificate may be signed by Certificate Authority #2.</p>
</li>
<li>
<p>The Certificate Authority #2 certificate; this certificate may be signed by Certificate Authority #3; and so on until the Root Certificate Authority.</p>
</li>
<li>
<p>The Root Certificate Authority certificate.</p>
</li>
<li>
<p>The private key corresponding to the site certificate.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Refer to the <a href="#og-keystore">section about KeyStores</a> for more information about generating the required certificates and private key.</p>
</div>
<div class="paragraph">
<p>Now you can create the HAProxy configuration file (in Linux it&#8217;s typically <code>/etc/haproxy/haproxy.cfg</code>).
This is a minimal configuration:</p>
</div>
<div class="listingblock">
<div class="title">haproxy.cfg</div>
<div class="content">
<pre class="CodeRay highlight"><code>global
tune.ssl.default-dh-param 1024
defaults
timeout connect 10000ms
timeout client 60000ms
timeout server 60000ms
frontend fe_http <i class="conum" data-value="1"></i><b>(1)</b>
mode http
bind *:80
# Redirect to https
redirect scheme https code 301
frontend fe_https <i class="conum" data-value="2"></i><b>(2)</b>
mode tcp
bind *:443 ssl no-sslv3 crt /path/to/domain.pem ciphers TLSv1.2 alpn h2,http/1.1
default_backend be_http
backend be_http <i class="conum" data-value="3"></i><b>(3)</b>
mode tcp
server domain 127.0.0.1:8282 send-proxy-v2</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>fe_http</code> front-end accepts connections on port 80 and redirects them to use the <code>https</code> scheme.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The <code>fe_https</code> front-end accepts connections on port 443, and it is where the TLS decryption/encryption happens.
You must specify the path to the PEM file containing the TLS key material (the <code>crt /path/to/domain.pem</code> part), the ciphers that are suitable for HTTP/2 (<code>ciphers TLSv1.2</code>), and the ALPN protocols supported (<code>alpn h2,http/1.1</code>).
This front-end then forwards the now decrypted bytes to the backend in <code>mode tcp</code>.
The <code>mode tcp</code> says that HAProxy will not try to interpret the bytes but instead opaquely forwards them to the backend.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>The <code>be_http</code> backend will forward (again in <code>mode tcp</code>) the clear-text bytes to a Jetty connector that talks clear-text HTTP/2 and HTTP/1.1 on port 8282.
The <code>send-proxy-v2</code> directive sends the proxy protocol v2 bytes to the backend server.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>On the Jetty side, you need to enable the following modules:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=proxy-protocol,http2c,http,deploy</pre>
</div>
</div>
<div class="paragraph">
<p>You need to specify the host (<code>127.0.0.1</code>) and port (<code>8282</code>) you have configured in HAProxy when you start Jetty:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar jetty.http.host=127.0.0.1 jetty.http.port=8282</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>You want the Jetty connector that listens on port <code>8282</code> to be available only to HAProxy, and not to remote clients.</p>
</div>
<div class="paragraph">
<p>For this reason, you want to specify the <code>jetty.http.host</code> property on the command line (or in <code>$JETTY_BASE/start.d/http.ini</code> to make this setting persistent) to bind the Jetty connector only on the loopback interface (<code>127.0.0.1</code>), making it available to HAProxy but not to remote clients.</p>
</div>
<div class="paragraph">
<p>If your Jetty instance runs on a different machine and/or on a different (sub)network, you may want to adjust both the back-end section of the HAProxy configuration file and the <code>jetty.http.host</code> property to match accordingly.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>With this configuration for HAProxy and Jetty, browsers supporting HTTP/2 will connect to HAProxy, which will decrypt the traffic and send it to Jetty.
Likewise, HTTP/1.1 clients will connect to HAProxy, which will decrypt the traffic and send it to Jetty.</p>
</div>
<div class="paragraph">
<p>The Jetty connector, configured with the <code>http2c</code> and the <code>http</code> modules is able to distinguish whether the incoming bytes are HTTP/2 or HTTP/1.1 and will handle the request accordingly.</p>
</div>
<div class="paragraph">
<p>The response is relayed back to HAProxy, which will encrypt it and send it back to the remote client.</p>
</div>
<div class="paragraph">
<p>This configuration offers you efficient TLS offloading, HTTP/2 support and transparent fallback to HTTP/1.1 for clients that don&#8217;t support HTTP/1.1.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-protocols-websocket"><a class="anchor" href="#og-protocols-websocket"></a><a class="link" href="#og-protocols-websocket">WebSocket</a></h4>
<div class="paragraph">
<p>WebSocket is a network protocol for bidirectional data communication initiated via the <a href="https://tools.ietf.org/html/rfc7230#section-6.7">HTTP/1.1 upgrade mechanism</a>.
WebSocket provides a simple, low-level, framing protocol layered over TCP.
One or more WebSocket frames compose a WebSocket <em>message</em> that is either a UTF-8 <em>text</em> message or <em>binary</em> message.</p>
</div>
<div class="paragraph">
<p>Jetty provides an implementation of the following standards and specifications.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><a href="http://tools.ietf.org/html/rfc6455">RFC-6455</a> - The WebSocket Protocol</dt>
<dd>
<p>Jetty supports version 13 of the released and final specification.</p>
</dd>
<dt class="hdlist1"><a href="http://www.jcp.org/en/jsr/detail?id=356">JSR-356</a> - The Java WebSocket API (<code>javax.websocket</code>)</dt>
<dd>
<p>This is the official Java API for working with WebSockets.</p>
</dd>
<dt class="hdlist1"><a href="https://tools.ietf.org/html/rfc7692">RFC-7692</a> - WebSocket Per-Message Deflate Extension</dt>
<dd>
<p>This is the replacement for perframe-compression, switching the compression to being based on the entire message, not the individual frames.</p>
</dd>
<dt class="hdlist1"><a href="https://tools.ietf.org/html/rfc8441">RFC-8441</a> - Bootstrapping WebSockets with HTTP/2</dt>
<dd>
<p>Allows a single stream of an HTTP/2 connection to be upgraded to WebSocket.
This allows one TCP connection to be shared by both protocols and extends HTTP/2&#8217;s more efficient use of the network to WebSockets.</p>
</dd>
</dl>
</div>
<div class="sect4">
<h5 id="og-protocols-websocket-configure"><a class="anchor" href="#og-protocols-websocket-configure"></a><a class="link" href="#og-protocols-websocket-configure">Configuring WebSocket</a></h5>
<div class="paragraph">
<p>Jetty provides two WebSocket implementations: one based on the Java WebSocket APIs defined by JSR 356, provided by module <code>websocket-javax</code>, and one based on Jetty specific WebSocket APIs, provided by module <code>websocket-jetty</code>.
The Jetty <code>websocket</code> module enables both implementations, but each implementation can be enabled independently.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Remember that a WebSocket connection is always initiated from the HTTP protocol (either an HTTP/1.1 upgrade or an HTTP/2 connect), therefore to enable WebSocket you need to enable HTTP.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>To enable WebSocket support, you also need to decide what version of the HTTP protocol you want WebSocket to be initiated from, and whether you want secure HTTP.</p>
</div>
<div class="paragraph">
<p>For example, to enable clear-text WebSocket from HTTP/1.1, 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=http,websocket</pre>
</div>
</div>
<div class="paragraph">
<p>To enable secure WebSocket from HTTP/2, 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=http2,websocket</pre>
</div>
</div>
<div class="paragraph">
<p>When enabling secure protocols you need a valid KeyStore (read <a href="#og-keystore">this section</a> to create your own KeyStore).
As a quick example, you can enable the <a href="#og-module-test-keystore"><code>test-keystore</code> module</a>, that creates on-the-fly 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>To enable WebSocket on both HTTP/1.1 and HTTP/2, both clear-text and secure, 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=http,https,http2c,http2,websocket</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-protocols-websocket-disable"><a class="anchor" href="#og-protocols-websocket-disable"></a><a class="link" href="#og-protocols-websocket-disable">Selectively Disabling WebSocket</a></h5>
<div class="paragraph">
<p>Enabling the WebSocket Jetty modules comes with a startup cost because Jetty must perform two steps:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Scan web applications <code>*.war</code> files (and all the jars and classes inside it) looking for WebSocket EndPoints classes (either annotated with WebSocket API annotations or extending/implementing WebSocket API classes/interfaces).
This can be a significant cost if your web application contains a lot of classes and/or jar files.</p>
</li>
<li>
<p>Configure and wire WebSocket EndPoints so that WebSocket messages are delivered to the correspondent WebSocket EndPoint.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>WebSocket support is by default enabled for all web applications.</p>
</div>
<div class="paragraph">
<p>For a specific web application, you can disable step 2 for Java WebSocket support (i.e. when the <code>websocket-javax</code> module is enabled) by setting the context attribute <code>org.eclipse.jetty.websocket.javax</code> to <code>false</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="tag">&lt;web-app</span> <span class="attribute-name">xmlns</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">http://xmlns.jcp.org/xml/ns/javaee</span><span class="delimiter">&quot;</span></span>
<span class="attribute-name">xmlns:xsi</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">http://www.w3.org/2001/XMLSchema-instance</span><span class="delimiter">&quot;</span></span>
<span class="attribute-name">xsi:schemaLocation</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd</span><span class="delimiter">&quot;</span></span>
<span class="attribute-name">version</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">4.0</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- Disable Javax WebSocket --&gt;</span>
<span class="tag">&lt;context-param&gt;</span>
<span class="tag">&lt;param-name&gt;</span>org.eclipse.jetty.websocket.javax<span class="tag">&lt;/param-name&gt;</span>
<span class="tag">&lt;param-value&gt;</span>false<span class="tag">&lt;/param-value&gt;</span>
<span class="tag">&lt;/context-param&gt;</span>
...
<span class="tag">&lt;/web-app&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Furthermore, for a specific web application, you can disable step 1 (and therefore also step 2) as described in the <a href="#og-annotations">annotations processing section</a>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-protocols-websocket-webapp-client"><a class="anchor" href="#og-protocols-websocket-webapp-client"></a><a class="link" href="#og-protocols-websocket-webapp-client">Using WebSocket Client in WebApps</a></h5>
<div class="paragraph">
<p>Web applications may need to use a WebSocket client to communicate with third party WebSocket services.</p>
</div>
<div class="paragraph">
<p>If the web application uses the Java WebSocket APIs, the WebSocket client APIs are provided by the Servlet Container and are available to the web application by enabling the WebSocket server APIs, and therefore you must enable the <code>websocket-javax</code> Jetty module.</p>
</div>
<div class="paragraph">
<p>However, the Java WebSocket Client APIs are quite limited (for example, they do not support secure WebSocket).
For this reason, web applications may want to use the Jetty WebSocket Client APIs.</p>
</div>
<div class="paragraph">
<p>When using the Jetty WebSocket Client APIs, web applications should include the required jars and their dependencies in the <code>WEB-INF/lib</code> directory of the <code>*.war</code> file.
Alternatively, when deploying your web applications in Jetty, you can enable the <code>websocket-jetty-client</code> Jetty module to allow web applications to use the Jetty WebSocket Client APIs provided by Jetty, without the need to include jars and their dependencies in the <code>*.war</code> file.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-keystore"><a class="anchor" href="#og-keystore"></a><a class="link" href="#og-keystore">Configuring SSL/TLS KeyStores</a></h3>
<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>Refer to the <a href="#og-protocols-ssl">secure protocols section</a> for more information about how to configure a secure connector using a KeyStore.</p>
</div>
<div class="sect3">
<h4 id="og-keystore-create"><a class="anchor" href="#og-keystore-create"></a><a class="link" href="#og-keystore-create">Creating a KeyStore</a></h4>
<div class="paragraph">
<p>KeyStores are created with the JDK tool <code>$JAVA_HOME/bin/keytool</code>.</p>
</div>
<div class="paragraph">
<p>The following command creates a KeyStore file containing a private key and a self-signed certificate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>keytool
-genkeypair <i class="conum" data-value="1"></i><b>(1)</b>
-alias mykey <i class="conum" data-value="2"></i><b>(2)</b>
-validity 90 <i class="conum" data-value="3"></i><b>(3)</b>
-keyalg RSA <i class="conum" data-value="4"></i><b>(4)</b>
-keysize 2048 <i class="conum" data-value="5"></i><b>(5)</b>
-keystore /path/to/keystore.p12 <i class="conum" data-value="6"></i><b>(6)</b>
-storetype pkcs12 <i class="conum" data-value="7"></i><b>(7)</b>
-dname &quot;CN=domain.com, OU=Unit, O=Company, L=City, S=State, C=Country&quot; <i class="conum" data-value="8"></i><b>(8)</b>
-ext san=dns:www.domain.com,dns:domain.org <i class="conum" data-value="9"></i><b>(9)</b>
-v <i class="conum" data-value="10"></i><b>(10)</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 command to generate a key and certificate pair</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>the alias name of the key and certificate pair</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>specifies the number of days after which the certificate expires</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>the algorithm <em>must</em> be RSA (the DSA algorithm does not work for web sites)</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>indicates the strength of the key</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>the KeyStore file</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>the KeyStore type, stick with the standard PKCS12</td>
</tr>
<tr>
<td><i class="conum" data-value="8"></i><b>8</b></td>
<td>the distinguished name (more below)&#8201;&#8212;&#8201;customize it with your values for CN, OU, O, L, S and C</td>
</tr>
<tr>
<td><i class="conum" data-value="9"></i><b>9</b></td>
<td>the extension with the subject alternative names (more below)</td>
</tr>
<tr>
<td><i class="conum" data-value="10"></i><b>10</b></td>
<td>verbose output</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The command prompts for the KeyStore password that you must choose to protect the access to the KeyStore.</p>
</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>The important parts of the command above are the <em>Common Name</em> (CN) part of the distinguished name, and the subject alternative names (SAN).</p>
</div>
<div class="paragraph">
<p>The CN value must be the main domain you own and that you want to use for your web applications.
For example, if you have bought domains <code>domain.com</code> and <code>domain.org</code>, you want to specify <code>CN=domain.com</code> as your main domain.</p>
</div>
<div class="paragraph">
<p>Furthermore, to specify additional domains or subdomains within the same certificate, you must specify the SAN extension.
In the example above, <code>san=dns:www.domain.com,dns:domain.org</code> specifies <code>www.domain.com</code> and <code>domain.org</code> as alternative names for your web applications (that you can configure using <a href="#og-deploy-virtual-hosts">virtual hosts</a>).</p>
</div>
<div class="paragraph">
<p>In rare cases, you may want to specify IP addresses, rather than domains, in the SAN extension.
The syntax in such case is <code>san=ip:127.0.0.1,ip:[::1]</code>, which specifies as subject alternative names IPv4 <code>127.0.0.1</code> and IPv6 <code>[::1]</code>.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="og-keystore-create-many"><a class="anchor" href="#og-keystore-create-many"></a><a class="link" href="#og-keystore-create-many">KeyStores with Multiple Entries</a></h5>
<div class="paragraph">
<p>A single KeyStore may contain multiple key/certificate pairs.
This is useful when you need to support multiple domains on the same Jetty server (typically accomplished using <a href="#og-deploy-virtual-hosts">virtual hosts</a>).</p>
</div>
<div class="paragraph">
<p>You can create multiple key/certificate pairs as detailed in the <a href="#og-keystore-create">previous section</a>, provided that you assign each one to a different alias.</p>
</div>
<div class="paragraph">
<p>Compliant TLS clients will send the <a href="#og-protocols-ssl-sni">TLS SNI extension</a> when creating new connections, and Jetty will automatically choose the right certificate by matching the SNI name sent by the client with the CN or SAN of certificates present in the KeyStore.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-keystore-csr"><a class="anchor" href="#og-keystore-csr"></a><a class="link" href="#og-keystore-csr">Creating a Certificate Signing Request</a></h4>
<div class="paragraph">
<p>Self-signed certificates are not trusted by browsers and generic clients: you need to establish a trust chain by having your self-signed certificate signed by a certificate authority (CA).</p>
</div>
<div class="paragraph">
<p>Browsers and generic clients (e.g. Java clients) have an internal list of trusted certificate authorities root certificates; they use these trusted certificates to verify the certificate they received from the server when they connect to your web applications.</p>
</div>
<div class="paragraph">
<p>To have your self-signed certificate signed by a certificate authority you first need to produce a <em>certificate signing request</em> (CSR):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>keytool
-certreq <i class="conum" data-value="1"></i><b>(1)</b>
-file domain.com.csr <i class="conum" data-value="2"></i><b>(2)</b>
-keystore keystore.p12 <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 command to generate a certificate signing request</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>the file to save the CSR</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>the keystore that contains the self-signed certificate</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Then, you have to send the CSR file to the certificate authority of your choice, and wait for their reply (they will probably require a proof that you really own the domains indicated in your certificate).</p>
</div>
<div class="paragraph">
<p>Eventually, the certificate authority will reply to you with one or more files containing the CA certificate chain, and your certificate signed by their certificate chain.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-keystore-csr-import"><a class="anchor" href="#og-keystore-csr-import"></a><a class="link" href="#og-keystore-csr-import">Importing the Signed Certificate</a></h4>
<div class="paragraph">
<p>The file you receive from the CA is typically in PEM format, and you <strong>must</strong> import it back into the same KeyStore file you used to generate the CSR.
You must import <strong>both</strong> the certificate chain and your signed certificate.</p>
</div>
<div class="paragraph">
<p>First, import the certificate chain:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>keytool
-importcert <i class="conum" data-value="1"></i><b>(1)</b>
-alias ca <i class="conum" data-value="2"></i><b>(2)</b>
-file chain_from_ca.pem <i class="conum" data-value="3"></i><b>(3)</b>
-keystore keystore.p12 <i class="conum" data-value="4"></i><b>(4)</b>
-trustcacerts <i class="conum" data-value="5"></i><b>(5)</b>
-v <i class="conum" data-value="6"></i><b>(6)</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 command to import certificates</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>use the <code>ca</code> alias to differentiate from the alias of the server certificate</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>the file containing the certificate chain received from the CA</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>your KeyStore file</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>specify that you trust CA certificates</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>verbose output</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Then, import the signed certificate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>keytool
-importcert
-file signed_certificate.pem
-keystore keystore.p12
-trustcacerts
-v</pre>
</div>
</div>
<div class="paragraph">
<p>Now you have a trusted certificate in your KeyStore that you can use for the domains of your web applications.</p>
</div>
<div class="paragraph">
<p>Refer to the section about configuring <a href="#og-protocols-ssl">secure protocols</a> to configure the secure connector with your newly created KeyStore.</p>
</div>
</div>
<div class="sect3">
<h4 id="og-keystore-client-authn"><a class="anchor" href="#og-keystore-client-authn"></a><a class="link" href="#og-keystore-client-authn">Creating a KeyStore for Client Certificate Authentication</a></h4>
<div class="paragraph">
<p>For the majority of secure web sites, it is the client (typically the browser) that validates the certificate sent by the server (by verifying the certificate chain).
This is the <em>server domain certificate</em>.</p>
</div>
<div class="paragraph">
<p>However, the TLS protocol supports a <em>mutual authentication</em> mode where also the client must send a certificate to the server, that the server validates.</p>
</div>
<div class="paragraph">
<p>You typically want to sign the client certificate(s) with a server certificate that you control, and you must distribute the client certificate(s) to all the clients that need it, and redistribute the client certificates when they expire.
The <em>server authentication certificate</em> may be different from the <em>server domain certificate</em>, but it&#8217;s typically stored in the same KeyStore for simplicity (although under a different alias).</p>
</div>
<div class="paragraph">
<p>First, you want to create the private key and server authentication certificate that you will use to sign client certificates:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>keytool
-genkeypair
-alias server_authn <i class="conum" data-value="1"></i><b>(1)</b>
-validity 90
-keyalg RSA
-keysize 2048
-keystore keystore.p12 <i class="conum" data-value="2"></i><b>(2)</b>
-storetype pkcs12
-dname &quot;CN=server_authn, OU=Unit, O=Company, L=City, S=State, C=Country&quot; <i class="conum" data-value="3"></i><b>(3)</b>
-ext bc=ca:true <i class="conum" data-value="4"></i><b>(4)</b>
-v</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>use the <code>server_authn</code> alias to differentiate from the alias of the server certificate</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>the KeyStore file</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>the CN is not that important, since this certificate will not be validated by clients</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>the extension with the basic constraints (more below)</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">
The important difference with the <a href="#og-keystore-create">creation of a server certificate</a> is the <em>basic constraints</em> extension (<code>bc</code>) that indicates that this certificates acts as a certificate authority (<code>ca:true</code>).
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now you want to export both the private key and server authentication certificate.
Unfortunately, the <code>keytool</code> program cannot export private keys, so you need to use a different command line program like <code>openssl</code>, or a graphical program like <a href="https://keystore-explorer.org/">KeyStore Explorer</a>.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s use <code>openssl</code> to export the server authentication private key:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>openssl
pkcs12
-in keystore.p12
-nodes
-nocerts
-out server_authn.key</pre>
</div>
</div>
<div class="paragraph">
<p>Now let&#8217;s export the server authentication certificate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>keytool
-exportcert
-keystore keystore.p12
-rfc
-file server_authn.crt
-v</pre>
</div>
</div>
<div class="paragraph">
<p>At this point, you want to create a client KeyStore, so that you can sign the client certificate with the server authentication cryptographic material:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>keytool
-genkeypair
-validity 90
-keyalg RSA
-keysize 2048
-keystore client_keystore.p12 <i class="conum" data-value="1"></i><b>(1)</b>
-storetype pkcs12
-dname &quot;CN=client, OU=Unit, O=Company, L=City, S=State, C=Country&quot; <i class="conum" data-value="2"></i><b>(2)</b>
-v</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>the client KeyStore file</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>the CN is not that important, since it will not be validated by the server</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now produce a certificate signing request (CSR):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>keytool
-certreq
-file client.csr
-keystore client_keystore.p12</pre>
</div>
</div>
<div class="paragraph">
<p>Now you need to sign the CSR, but again the <code>keytool</code> program does not have this functionality, and you must resort again to use <code>openssl</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>openssl
x509
-req
-days 90
-in client.csr
-CA server_authn.crt
-CAkey server_authn.key
-CAcreateserial
-sha256
-out signed.crt</pre>
</div>
</div>
<div class="paragraph">
<p>Now you need to import the server authentication certificate and the signed client certificate into the client KeyStore.</p>
</div>
<div class="paragraph">
<p>First, the server authentication certificate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>keytool
-importcert
-alias ca
-file server_authn.crt
-keystore client_keystore.p12
-v</pre>
</div>
</div>
<div class="paragraph">
<p>Then, the signed client certificate:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>keytool
-importcert
-file signed.crt
-keystore client_keystore.p12
-v</pre>
</div>
</div>
<div class="paragraph">
<p>Now you can distribute <code>client_keystore.p12</code> to your client(s).</p>
</div>
<div class="paragraph">
<p>Refer to the section about configuring <a href="#og-protocols-ssl">secure protocols</a> to configure the secure connector to require client authentication.</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#pg-server-session">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-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-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 default Jetty implements the SLF4J api, but you can choose a different logging implementation by following the instructions <a href="#og-logging">here</a></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#pg-server-session">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-quickstart"><a class="anchor" href="#og-quickstart"></a><a class="link" href="#og-quickstart">Faster Web Application Deployment</a></h3>
<div class="paragraph">
<p>The auto discovery features of the Servlet Specification can make deployments slow and uncertain.
Auto discovery of web application configuration can be useful during the development as it allows new features and frameworks to be enabled simply by dropping in a jar file.
However for production deployment, the need to scan the contents of many jars can have a significant impact at startup time.</p>
</div>
<div class="paragraph">
<p>The <code>quickstart</code> module allows a webapp to be pre-scanned, making startup predictable and faster.
During scanning all declarative configuration (ie from web.xml, web-fragment.xml and annotations) are encoded into an effective <code>web.xml</code>, called <code>WEB-INF/quickstart-web.xml</code>, which can be inspected to understand what will be deployed.</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>Programmatic configuration is <em>not</em> encoded into the generated <code>quickstart-web.xml</code> file.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>With <code>quickstart</code>, webapps that took many seconds to scan and deploy can now be deployed in a few hundred milliseconds.</p>
</div>
<div class="sect3">
<h4 id="og-enabling"><a class="anchor" href="#og-enabling"></a><a class="link" href="#og-enabling">Enabling</a></h4>
<div class="paragraph">
<p>Enable the <code>quickstart</code> module for your jetty base:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ cd $JETTY-BASE
$ java -jar $JETTY_HOME/start.jar --add-module=quickstart</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>$JETTY-BASE/start.d/quickstart.ini</code> file contains these configurable parameters:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.quickstart.mode</dt>
<dd>
<p>The values are:</p>
<div class="dlist">
<dl>
<dt class="hdlist1">AUTO</dt>
<dd>
<p>Allows jetty to run either with or without a <code>quickstart-web.xml</code> file.
If jetty detects the file, then it will be used, otherwise the app is started normally.</p>
</dd>
<dt class="hdlist1">GENERATE</dt>
<dd>
<p>In this mode, jetty will generate a <code>quickstart-web.xml</code> file and then terminate.
Use this mode first before changing to either <code>AUTO</code> or <code>QUICKSTART</code>.</p>
</dd>
<dt class="hdlist1">QUICKSTART</dt>
<dd>
<p>In this mode, if jetty does not detect a <code>quickstart-web.xml</code> file then jetty will not start.</p>
</dd>
</dl>
</div>
</dd>
<dt class="hdlist1">jetty.quickstart.origin</dt>
<dd>
<p>Use this parameter to set the name of the attribute in the <code>quickstart-web.xml</code> file that contains the origin of each element.
Knowing the descriptor or annotation from which each element derives can be useful for debugging.
Note that the origin attribute does not conform to the web xml schema, so if you deploy with xml validation, you&#8217;ll see errors.
It is probably best to do a few trial runs with the attribute set, then turn it off for final generation.</p>
</dd>
<dt class="hdlist1">jetty.quickstart.xml</dt>
<dd>
<p>Use this parameter to change the name of the generated file.
By default this is <code>quickstart-web.xml</code> in the webapp&#8217;s <code>WEB-INF</code> directory.
The file named by this parameter will always be interpreted relative to <code>WEB-INF</code>.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>If your webapp is a war file, you will need to either first unpack it yourself, or use a context xml file (or code equivalent) that calls <code>WebAppContext.setExtractWAR(true)</code>.
If you allow Jetty to do the unpacking, it will use the usual mechanisms to find the location to which to unpack.
Note that by default Jetty unpacks to a temporary location which is <em>not</em> reused between executions.
So either specify the directory to which to unpack, or make a <code>work</code> directory in your base to ensure the unpacked war is preserved and reused across restarts.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-annotations"><a class="anchor" href="#og-annotations"></a><a class="link" href="#og-annotations">Annotations</a></h3>
<div class="paragraph">
<p>Enable the <code>annotations</code> module if your webapp - or any of its third party libraries - uses any of the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Annotations:</p>
<div class="ulist">
<ul>
<li>
<p>@Resource</p>
</li>
<li>
<p>@Resources</p>
</li>
<li>
<p>@PostConstruct</p>
</li>
<li>
<p>@PreDestroy</p>
</li>
<li>
<p>@DeclaredRoles</p>
</li>
<li>
<p>@RunAs</p>
</li>
<li>
<p>@MultipartConfig</p>
</li>
<li>
<p>@WebServlet</p>
</li>
<li>
<p>@WebFilter</p>
</li>
<li>
<p>@WebListener</p>
</li>
<li>
<p>@WebInitParam</p>
</li>
<li>
<p>@ServletSecurity, @HttpConstraint, @HttpMethodConstraint</p>
</li>
<li>
<p>@HandlesTypes</p>
</li>
</ul>
</div>
</li>
<li>
<p>javax.servlet.ServletContainerInitializers</p>
</li>
<li>
<p>JSP</p>
</li>
</ul>
</div>
<div class="sect3">
<h4 id="og-annotations-scanning"><a class="anchor" href="#og-annotations-scanning"></a><a class="link" href="#og-annotations-scanning">Annotation Scanning</a></h4>
<div class="paragraph">
<p>According to more recent versions of the Servlet Specification, the web.xml file can contain the attribute <code>metadata-complete</code>.
If this is set to <code>true</code>, then <em>no</em> annotation scanning takes place, and your descriptor must contain the equivalent xml statements of any annotations.</p>
</div>
<div class="paragraph">
<p>If it is <code>metadata-complete=false</code>, or your web.xml predates the inclusion of this attribute, annotation scanning is required to take place.</p>
</div>
<div class="paragraph">
<p>To prevent annotation scanning you can use the <code>WebAppContext.setConfigurationDiscovered(false)</code> method.
Here&#8217;s an example context xml file that calls this method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">configurationDiscovered</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>false<span class="tag">&lt;/Set&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;/Configure&gt;</span></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="https://www.eclipse.org/jetty/javadoc/jetty-10/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 that scanning should not take place.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>However, despite <code>metadata-complete=true</code>, scanning of classes may <em>still</em> occur because of <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html">javax.servlet.ServletContainerInitializer</a>s.
Classes implementing this interface are found by Jetty using the <a href="http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html">javax.util.ServiceLoader</a> mechanism, and if one is present <em>and</em> it includes the @HandlesTypes annotation, then Jetty must scan the class hierarchy of the web application.
This may be very time-consuming if you have many jars.</p>
</div>
<div class="paragraph">
<p>We will now look at ways to limit the jars that are scanned.</p>
</div>
<div class="sect4">
<h5 id="og-the-container-classpath"><a class="anchor" href="#og-the-container-classpath"></a><a class="link" href="#og-the-container-classpath">The container classpath</a></h5>
<div class="paragraph">
<p>By default, Jetty will <em>not</em> scan any classes that are on the container&#8217;s classpath.</p>
</div>
<div class="paragraph">
<p>Sometimes, you may have third party libraries on the container&#8217;s classpath that you need to be scanned.
In this case, use the <code>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</code> context attribute to define which container jars and class directories to scan.
The value of this attribute is a regular expression.</p>
</div>
<div class="paragraph">
<p>Here&#8217;s an example from a context xml file that includes any jar whose name starts with "foo-" or "bar-", or a directory named "classes":</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">setAttribute</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Arg&gt;</span>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Arg&gt;</span>.*/foo-[^/]*\.jar$|.*/bar-[^/]*\.jar$|.*/classes/.*<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="https://www.eclipse.org/jetty/javadoc/jetty-10/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 a context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Specifies the name of the context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Specifies the value of the context attribute.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Note that the order of the patterns defines the ordering of the scanning of the jars or class directories.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-the-webapp-classpath"><a class="anchor" href="#og-the-webapp-classpath"></a><a class="link" href="#og-the-webapp-classpath">The webapp classpath</a></h5>
<div class="paragraph">
<p>By default Jetty will scan <em>all</em> classes from <code>WEB-INF/classes</code> and <em>all</em> jars from <code>WEB-INF/lib</code> according to the order, if any, established by absolute or relative ordering clauses in web.xml.</p>
</div>
<div class="paragraph">
<p>If your webapp contains many jar files that you know do not contain any annotations, you can significantly speed up deployment by omitting them from scanning.
However, be careful if your webapp uses a <code>ServletContainerInitializer</code> with an <code>@HandlesTypes</code> annotation that you don&#8217;t exclude jars that contain classes matching the annotation.</p>
</div>
<div class="paragraph">
<p>Use the <code>org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</code> context attribute to define a regular expression for jars and class directories to select for scanning.</p>
</div>
<div class="paragraph">
<p>Here&#8217;s an example of a context xml file that sets a pattern that matches any jar on the webapp&#8217;s classpath that starts with <code>spring-</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">setAttribute</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Arg&gt;</span>org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Arg&gt;</span>.*/spring-[^/]*\.jar$<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="https://www.eclipse.org/jetty/javadoc/jetty-10/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 a context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Specifies the name of the context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Specifies the value of the context attribute.</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="og-multi-threading"><a class="anchor" href="#og-multi-threading"></a><a class="link" href="#og-multi-threading">Multi-threading</a></h5>
<div class="paragraph">
<p>By default Jetty performs annotation scanning in a multi-threaded manner in order to complete it in the minimum amount of time.</p>
</div>
<div class="paragraph">
<p>If you don&#8217;t want multi-threaded scanning, you can configure Jetty to revert to single-threaded scanning.
There are several options to configure this:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Set the context attribute <code>org.eclipse.jetty.annotations.multiThreaded</code> to <code>false</code></p>
</li>
<li>
<p>Set the <code>Server</code> attribute <code>org.eclipse.jetty.annotations.multiThreaded</code> to <code>false</code></p>
</li>
<li>
<p>Set the System property <code>org.eclipse.jetty.annotations.multiThreaded</code> to <code>false</code></p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Method 1 will only affect the current webapp.
Method 2 will affect all webapps deployed to the same Server instance.
Method 3 will affect all webapps deployed in the same JVM.</p>
</div>
<div class="paragraph">
<p>By default, Jetty will wait a maximum of 60 seconds for all of the scanning threads to complete.
You can set this to a higher or lower number of seconds by doing one of the following:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Set the context attribute <code>org.eclipse.jetty.annotations.maxWait</code></p>
</li>
<li>
<p>Set the <code>Server</code> attribute <code>org.eclipse.jetty.annotations.maxWait</code></p>
</li>
<li>
<p>Set the System property <code>org.eclipse.jetty.annotations.maxWait</code></p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Method 1 will only affect the current webapp.
Method 2 will affect all webapps deployed to the same Server instance.
Method 3 will affect all webapps deployed in the same JVM.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-annotations-scis"><a class="anchor" href="#og-annotations-scis"></a><a class="link" href="#og-annotations-scis">ServletContainerInitializers</a></h4>
<div class="paragraph">
<p>The <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html">javax.servlet.ServletContainerInitializer</a> class can exist in: the container&#8217;s classpath, the webapp&#8217;s <code>WEB-INF/classes</code> directory, the webapp&#8217;s <code>WEB-INF/lib</code> jars, or any external extraClasspath that you have configured on the webapp.</p>
</div>
<div class="paragraph">
<p>The Servlet Specification does not define any order in which a <code>ServletContainerInitializer</code> must be called when the webapp starts.
By default Jetty will call them in the following order:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>ServletContainerInitializers from the container&#8217;s classpath</p>
</li>
<li>
<p>ServletContainerInitializers from WEB-INF/classes</p>
</li>
<li>
<p>ServletContainerInitializers from WEB-INF/lib jars <em>in the order established in web.xml</em>, or in the order that the SCI is returned by the <a href="http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html">javax.util.ServiceLoader</a> if there is <em>no</em> ordering.</p>
</li>
</ol>
</div>
<div class="sect4">
<h5 id="og-exclusions"><a class="anchor" href="#og-exclusions"></a><a class="link" href="#og-exclusions">Exclusions</a></h5>
<div class="paragraph">
<p>By default, as according to the Servlet Specification, all <code>ServletContainerInitializer</code> that are discovered are invoked.</p>
</div>
<div class="paragraph">
<p>Sometimes, depending on your requirements, you may need to prevent some being called at all.</p>
</div>
<div class="paragraph">
<p>In this case, you can define the <code>org.eclipse.jetty.containerInitializerExclusionPattern</code> context attribute.</p>
</div>
<div class="paragraph">
<p>This is a regular expression that defines <a href="http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html">patterns</a> of classnames that you want to exclude.
Here&#8217;s an example of setting the context attribute in a context xml file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">setAttribute</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Arg&gt;</span>org.eclipse.jetty.containerInitializerExclusionPattern<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Arg&gt;</span>com.acme.*|com.corp.SlowContainerInitializer<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="https://www.eclipse.org/jetty/javadoc/jetty-10/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 a context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Specifies the name of the context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Specifies the value of the context attribute.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>In this example we exclude <strong>all</strong> <code>ServletContainerInitializer</code> instances in the <code>com.acme package</code>, and the specific class <code>com.corp.SlowContainerInitializer</code>.</p>
</div>
<div class="paragraph">
<p>It is possible to use exclusion and ordering together to control <code>ServletContainerInitializer</code> invocation - the exclusions will be applied before the ordering.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-ordering"><a class="anchor" href="#og-ordering"></a><a class="link" href="#og-ordering">Ordering</a></h5>
<div class="paragraph">
<p>If you need <code>ServletContainerInitializer</code> classes called in a specific order, you can use the context attribute <code>org.eclipse.jetty.containerInitializerOrder</code>.
Set it to a list of comma separated class names of <code>ServletContainerInitializers</code> in the order that you want them applied.</p>
</div>
<div class="paragraph">
<p>You may optionally use the wildcard character <code>*</code> <strong>once</strong> in the list.
It will match all <code>ServletContainerInitializer</code> classes not explicitly named in the list.</p>
</div>
<div class="paragraph">
<p>Here is an example context xml file that ensures the <code>com.example.PrioritySCI</code> will be called first, followed by the <code>com.acme.FooSCI</code>, then all other SCIs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">setAttribute</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Arg&gt;</span>org.eclipse.jetty.containerInitializerOrder<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Arg&gt;</span>org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServletContainerInitializer, com.acme.FooSCI, *<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="https://www.eclipse.org/jetty/javadoc/jetty-10/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 a context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Specifies the name of the context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Specifies the value of the context attribute.</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-jsp"><a class="anchor" href="#og-jsp"></a><a class="link" href="#og-jsp">Java Server Pages</a></h3>
<div class="paragraph">
<p>Jetty supports JSP via the <code>jsp</code> module, which is based on Apache Jasper:</p>
</div>
<div class="listingblock">
<div class="content">
<pre># DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables JSP for all web applications deployed on the server.
[depend]
servlet
annotations
apache-jsp</pre>
</div>
</div>
<div class="paragraph">
<p>Logging has been bridged to Jetty logging, so you can enable logging for the <code>org.apache.jasper</code> package, subpackages and classes as usual.</p>
</div>
<div class="sect3">
<h4 id="og-configuration-of-the-jsp-servlet"><a class="anchor" href="#og-configuration-of-the-jsp-servlet"></a><a class="link" href="#og-configuration-of-the-jsp-servlet">Configuration of the JSP Servlet</a></h4>
<div class="paragraph">
<p>The <code>org.eclipse.jetty.jsp.JettyJspServlet</code> is the servlet responsible for serving JSPs.</p>
</div>
<div class="paragraph">
<p>It is configured as the default jsp servlet in the <code>$JETTY_HOME/etc/webdefault.xml</code> file.
Notice that Jetty identifies the jsp servlet by the presence of the <code>id="jsp"</code> attribute in the <code>&lt;servlet&gt;</code> declaration.</p>
</div>
<div class="paragraph">
<p>That file maps the <code>org.eclipse.jetty.jsp.JettyJspServlet</code> to the following partial urls:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>*.jsp</code></p>
</li>
<li>
<p><code>*.jspf</code></p>
</li>
<li>
<p><code>*.jspx</code></p>
</li>
<li>
<p><code>*.xsp</code></p>
</li>
<li>
<p><code>*.JSP</code></p>
</li>
<li>
<p><code>*.JSPF</code></p>
</li>
<li>
<p><code>*.JSPX</code></p>
</li>
<li>
<p><code>*.XSP</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>You can change to a different servlet, change or add <code>&lt;init-param&gt;</code>s or add extra <code>&lt;servlet-mapping&gt;</code>s in your <code>web.xml</code> file.</p>
</div>
<div class="paragraph">
<p>Here&#8217;s an example of adding an <code>&lt;init-param&gt;</code> to augment the definitions from the standard <code>webdefault.xml</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;servlet</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">jsp</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;servlet-name&gt;</span>jsp<span class="tag">&lt;/servlet-name&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;init-param&gt;</span>
<span class="tag">&lt;param-name&gt;</span>keepgenerated<span class="tag">&lt;/param-name&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;param-value&gt;</span>true<span class="tag">&lt;/param-value&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;/init-param&gt;</span>
<span class="tag">&lt;/servlet&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>This identifies this servlet as the jsp servlet to Jetty.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>This identifies this declaration as augmenting the already-defined servlet called <code>jsp</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>This init param controls whether the jsp servlet retains the <code>*.java</code> files generated during jsp compilation.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>This sets the value of the init param</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Another element you might consider adding to the default setup is <code>async-supported</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;servlet</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">jsp</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;servlet-name&gt;</span>jsp<span class="tag">&lt;/servlet-name&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;async-supported&gt;</span>true<span class="tag">&lt;/async-supported&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;/servlet&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>This identifies this servlet as the jsp servlet to Jetty.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>This identifies this declaration as augmenting the already-defined servlet called <code>jsp</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>By default, the jsp servlet does not support async.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>There are many configuration parameters for the Apache Jasper JSP Servlet, here are some of them:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 4. JSP Servlet Parameters</caption>
<colgroup>
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
<col style="width: 25%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">init param</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Default</th>
<th class="tableblock halign-left valign-top"><code>webdefault.xml</code></th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">checkInterval</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If non-zero and <code>development</code> is <code>false</code>, background jsp recompilation is enabled. This value is the interval in seconds between background recompile checks.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">0</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">classpath</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The classpath is dynamically generated if the context has a URL classloader. The <code>org.apache.catalina.jsp_classpath</code>
context attribute is used to add to the classpath, but if this is not set, this <code>classpath</code> configuration item is added to the classpath instead.`</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">classdebuginfo</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Include debugging info in class file.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">compilerClassName</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If not set, defaults to the Eclipse jdt compiler.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">compiler</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Used if the Eclipse jdt compiler cannot be found on the
classpath. It is the classname of a compiler that Ant should invoke.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">compilerTargetVM</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Target vm to compile for.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1.8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1.8</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">compilerSourceVM</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Sets source compliance level for the jdt compiler.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1.8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1.8</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">development</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>true</code> recompilation checks occur at the frequency governed by <code>modificationTestInterval</code>.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">displaySourceFragment</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Should a source fragment be included in
exception messages</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">dumpSmap</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Dump SMAP JSR45 info to a file.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">enablePooling</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Determines whether tag handler pooling is enabled.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">engineOptionsClass</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allows specifying the Options class used to
configure Jasper. If not present, the default EmbeddedServletOptions
will be used.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">errorOnUseBeanInvalidClassAttribute</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Should Jasper issue an error when
the value of the class attribute in an useBean action is not a valid
bean class</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">fork</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Only relevant if you use Ant to compile JSPs: by default Jetty will use the Eclipse jdt compiler.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">genStrAsCharArray</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Option for generating Strings as char arrays.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">ieClassId</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The class-id value to be sent to Internet Explorer when
using &lt;jsp:plugin&gt; tags.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">clsid:8AD9C840-044E-11D1-B3E9-00805F499D93</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">javaEncoding</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Pass through the encoding to use for the compilation.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">UTF8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">jspIdleTimeout</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The amount of time in seconds a JSP can be idle before
it is unloaded. A value of zero or less indicates never unload.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">-1</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">keepgenerated</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Do you want to keep the generated Java files around?</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">mappedFile</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Support for mapped Files. Generates a servlet that has a
print statement per line of the JSP file</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">maxLoadedJsps</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The maximum number of JSPs that will be loaded for a web
application. If more than this number of JSPs are loaded, the least
recently used JSPs will be unloaded so that the number of JSPs loaded at
any one time does not exceed this limit. A value of zero or less
indicates no limit.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">-1</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">modificationTestInterval</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If <code>development=true</code>, interval between
recompilation checks, triggered by a request.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">4</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">quoteAttributeEL</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">When EL is used in an attribute value on a JSP page, should the rules for quoting of attributes described in JSP.1.6 be applied to the expression</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">recompileOnFail</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">If a JSP compilation fails should the
modificationTestInterval be ignored and the next access trigger a
re-compilation attempt? Used in development mode only and is disabled by
default as compilation may be expensive and could lead to excessive
resource usage.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">scratchDir</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Directory where servlets are generated. The default is the value of the context attribute <code>javax.servlet.context.tempdir</code>, or the system property <code>java.io.tmpdir</code> if the context attribute is not set.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">strictQuoteEscaping</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Should the quote escaping required by section JSP.1.6 of the JSP specification be applied to scriplet expression.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">-</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">suppressSmap</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Generation of SMAP info for JSR45 debugging.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">trimSpaces</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Should template text that consists entirely of whitespace be removed from the output (true), replaced with a single space (single) or left unchanged (false)? Note that if a JSP page or tag file specifies a trimDirectiveWhitespaces value of true, that will take precedence over this configuration setting for that page/tag.
trimmed?</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">–</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">xpoweredBy</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Generate an X-Powered-By response header.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
</tbody>
</table>
<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>If the value you set doesn&#8217;t take effect, try using all lower case instead of camel case, or capitalizing only some of the words in the name, as Jasper is inconsistent in its parameter naming strategy.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-javaserver-pages-standard-tag-libraries"><a class="anchor" href="#og-javaserver-pages-standard-tag-libraries"></a><a class="link" href="#og-javaserver-pages-standard-tag-libraries">JavaServer Pages Standard Tag Libraries</a></h3>
<div class="paragraph">
<p>The JavaServer Pages Standard Tag Library (JSTL) is part of the Jetty distribution, and is available via the <code>jstl</code> module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre># DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables JSTL for all web applications deployed on the server.
[depend]
jsp
apache-jstl</pre>
</div>
</div>
<div class="paragraph">
<p>When enabled, Jetty will make the JSTL tags available for your webapps.</p>
</div>
</div>
<div class="sect2">
<h3 id="og-javaserver-faces-taglibs"><a class="anchor" href="#og-javaserver-faces-taglibs"></a><a class="link" href="#og-javaserver-faces-taglibs">JavaServer Faces TagLibs</a></h3>
<div class="paragraph">
<p>If you want to use JSF with your webapp, you should copy the relevant jars from your implementation of choice into your <code>$JETTY_BASE</code> directory, ideally into <code>$JETTY_BASE/lib/ext</code>.
If that directory does not exist, enable the <code>ext</code> module, which will create the directory and ensure all jars within it are put onto the container classpath.</p>
</div>
<div class="paragraph">
<p>Then you will need to tell Jetty which of those jars contains the <code>*.tld</code> files.
To accomplish that, you need to specify either the name of the file or a pattern that matches the name/s of the file/s as the <code>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</code> context attribute.
You will need to preserve the existing value of the attribute, and add in your extra pattern.</p>
</div>
<div class="paragraph">
<p>Here&#8217;s an example of using a context xml file to add in a pattern to match files starting with <code>jsf-</code>, which contain the <code>*.tld</code> files:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">setAttribute</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Arg&gt;</span>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Arg&gt;</span>.*/jetty-servlet-api-[^/]*\.jar$|.*/javax.servlet.jsp.jstl-.*\.jar$|.*/org.apache.taglibs.taglibs-standard-impl-.*\.jar$|.*/jsf-[^/]*\.jar$<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="https://www.eclipse.org/jetty/javadoc/jetty-10/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 a context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Specifies the name of the context attribute.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Adds the additional pattern <code>.*/jsf-[^/]*\.jar$</code> to those already existing.</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="og-jndi"><a class="anchor" href="#og-jndi"></a><a class="link" href="#og-jndi">JNDI</a></h3>
<div class="paragraph">
<p>Enable the <code>plus</code> module in order to be able to use JNDI resources in your webapp.
If you already have the <code>annotations</code> module enabled, then it will already be enabled.</p>
</div>
<div class="paragraph">
<p>If you have extra jars associated with your JNDI resources, eg database drivers etc, that are not located inside your webapp then you should place those jars into your <code>$jetty.base/lib/ext</code> directory.
If your base doesn&#8217;t already contain this directory, then enable the <code>ext</code> module, and Jetty will create the directory for you and ensure its contents are on the server&#8217;s classpath.</p>
</div>
<div class="paragraph">
<p>You can now declare JNDI resources and reference them within your webapps.</p>
</div>
<div class="sect3">
<h4 id="og-declaring-resources"><a class="anchor" href="#og-declaring-resources"></a><a class="link" href="#og-declaring-resources">Declaring resources</a></h4>
<div class="paragraph">
<p>You must declare the objects you want bound into the environment so that you can then hook them into your webapp via <code>env-entry</code>, <code>resource-ref</code> and <code>resource-env-refs</code> in <code>web.xml</code>, <code>web-fragment.xml</code> or <code>override-web.xml</code>.</p>
</div>
<div class="paragraph">
<p>You make these declarations in Jetty XML files that are either <em>external</em> or <em>internal</em> to your webapp.
A server or context XML file is external to your webapp.
The special <code>WEB-INF/jetty-env.xml</code> file is internal to your webapp.
See the section on <a href="#og-jndi-xml">Jetty XML files</a> for more information on how to choose in which XML file to place your declarations.</p>
</div>
<div class="paragraph">
<p>For now, let&#8217;s look at <em>what</em> you declare in the XML file, regardless of its location.</p>
</div>
<div class="paragraph">
<p>Declaring a JDNI resource to be referenced later in your webapp is accomplished by declaring new instances of the following types:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><a href="#og-jndi-env"><code>org.eclipse.jetty.plus.jndi.EnvEntry</code></a></dt>
<dd>
<p>Used for <code>env-entry</code> type of entries</p>
</dd>
<dt class="hdlist1"><a href="#og-jndi-resource"><code>org.eclipse.jetty.plus.jndi.Resource</code></a></dt>
<dd>
<p>Used for most other type of resources</p>
</dd>
<dt class="hdlist1"><a href="#og-jndi-tx"><code>org.eclipse.jetty.plus.jndi.Transaction</code></a></dt>
<dd>
<p>For a JTA manager</p>
</dd>
<dt class="hdlist1"><a href="#og-jndi-link"><code>org.eclipse.jetty.plus.jndi.Link</code></a></dt>
<dd>
<p>For the link between a <code>web.xml</code> resource name and a naming entry</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>Declarations of each of these types follow a similar pattern:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.xxxx</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Arg&gt;</span><span class="comment">&lt;!-- scope --&gt;</span><span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Arg&gt;</span><span class="comment">&lt;!-- name --&gt;</span><span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Arg&gt;</span><span class="comment">&lt;!-- value --&gt;</span><span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;/New&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Defines a resource to Jetty.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Specifies the <a href="#og-jndi-scope">scope</a> of the resource.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Specifies the name of the resource which will be looked up by the webapp relative to the <code>java:comp/env</code> namespace.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Specifies the value of the resource.</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="og-jndi-env"><a class="anchor" href="#og-jndi-env"></a><a class="link" href="#og-jndi-env">org.eclipse.jetty.plus.jndi.EnvEntry</a></h5>
<div class="paragraph">
<p>Sometimes it is useful to pass configuration information to a webapp at runtime that you either cannot or cannot conveniently code into a <code>web.xml</code> <code>&lt;env-entry&gt;</code>.
In such cases, you can use the <code>org.eclipse.jetty.plus.jndi.EnvEntry</code> class, and optionally even override an entry of the same name in <code>web.xml</code>.</p>
</div>
<div class="paragraph">
<p>Here&#8217;s an example that defines the equivalent of an <code>env-entry</code> called <code>mySpecialValue</code> with value <code>4000</code> that overrides an <code>&lt;env-entry&gt;</code> declaration of the same name in web.xml:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.EnvEntry</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Arg&gt;</span>mySpecialValue<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.Integer</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>4000<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">boolean</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>true<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="5"></i><b>(5)</b>
<span class="tag">&lt;/New&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Define an <code>EnvEntry</code> that corresponds to an <code>&lt;env-entry&gt;</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td><a href="#og-jndi-scope">Scoped</a> at the JVM level.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>The name of the entry, corresponding to a lookup by the webapp of <code>java:comp/env/mySpecialValue</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>The value of the entry, in this case the integer value <code>4000</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td><code>true</code> means to override the value of an <code>&lt;env-entry&gt;</code> of the same name in <code>web.xml</code>.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Note that if you don&#8217;t want to override the <code>web.xml</code> value, simply omit the last argument, or set it to <code>false</code>.</p>
</div>
<div class="paragraph">
<p>The Servlet Specification allows binding only the following object types to an <code>env-entry</code>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>java.lang.String</p>
</li>
<li>
<p>java.lang.Integer</p>
</li>
<li>
<p>java.lang.Float</p>
</li>
<li>
<p>java.lang.Double</p>
</li>
<li>
<p>java.lang.Long</p>
</li>
<li>
<p>java.lang.Short</p>
</li>
<li>
<p>java.lang.Character</p>
</li>
<li>
<p>java.lang.Byte</p>
</li>
<li>
<p>java.lang.Boolean</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Jetty is a little more flexible and allows you to also bind:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>custom POJOs</p>
</li>
<li>
<p><a href="http://docs.oracle.com/javase/1.5.0/docs/api/javax/naming/Reference.html"><code>javax.naming.References</code></a></p>
</li>
<li>
<p><a href="http://docs.oracle.com/javase/1.5.0/docs/api/javax/naming/Referenceable.html"><code>javax.naming.Referenceables</code></a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Be aware that if you take advantage of this feature, your web application is <em>not portable</em>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-jndi-resource"><a class="anchor" href="#og-jndi-resource"></a><a class="link" href="#og-jndi-resource">org.eclipse.jetty.plus.jndi.Resource</a></h5>
<div class="paragraph">
<p>You can configure any type of resource that you want to refer to in <code>web.xml</code> via a <code>resource-ref</code> or <code>resource-env-ref</code> by using the <code>org.eclipse.jetty.plus.jndi.Resource</code> type of naming entry.</p>
</div>
<div class="paragraph">
<p>You provide the scope, the name of the object (relative to <code>java:comp/env</code>) and a POJO, <code>javax.naming.Reference</code> or <code>javax.naming.Referenceable</code> instance.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s examine how to configure some of the most common types of resources.</p>
</div>
<div class="sect5">
<h6 id="og-datasources"><a class="anchor" href="#og-datasources"></a><a class="link" href="#og-datasources">DataSources</a></h6>
<div class="paragraph">
<p>In this example, we&#8217;ll configure a <a href="http://db.apache.org/derby">Derby</a> DataSource named <code>jdbc/myds</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">'</span><span class="content">wac</span><span class="delimiter">'</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Resource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">wac</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>jdbc/myds<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.apache.derby.jdbc.EmbeddedDataSource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">DatabaseName</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>test<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">createDatabase</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>create<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This would linked into the webapps JNDI namespace via an entry in a <code>web.xml</code> like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;resource-ref&gt;</span>
<span class="tag">&lt;res-ref-name&gt;</span>jdbc/myds<span class="tag">&lt;/res-ref-name&gt;</span>
<span class="tag">&lt;res-type&gt;</span>javax.sql.DataSource<span class="tag">&lt;/res-type&gt;</span>
<span class="tag">&lt;res-auth&gt;</span>Container<span class="tag">&lt;/res-auth&gt;</span>
<span class="tag">&lt;/resource-ref&gt;</span></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>When configuring Resources, ensure that the type of object you configure matches the type of object you expect to look up in <code>java:comp/env</code>.
For database connection factories, this means that the object you register as a Resource <em>must</em> implement the <code>javax.sql.DataSource</code> interface.</p>
</div>
<div class="paragraph">
<p>Also note that the <a href="http://jcp.org/aboutJava/communityprocess/pr/jsr244/index.html">J2EE Specification</a> recommends storing DataSources relative to <code>jdbc/</code> and thus looked up by the application as <code>java:comp/env/jdbc/xxx</code>.
Eg The Datasource bound in Jetty as <code>jdbc/users</code> would be looked up by the application as <code>java:comp/env/jdbc/users</code></p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect5">
<h6 id="og-jms-queues-topics-and-connectionfactories"><a class="anchor" href="#og-jms-queues-topics-and-connectionfactories"></a><a class="link" href="#og-jms-queues-topics-and-connectionfactories">JMS Queues, Topics and ConnectionFactories</a></h6>
<div class="paragraph">
<p>Jetty can bind any implementation of the JMS destinations and connection factories.</p>
</div>
<div class="paragraph">
<p>Here is an example of binding an <a href="http://activemq.apache.org">ActiveMQ</a> in-JVM connection factory:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">'</span><span class="content">wac</span><span class="delimiter">'</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Resource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">'</span><span class="content">wac</span><span class="delimiter">'</span></span><span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>jms/connectionFactory<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.apache.activemq.ActiveMQConnectionFactory</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>vm://localhost?broker.persistent=false<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The corresponding entry in <code>web.xml</code> to bind the ConnectionFactory into the webapp&#8217;s JNDI namespace would be:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;resource-ref&gt;</span>
<span class="tag">&lt;res-ref-name&gt;</span>jms/connectionFactory<span class="tag">&lt;/res-ref-name&gt;</span>
<span class="tag">&lt;res-type&gt;</span>javax.jms.ConnectionFactory<span class="tag">&lt;/res-type&gt;</span>
<span class="tag">&lt;res-auth&gt;</span>Container<span class="tag">&lt;/res-auth&gt;</span>
<span class="tag">&lt;/resource-ref&gt;</span></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>The <a href="http://jcp.org/aboutJava/communityprocess/pr/jsr244/index.html">J2EE Specification</a> recommends storing JMS connection factories under <code>jms/</code>.
Eg The ConnectionFactory bound in Jetty as <code>jms/inqueue</code> would be looked up by the application as <code>java:comp/env/jms/inqueue</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect5">
<h6 id="og-mail"><a class="anchor" href="#og-mail"></a><a class="link" href="#og-mail">Mail</a></h6>
<div class="paragraph">
<p>To configure access to <code>javax.mail.Session</code> from within a webapp, declare an <code>org.eclipse.jetty.plus.jndi.Resource</code> with an <code>org.eclipse.jetty.jndi.factories.MailSessionReference</code> that will hold the mail configuration and create the instance of the <code>Session</code> when it is referenced:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">'</span><span class="content">wac</span><span class="delimiter">'</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Resource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">wac</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>mail/Session<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.jndi.factories.MailSessionReference</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">user</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>fred<span class="tag">&lt;/Set&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">password</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>OBF:1xmk1w261z0f1w1c1xmq<span class="tag">&lt;/Set&gt;</span> <i class="conum" data-value="3"></i><b>(3)</b>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">properties</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span> <i class="conum" data-value="4"></i><b>(4)</b>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.util.Properties</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Put</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">mail.smtp.host</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>XXX<span class="tag">&lt;/Put&gt;</span>
<span class="tag">&lt;Put</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">mail.from</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>me@me<span class="tag">&lt;/Put&gt;</span>
<span class="tag">&lt;Put</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">mail.debug</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>true<span class="tag">&lt;/Put&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Use the <code>org.eclipse.jetty.jndi.factories.MailSessionReference</code> class to hold the configuration.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Set the username for the mail instance.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>Set the password for the mail instance - use Jetty&#8217;s secure password obfuscation to obscure the password.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>Set all other applicable properties.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The webapp performs a lookup for <code>java:comp/env/mail/Session</code> at runtime and obtains a <code>javax.mail.Session</code> that has the correct configuration to permit it to send email via SMTP.</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>Jetty does not provide the <code>javax.mail</code> and <code>javax.activation</code> jars.</p>
</div>
<div class="paragraph">
<p>Note also that the <a href="http://jcp.org/aboutJava/communityprocess/pr/jsr244/index.html">J2EE Specification</a> recommends storing JavaMail connection factories under <code>mail/</code>.
Eg The <code>MailSessionReference</code> bound to jetty as <code>mail/smtp</code> would be looked up by the application as <code>java:comp/env/mail/smtp</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-jndi-tx"><a class="anchor" href="#og-jndi-tx"></a><a class="link" href="#og-jndi-tx">org.eclipse.jetty.plus.jndi.Transaction</a></h5>
<div class="paragraph">
<p>To perform distributed transactions with your resources, a <em>transaction manager</em> that supports the JTA interfaces is required.
The transaction manager is looked up by the application as <code>java:comp/UserTransaction</code>.</p>
</div>
<div class="paragraph">
<p>Jetty does not ship with a JTA manager, but <em>does</em> provide the infrastructure to plug in the JTA manager of your choice.</p>
</div>
<div class="paragraph">
<p>Use the <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/plus/jndi/Transaction.html">org.eclipse.jetty.plus.jndi.Transaction</a> object in a <a href="#og-jndi-xml">Jetty XML file</a> to configure the JTA manager.</p>
</div>
<div class="paragraph">
<p>The following example configures the <a href="http://www.atomikos.com/">Atomikos</a> transaction manager:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;New</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">tx</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Transaction</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">com.atomikos.icatch.jta.J2eeUserTransaction</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Jetty will automatically bind this JTA manager to the webapp&#8217;s JNDI namespace at <code>java:comp/UserTransaction</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-jndi-link"><a class="anchor" href="#og-jndi-link"></a><a class="link" href="#og-jndi-link">org.eclipse.jetty.plus.jndi.Link</a></h5>
<div class="paragraph">
<p>Usually, the name you provide for the <code>org.eclipse.jetty.plus.jndi.Resource</code> is the same name you reference in <code>web.xml</code>.
This ensures that the two are linked together and thus accessible to your webapp.</p>
</div>
<div class="paragraph">
<p>However, if the names cannot be the same, then it is possible to effectively alias one to another using an <code>org.eclipse.jetty.plus.jndi.Link</code>.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s look at an example.</p>
</div>
<div class="paragraph">
<p>Supposing you have a declaration for a Datasource named <code>jdbc/workforce</code> in a Jetty context XML file, but your web.xml wants to link to a <code>&lt;resource-ref&gt;</code> named <code>jdbc/employees</code>, and you cannot edit the web.xml.
You can create a <code>WEB-INF/jetty-env.xml</code> file with an <code>org.eclipse.jetty.plus.jndi.Link</code> that ties together the names <code>jdbc/workforce</code> and <code>jdbc/employees</code>:</p>
</div>
<div class="paragraph">
<p>The context XML file declares <code>jdbc/workforce</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">'</span><span class="content">wac</span><span class="delimiter">'</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Resource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">wac</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>jdbc/workforce<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.apache.derby.jdbc.EmbeddedDataSource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">DatabaseName</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>test<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">createDatabase</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>create<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>web.xml</code> refers to it as <code>jdbc/employees</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;resource-ref&gt;</span>
<span class="tag">&lt;res-ref-name&gt;</span>jdbc/employees<span class="tag">&lt;/res-ref-name&gt;</span>
<span class="tag">&lt;res-type&gt;</span>javax.sql.DataSource<span class="tag">&lt;/res-type&gt;</span>
<span class="tag">&lt;res-auth&gt;</span>Container<span class="tag">&lt;/res-auth&gt;</span>
<span class="tag">&lt;/resource-ref&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Create a <code>WEB-INF/jetty-env.xml</code> file with a <code>org.eclipse.jetty.plus.jndi.Link</code> to link these names together:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Link</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">'</span><span class="content">wac</span><span class="delimiter">'</span></span><span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>jdbc/employees<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Arg&gt;</span>jdbc/workforce<span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;/New&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>The name as referenced in the <code>web.xml</code> file.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The name as referenced in the context XML file.</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="og-jndi-xml"><a class="anchor" href="#og-jndi-xml"></a><a class="link" href="#og-jndi-xml">Jetty XML files</a></h5>
<div class="paragraph">
<p>You can define naming resources in three places:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Server XML file</dt>
<dd>
<p>Naming resources defined in a server XML file are <a href="#og-jndi-scope">scoped</a> at either the JVM level or the <code>org.eclipse.jetty.server.Server</code> level.
The classes for the resource <em>must</em> be visible at the Jetty <strong>container</strong> level.
If instead the classes for the resource only exist inside your webapp, you must declare it in a <code>WEB-INF/jetty-env.xml</code> file.</p>
</dd>
<dt class="hdlist1">Context XML file</dt>
<dd>
<p>Entries in a context XML file should be <a href="#og-jndi-scope">scoped</a> at the level of the webapp to which they apply (although it is possible to use a less strict scoping level of Server or JVM, but not recommended).
As with resources declared in a server XML file, classes associated with the resource <em>must</em> be visible on the <strong>container&#8217;s</strong> classpath.</p>
</dd>
<dt class="hdlist1">WEB-INF/jetty-env.xml</dt>
<dd>
<p>Naming resources in a <code>WEB-INF/jetty-env.xml</code> file are <a href="#og-jndi-scope">scoped</a> to the webapp in which the file resides.
While you can enter JVM or Server scopes if you choose, we do not recommend doing so.
The resources defined here may use classes from inside your webapp.</p>
</dd>
</dl>
</div>
</div>
<div class="sect4">
<h5 id="og-jndi-scope"><a class="anchor" href="#og-jndi-scope"></a><a class="link" href="#og-jndi-scope">Resource scoping</a></h5>
<div class="paragraph">
<p>Naming resources within Jetty belong to one of three different scopes, in increasing order of restrictiveness:</p>
</div>
<div class="paragraph">
<p><strong>JVM scope:</strong>
The name is unique across the JVM instance, and is visible to all application code.
This scope is represented by a <code>null</code> first parameter to the resource declaration.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;New</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">cf</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Resource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Arg&gt;</span>jms/connectionFactory<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.apache.activemq.ActiveMQConnectionFactory</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>vm://localhost?broker.persistent=false<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Empty first arg equates to JVM scope for the object bound to name <code>jms/connectionFactory</code>.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p><strong>Server scope:</strong>
The name is unique to a Server instance, and is only visible to applications associated with that instance.
This scope is represented by referencing the Server instance as the first parameter to the resource declaration.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;New</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">cf</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Resource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Server</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Arg&gt;</span>jms/connectionFactory<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.apache.activemq.ActiveMQConnectionFactory</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>vm://localhost?broker.persistent=false<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>We refer to the id <code>Server</code> which identifies the default <code>org.eclipse.jetty.server.Server</code> instance.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p><strong>Webapp scope:</strong>
The name is unique to the <code>org.eclipse.jetty.webapp.WebAppContext</code> instance, and is only visible to that application.
This scope is represented by referencing the instance as the first parameter to the resource declaration.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.plus.jndi.Resource</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span><span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">'</span><span class="content">wac</span><span class="delimiter">'</span></span><span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Arg&gt;</span>jms/connectionFactory<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.apache.activemq.ActiveMQConnectionFactory</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>vm://localhost?broker.persistent=false<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>We refer to an instance of an <code>org.eclipse.jetty.webapp.WebAppContext</code> which has been previously defined.</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-jaas"><a class="anchor" href="#og-jaas"></a><a class="link" href="#og-jaas">JAAS</a></h3>
<div class="paragraph">
<p>JAAS implements a Java version of the standard Pluggable Authentication Module (PAM) framework.</p>
</div>
<div class="paragraph">
<p>JAAS can be used for two purposes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>for authentication of users, to reliably and securely determine who is currently executing Java code, regardless of whether the code is running as an application, an applet, a bean, or a servlet</p>
</li>
<li>
<p>for authorization of users to ensure they have the access control rights (permissions) required to do the actions performed</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>JAAS authentication is performed in a pluggable fashion.
This permits applications to remain independent from underlying authentication technologies.
New or updated authentication technologies can be plugged under an application without requiring modifications to the application itself.</p>
</div>
<div class="paragraph">
<p>See Java Authentication and Authorization Service (JAAS) <a href="http://java.sun.com/javase/7/docs/technotes/guides/security/jaas/JAASRefGuide.html">Reference Guide</a> for more information about JAAS.</p>
</div>
<div class="paragraph">
<p>The Jetty JAAS support aims to dictate as little as possible whilst providing a sufficiently flexible infrastructure to allow users to drop either one of the <a href="#og-jaas-loginmodules">JAAS Login Modules that ships with Jetty</a>, or their
own custom <a href="https://docs.oracle.com/javase/7/docs/api/javax/security/auth/spi/LoginModule.html">LoginModule</a>s.</p>
</div>
<div class="sect3">
<h4 id="og-jaas-configuration"><a class="anchor" href="#og-jaas-configuration"></a><a class="link" href="#og-jaas-configuration">Configuration</a></h4>
<div class="sect4">
<h5 id="og-jaas-module"><a class="anchor" href="#og-jaas-module"></a><a class="link" href="#og-jaas-module">The <code>jaas</code> module</a></h5>
<div class="paragraph">
<p>Enable the <code>jaas</code> module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre># DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables JAAS for deployed web applications.
[depend]
server
[lib]
lib/jetty-jaas-${jetty.version}.jar
[xml]
etc/jetty-jaas.xml
[ini-template]
## The file location (relative to $jetty.base) for the
## JAAS "java.security.auth.login.config" system property
# jetty.jaas.login.conf=etc/login.conf</pre>
</div>
</div>
<div class="paragraph">
<p>The configurable items in the resulting <code>$jetty.base/start.d/jaas.ini</code> file are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">jetty.jaas.login.conf</dt>
<dd>
<p>This is the location of the file that will be referenced by the system property <code>java.security.auth.login.config</code>: Jetty sets this system property for you based on the value of this property.
The value of this property is assumed to be <em>relative to <code>$JETTY_BASE</code></em>.
The default value is <code>etc/login.conf</code>, which resolves to <code>$JETTY_BASE/etc/login.conf</code>.
If you don&#8217;t want to put your login module configuration file here, you can change this property to point to where it is.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>See more about the contents of this file in the <a href="#og-jaas-loginconf">Configuring JAAS</a> section.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-jaas-webapp"><a class="anchor" href="#og-jaas-webapp"></a><a class="link" href="#og-jaas-webapp">Configure the webapp for JAAS</a></h5>
<div class="paragraph">
<p>The <code>&lt;realm-name&gt;</code> in <code>web.xml</code> will be used to identify the <code>org.eclipse.jetty.jaas.JAASLoginService</code> declaration that integrates JAAS with Jetty.</p>
</div>
<div class="paragraph">
<p>For example, this <code>web.xml</code> contains a realm called <code>Test JAAS Realm</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;login-config&gt;</span>
<span class="tag">&lt;auth-method&gt;</span>FORM<span class="tag">&lt;/auth-method&gt;</span>
<span class="tag">&lt;realm-name&gt;</span>Test JAAS Realm<span class="tag">&lt;/realm-name&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;form-login-config&gt;</span>
<span class="tag">&lt;form-login-page&gt;</span>/login/login<span class="tag">&lt;/form-login-page&gt;</span>
<span class="tag">&lt;form-error-page&gt;</span>/login/error<span class="tag">&lt;/form-error-page&gt;</span>
<span class="tag">&lt;/form-login-config&gt;</span>
<span class="tag">&lt;/login-config&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>The name of the realm, which must be <em>identical</em> to the name of an <code>org.eclipse.jetty.jaas.JAASLoginService</code> declaration.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>We now need to declare an <code>org.eclipse.jetty.jaas.JAASLoginService</code> that references the realm name of <code>Test JAAS Realm</code>.
Here&#8217;s an example of a suitable XML snippet:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.jaas.JAASLoginService</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Name</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>Test JAAS Realm<span class="tag">&lt;/Set&gt;</span> <i class="conum" data-value="1"></i><b>(1)</b>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">LoginModuleName</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>xyz<span class="tag">&lt;/Set&gt;</span> <i class="conum" data-value="2"></i><b>(2)</b>
<span class="tag">&lt;/New&gt;</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>The name is the <em>same</em> as that declared in the <code>&lt;realm-name&gt;</code> in <code>web.xml</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The name that identifies a set of <code>javax.security.auth.spi.LoginModule</code> configurations that comprise the <a href="#og-jaas-loginconf">JAAS config file</a> identified in the <code>jetty.jaas.login.conf</code> property of the <a href="#og-jaas-module"><code>jaas</code> module</a>.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The <code>org.eclipse.jetty.jaas.JAASLoginService</code> can be declared in a couple of different places, pick whichever suits your purposes best:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If you have more than one webapp that you would like to use the same security infrastructure, then you can declare your <code>org.eclipse.jetty.jaas.JAASLoginService</code> as a bean that is added to the <code>org.eclipse.jetty.server.Server</code>.
The file in which you declare this needs to be on Jetty&#8217;s execution path.
The recommended procedure is to create a file in your <code>$jetty.base/etc</code> directory and then ensure it is on the classpath either by adding it to the Jetty <a href="#og-start-jar">start command line</a>, or more conveniently to a <a href="#custom-modules">custom module</a>.</p>
<div class="paragraph">
<p>Here&#8217;s an example of this type of XML file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Server</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.Server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">addBean</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.jaas.JAASLoginService</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">name</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>Test JAAS Realm<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">LoginModuleName</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>xyz<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
</li>
<li>
<p>Alternatively, if you want to use JAAS with a specific webapp only, you declare your <code>org.eclipse.jetty.jaas.JAASLoginService</code> in a context XLM file specific to that webapp:</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">securityHandler</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.security.ConstraintSecurityHandler</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">loginService</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.jaas.JAASLoginService</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">name</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>Test JAAS Realm<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">loginModuleName</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>xyz<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="sect4">
<h5 id="og-jaas-loginconf"><a class="anchor" href="#og-jaas-loginconf"></a><a class="link" href="#og-jaas-loginconf">Configure JAAS</a></h5>
<div class="paragraph">
<p>We now need to setup the contents of the file we specified as the <code>jetty.jaas.login.conf</code> property when we <a href="#og-jaas-module">configured the <code>jaas</code> module</a>.
Refer to the <a href="https://docs.oracle.com/javase/7/docs/api/javax/security/auth/login/Configuration.html">syntax rules</a> of this file for a full description.</p>
</div>
<div class="paragraph">
<p>Remembering the example we set up <a href="#og-jaas-webapp">previously</a>, the contents of the <code>$jetty.base/etc/login.conf</code> file could look as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>xyz { <i class="conum" data-value="1"></i><b>(1)</b>
com.acme.SomeLoginModule required debug=true; <i class="conum" data-value="2"></i><b>(2)</b>
com.other.OtherLoginModule optional; <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 name of the configuration <em>exactly</em> as specified in your <code>org.eclipse.jetty.jaas.JAASLoginService</code> declaration.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The first <code>LoginModule</code> declaration, containing the classname of the <code>LoginModule</code> and its configuration properties.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>A second <code>LoginModule</code> declaration.
You can provide as many <code>LoginModule</code> alternatives as you like, with a minimum of one.
Refer to the <a href="https://docs.oracle.com/javase/7/docs/api/javax/security/auth/login/Configuration.html">JAAS documentation</a> for more information on the standard configuration properties, and how JAAS interprets this file.</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-jaas-loginmodules"><a class="anchor" href="#og-jaas-loginmodules"></a><a class="link" href="#og-jaas-loginmodules">Provided LoginModules</a></h4>
<div class="ulist">
<ul>
<li>
<p><a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/jaas/spi/JDBCLoginModule.html"><code>org.eclipse.jetty.jaas.spi.JDBCLoginModule</code></a></p>
</li>
<li>
<p><a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.html"><code>org.eclipse.jetty.jaas.spi.PropertyFileLoginModule</code></a></p>
</li>
<li>
<p><a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/jaas/spi/DataSourceLoginModule.html"><code>org.eclipse.jetty.jaas.spi.DataSourceLoginModule</code></a></p>
</li>
<li>
<p><a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/jaas/spi/LdapLoginModule.html"><code>org.eclipse.jetty.jaas.ldap.LdapLoginModule</code></a></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>Passwords can be stored in clear text, obfuscated or checksummed.
The class <a href="https://www.eclipse.org/jetty/javadoc/jetty-10/org/eclipse/jetty/util/security/Password.html"><code>org.eclipse.jetty.util.security.Password</code></a> should be used to generate all varieties of passwords,the output from which can be put in to property files or entered into database tables.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="og-jdbcloginmodule"><a class="anchor" href="#og-jdbcloginmodule"></a><a class="link" href="#og-jdbcloginmodule">JDBCLoginModule</a></h5>
<div class="paragraph">
<p>The <code>org.eclipse.jetty.jaas.spi.JDBCLoginModule</code> stores user passwords and roles in a database accessed via JDBC calls.
You can configure the JDBC connection information, as well as the names of the table and columns storing the username and credential, and the names of the table and columns storing the roles.</p>
</div>
<div class="paragraph">
<p>Here is an example <a href="#og-jaas-loginconf">login module configuration file</a> entry for it using an HSQLDB driver:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>jdbc { <i class="conum" data-value="1"></i><b>(1)</b>
org.eclipse.jetty.jaas.spi.JDBCLoginModule required <i class="conum" data-value="2"></i><b>(2)</b> <i class="conum" data-value="3"></i><b>(3)</b>
dbUrl=&quot;jdbc:hsqldb:.&quot; <i class="conum" data-value="4"></i><b>(4)</b>
dbUserName=&quot;sa&quot; <i class="conum" data-value="5"></i><b>(5)</b>
dbDriver=&quot;org.hsqldb.jdbcDriver&quot; <i class="conum" data-value="6"></i><b>(6)</b>
userTable=&quot;myusers&quot; <i class="conum" data-value="7"></i><b>(7)</b>
userField=&quot;myuser&quot; <i class="conum" data-value="8"></i><b>(8)</b>
credentialField=&quot;mypassword&quot; <i class="conum" data-value="9"></i><b>(9)</b>
userRoleTable=&quot;myuserroles&quot; <i class="conum" data-value="10"></i><b>(10)</b>
userRoleUserField=&quot;myuser&quot; <i class="conum" data-value="11"></i><b>(11)</b>
userRoleRoleField=&quot;myrole&quot;; <i class="conum" data-value="12"></i><b>(12)</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 name of the configuration.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The name of the <code>LoginModule</code> class.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>A standard JAAS flag making successful authentication via this <code>LoginModule</code> mandatory.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>The JDBC url used to connect to the database.</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>The name of the JDBC user to use for the connection.</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>The name of the JDBC Driver class.</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>The name of the table holding the user authenication information.</td>
</tr>
<tr>
<td><i class="conum" data-value="8"></i><b>8</b></td>
<td>The name of the column holding the user name.</td>
</tr>
<tr>
<td><i class="conum" data-value="9"></i><b>9</b></td>
<td>The name of the column holding the user credential.</td>
</tr>
<tr>
<td><i class="conum" data-value="10"></i><b>10</b></td>
<td>The name of the table holding the user authorization information.</td>
</tr>
<tr>
<td><i class="conum" data-value="11"></i><b>11</b></td>
<td>The name of the column holding the user name.</td>
</tr>
<tr>
<td><i class="conum" data-value="12"></i><b>12</b></td>
<td>The name of the column holding the user role.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The properties <strong>7</strong>-<strong>12</strong> are used to format the following queries:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="sql"><span class="class">select</span> &lt;credentialField&gt; <span class="keyword">from</span> &lt;userTable&gt; <span class="keyword">where</span> &lt;userField&gt;=<span class="error">?</span>
<span class="class">select</span> &lt;userRoleRoleField&gt; <span class="keyword">from</span> &lt;userRoleTable&gt; <span class="keyword">where</span> &lt;userRoleUserField&gt;=<span class="error">?</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Credential and role information is lazily read from the database when a previously unauthenticated user requests authentication.
Note that this information is <em>only</em> cached for the length of the authenticated session.
When the user logs out or the session expires, the information is flushed from memory.</p>
</div>
<div class="paragraph">
<p>Note that passwords can be stored in the database in plain text or encoded formats&#8201;&#8212;&#8201;see the note on "Passwords/Credentials" above.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-datasourceloginmodule"><a class="anchor" href="#og-datasourceloginmodule"></a><a class="link" href="#og-datasourceloginmodule">DataSourceLoginModule</a></h5>
<div class="paragraph">
<p>Similar to the <code>org.eclipse.jetty.jaas.spi.JDBCLoginModule</code>, but using a <code>javax.sql.DataSource</code> to connect to the database instead of a JDBC driver.
The <code>javax.sql.DataSource</code> is obtained at runtime by performing a JNDI lookup on <code>java:comp/env/${dnJNDIName}</code>.</p>
</div>
<div class="paragraph">
<p>A sample login module configuration for this <code>LoginModule</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>ds { <i class="conum" data-value="1"></i><b>(1)</b>
org.eclipse.jetty.jaas.spi.DataSourceLoginModule required <i class="conum" data-value="2"></i><b>(2)</b> <i class="conum" data-value="3"></i><b>(3)</b>
dbJNDIName=&quot;ds&quot; <i class="conum" data-value="4"></i><b>(4)</b>
userTable=&quot;myusers&quot; <i class="conum" data-value="5"></i><b>(5)</b>
userField=&quot;myuser&quot; <i class="conum" data-value="6"></i><b>(6)</b>
credentialField=&quot;mypassword&quot; <i class="conum" data-value="7"></i><b>(7)</b>
userRoleTable=&quot;myuserroles&quot; <i class="conum" data-value="8"></i><b>(8)</b>
userRoleUserField=&quot;myuser&quot; <i class="conum" data-value="9"></i><b>(9)</b>
userRoleRoleField=&quot;myrole&quot;; <i class="conum" data-value="10"></i><b>(10)</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 name of the configuration.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The name of the <code>LoginModule</code> class.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>A standard JAAS flag making successful authentication via this <code>LoginModule</code> mandatory.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>The JNDI name, relative to <code>java:comp/env/</code> to lookup to obtain the <code>javax.sql.DataSource</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>The name of the table holding the user authenication information.</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>The name of the column holding the user name.</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>The name of the column holding the user credential.</td>
</tr>
<tr>
<td><i class="conum" data-value="8"></i><b>8</b></td>
<td>The name of the table holding the user authorization information.</td>
</tr>
<tr>
<td><i class="conum" data-value="9"></i><b>9</b></td>
<td>The name of the column holding the user name.</td>
</tr>
<tr>
<td><i class="conum" data-value="10"></i><b>10</b></td>
<td>The name of the column holding the user role.</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="og-propertyfileloginmodule"><a class="anchor" href="#og-propertyfileloginmodule"></a><a class="link" href="#og-propertyfileloginmodule">PropertyFileLoginModule</a></h5>
<div class="paragraph">
<p>With this login module implementation, the authentication and role information is read from a property file.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>props { <i class="conum" data-value="1"></i><b>(1)</b>
org.eclipse.jetty.jaas.spi.PropertyFileLoginModule required <i class="conum" data-value="2"></i><b>(2)</b> <i class="conum" data-value="3"></i><b>(3)</b>
file=&quot;/somewhere/somefile.props&quot;; <i class="conum" data-value="4"></i><b>(4)</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 name of the configuration.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The name of the <code>LoginModule</code> class.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>A standard JAAS flag making successful authentication via this <code>LoginModule</code> mandatory.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>The location of a properties file containing the authentication and authorization information.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The property file must be of the format:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="text">&lt;username&gt;: &lt;password&gt; [,&lt;rolename&gt; ...]</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here&#8217;s an example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>fred: OBF:1xmk1w261u9r1w1c1xmq,user,admin
harry: changeme,user,developer
tom: MD5:164c88b302622e17050af52c89945d44,user
dick: CRYPT:adpexzg3FUZAk,admin</pre>
</div>
</div>
<div class="paragraph">
<p>The contents of the file are fully read in and cached in memory the first time a user requests authentication.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-ldaploginmodule"><a class="anchor" href="#og-ldaploginmodule"></a><a class="link" href="#og-ldaploginmodule">LdapLoginModule</a></h5>
<div class="paragraph">
<p>The <code>org.eclipse.jetty.jaas.spi.LdapLoginModule</code> uses LDAP to access authentication and authorization information stored in a directory.
The LDAP connection information and structure of the authentication/authorization data can be configured.</p>
</div>
<div class="paragraph">
<p>Here&#8217;s an example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>example { <i class="conum" data-value="1"></i><b>(1)</b>
org.eclipse.jetty.jaas.spi.LdapLoginModule required <i class="conum" data-value="2"></i><b>(2)</b> <i class="conum" data-value="3"></i><b>(3)</b>
contextFactory=&quot;com.sun.jndi.ldap.LdapCtxFactory&quot; <i class="conum" data-value="4"></i><b>(4)</b>
hostname=&quot;ldap.example.com&quot; <i class="conum" data-value="5"></i><b>(5)</b>
port=&quot;389&quot; <i class="conum" data-value="6"></i><b>(6)</b>
bindDn=&quot;cn=Directory Manager&quot; <i class="conum" data-value="7"></i><b>(7)</b>
bindPassword=&quot;directory&quot; <i class="conum" data-value="8"></i><b>(8)</b>
authenticationMethod=&quot;simple&quot; <i class="conum" data-value="9"></i><b>(9)</b>
useLdaps=&quot;true&quot; <i class="conum" data-value="10"></i><b>(10)</b>
userBaseDn=&quot;ou=people,dc=alcatel&quot; <i class="conum" data-value="11"></i><b>(11)</b>
userRdnAttribute=&quot;uid&quot; <i class="conum" data-value="12"></i><b>(12)</b>
userIdAttribute=&quot;cn&quot; <i class="conum" data-value="13"></i><b>(13)</b>
userPasswordAttribute=&quot;userPassword&quot; <i class="conum" data-value="14"></i><b>(14)</b>
userObjectClass=&quot;inetOrgPerson&quot; <i class="conum" data-value="15"></i><b>(15)</b>
roleBaseDn=&quot;ou=groups,dc=example,dc=com&quot; <i class="conum" data-value="16"></i><b>(16)</b>
roleNameAttribute=&quot;cn&quot; <i class="conum" data-value="17"></i><b>(17)</b>
roleMemberAttribute=&quot;uniqueMember&quot; <i class="conum" data-value="18"></i><b>(18)</b>
roleObjectClass=&quot;groupOfUniqueNames&quot;; <i class="conum" data-value="19"></i><b>(19)</b>
forceBindingLogin=&quot;false&quot; <i class="conum" data-value="20"></i><b>(20)</b>
debug=&quot;false&quot; <i class="conum" data-value="21"></i><b>(21)</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 name of the configuration.</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The name of the <code>LoginModule</code> class.</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>A standard JAAS flag making successful authentication via this <code>LoginModule</code> mandatory.</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>The name of the context factory to use for the LDAP connection.</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>The hostname for the LDAP connection. Optional.</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>The port for the LDAP connection. Optional.</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>The caller security Principal. Optional.</td>
</tr>
<tr>
<td><i class="conum" data-value="8"></i><b>8</b></td>
<td>The caller security credential. Optional.</td>
</tr>
<tr>
<td><i class="conum" data-value="9"></i><b>9</b></td>
<td>The security level for the LDAP connection environment. Optional.</td>
</tr>
<tr>
<td><i class="conum" data-value="10"></i><b>10</b></td>
<td>If true, use <code>ldaps</code> instead of <code>ldap</code> for the connection url.</td>
</tr>
<tr>
<td><i class="conum" data-value="11"></i><b>11</b></td>
<td>The distinguished name of the directory to search for user information.</td>
</tr>
<tr>
<td><i class="conum" data-value="12"></i><b>12</b></td>
<td>The name of the attribute for the user roles.</td>
</tr>
<tr>
<td><i class="conum" data-value="13"></i><b>13</b></td>
<td>The name of the attribute for the user id.</td>
</tr>
<tr>
<td><i class="conum" data-value="14"></i><b>14</b></td>
<td>The name of the attribute for the user password.</td>
</tr>
<tr>
<td><i class="conum" data-value="15"></i><b>15</b></td>
<td>The <code>ObjectClass</code> for users.</td>
</tr>
<tr>
<td><i class="conum" data-value="16"></i><b>16</b></td>
<td>The distinguished name of the directory to search for role information.</td>
</tr>
<tr>
<td><i class="conum" data-value="17"></i><b>17</b></td>
<td>The name of the attribute for roles.</td>
</tr>
<tr>
<td><i class="conum" data-value="18"></i><b>18</b></td>
<td>The name of the attribute storing the user for the roles <code>ObjectClass</code>.</td>
</tr>
<tr>
<td><i class="conum" data-value="19"></i><b>19</b></td>
<td>The name of the <code>ObjectClass</code> for roles.</td>
</tr>
<tr>
<td><i class="conum" data-value="20"></i><b>20</b></td>
<td>If true, the authentication proceeds on the basis of a successful LDAP binding using the username and credential provided by the user.
If false, then authentication proceeds based on username and password information retrieved from LDAP.</td>
</tr>
<tr>
<td><i class="conum" data-value="21"></i><b>21</b></td>
<td>If true, failed login attempts are logged on the server.</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-jaspi"><a class="anchor" href="#og-jaspi"></a><a class="link" href="#og-jaspi">JASPI</a></h3>
<div class="paragraph">
<p>Enabling this module allows Jetty to utilize authentication modules that implement the JSR 196 (JASPI) specification. JASPI provides an SPI (Service Provider Interface) for pluggable, portable, and standardized authentication modules. Compatible modules are portable between servers that support the JASPI specification. This module provides a bridge from Java Authentication to the Jetty Security framework.</p>
</div>
<div class="paragraph">
<p>Only modules conforming to the "Servlet Container Profile" with the ServerAuthModule interface within the <a href="https://www.jcp.org/en/jsr/detail?id=196">JASPI Spec</a> are supported. These modules must be configured before start-up. Operations for runtime registering or de-registering authentication modules are not supported.</p>
</div>
<div class="sect3">
<h4 id="og-jaspi-configuration"><a class="anchor" href="#og-jaspi-configuration"></a><a class="link" href="#og-jaspi-configuration">Configuration</a></h4>
<div class="sect4">
<h5 id="og-jaspi-module"><a class="anchor" href="#og-jaspi-module"></a><a class="link" href="#og-jaspi-module">The <code>jaspi</code> module</a></h5>
<div class="paragraph">
<p>Enable the <code>jaspi</code> module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre># DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables JASPI authentication for deployed web applications.
[tags]
security
[depend]
security
auth-config-factory
[lib]
lib/jetty-jaspi-${jetty.version}.jar
lib/jaspi/*.jar
[xml]
etc/jaspi/jaspi-authmoduleconfig.xml
[files]
basehome:etc/jaspi/jaspi-authmoduleconfig.xml|etc/jaspi/jaspi-authmoduleconfig.xml</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-jaspi-xml"><a class="anchor" href="#og-jaspi-xml"></a><a class="link" href="#og-jaspi-xml">Configure JASPI</a></h5>
<div class="paragraph">
<p>To enable the <code>jaspi</code> module you can 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=jaspi</pre>
</div>
</div>
<div class="paragraph">
<p>You can then register a <code>AuthConfigProvider</code> onto the static <code>AuthConfigFactory</code> obtained with <code>AuthConfigFactory.getFactory()</code>. This registration can be done in the XML configuration file which will be copied to <code>$JETTY_BASE/etc/jaspi/jaspi-authmoduleconfig.xml</code> when the module is enabled.</p>
</div>
<div class="sect5">
<h6 id="og-jaspi-demo"><a class="anchor" href="#og-jaspi-demo"></a><a class="link" href="#og-jaspi-demo">JASPI Demo</a></h6>
<div class="paragraph">
<p>The <code>jaspi-demo</code> module illustrates setting up HTTP Basic Authentication using a Java Authentication module that comes packaged with jetty: <code>org.eclipse.jetty.security.jaspi.modules.BasicAuthenticationAuthModule</code>, and applies it for a context named <code>/test</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">javax.security.auth.message.config.AuthConfigFactory</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">getFactory</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">registerConfigProvider</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- The Jetty provided implementation of AuthConfigProvider which will wrap a ServerAuthModule. --&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>org.eclipse.jetty.security.jaspi.provider.JaspiAuthConfigProvider<span class="tag">&lt;/Arg&gt;</span>
<span class="comment">&lt;!-- A Map of initialization properties. --&gt;</span>
<span class="tag">&lt;Arg&gt;</span>
<span class="tag">&lt;Map&gt;</span>
<span class="tag">&lt;Entry&gt;</span>
<span class="comment">&lt;!-- Provide the fully qualified classname of the ServerAuthModule to be used. --&gt;</span>
<span class="tag">&lt;Item&gt;</span>ServerAuthModule<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>org.eclipse.jetty.security.jaspi.modules.BasicAuthenticationAuthModule<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Entry&gt;</span>
<span class="tag">&lt;Entry&gt;</span>
<span class="comment">&lt;!-- Realm as utilised by Jetty Security --&gt;</span>
<span class="tag">&lt;Item&gt;</span>org.eclipse.jetty.security.jaspi.modules.RealmName<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>Test Realm<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Entry&gt;</span>
<span class="tag">&lt;/Map&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="comment">&lt;!-- Message Layer Identifier as per spec chapter 3.1 --&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>HttpServlet<span class="tag">&lt;/Arg&gt;</span>
<span class="comment">&lt;!-- Application Context Identifier as per spec chapter 3.2
AppContextID ::= hostname blank context-path
The algorithm applied here will use the
_serverName on the configured JaspiAuthenticatorFactory (if set) and try to match it
against the &quot;server&quot; part (in the &quot;server /test&quot; example below).
Next it will try to match the ServletContext#getVirtualServerName to the &quot;server&quot; part.
If neither are set, it will then try to match the first Subject's principal name, and finally fall back to
the default value &quot;server&quot; if none are available.
The context-path should match the context path where this applies.
--&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>server /test<span class="tag">&lt;/Arg&gt;</span>
<span class="comment">&lt;!-- A friendly description of the provided auth-module. --&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>A simple provider using HTTP BASIC authentication.<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This example uses the <code>AuthConfigProvider</code> implementation provided by Jetty to register a <code>ServerAuthModule</code> directly. Other custom or 3rd party modules that are compatible with the <code>ServerAuthModule</code> interface in JASPI can be registered in the same way.</p>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-integration-with-jetty-authentication-mechanisms"><a class="anchor" href="#og-integration-with-jetty-authentication-mechanisms"></a><a class="link" href="#og-integration-with-jetty-authentication-mechanisms">Integration with Jetty Authentication Mechanisms</a></h5>
<div class="paragraph">
<p>To integrate with Jetty authentication mechanisms you must add a <code>LoginService</code> to your context. The <code>LoginService</code> provides a way for you to obtain a <code>UserIdentity</code> from a username and credentials. JASPI can interact with this Jetty <code>LoginService</code> by using the <code>PasswordValidationCallback</code>.</p>
</div>
<div class="paragraph">
<p>The <code>CallerPrincipalCallback</code> and <code>GroupPrincipalCallback</code> do not require use of a Jetty <code>LoginService</code>. The principal from the <code>CallerPrincipalCallback</code> will be used directly with the <code>IdentityService</code> to produce a <code>UserIdentity</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-replacing-the-jetty-defaultauthconfigfactory"><a class="anchor" href="#og-replacing-the-jetty-defaultauthconfigfactory"></a><a class="link" href="#og-replacing-the-jetty-defaultauthconfigfactory">Replacing the Jetty DefaultAuthConfigFactory</a></h5>
<div class="paragraph">
<p>Jetty provides an implementation of the <code>AuthConfigFactory</code> interface which is used to register <code>AuthConfigProviders</code>. This can be replaced by a custom implementation by adding a custom module which provides <code>auth-config-factory</code>.
This custom module must reference an XML file which sets a new instance of the <code>AuthConfigFactory</code> with the static method <code>AuthConfigFactory.setFactory()</code>.
For an example of this see the <code>jaspi-default-auth-config-factory</code> module, which provides the default implementation used by Jetty.</p>
</div>
<div class="listingblock">
<div class="content">
<pre># DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Provides a DefaultAuthConfigFactory for jaspi
[tags]
security
[depend]
security
[provide]
auth-config-factory
[xml]
etc/jaspi/jaspi-default.xml</pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-jmx"><a class="anchor" href="#og-jmx"></a><a class="link" href="#og-jmx">Eclipse Jetty Monitoring &amp; Management</a></h3>
<div class="paragraph">
<p>Monitoring and management of a Jetty server is important because it allows you to monitor the status of the server (<em>"Is the server processing requests?"</em>) and to manage&#8201;&#8212;&#8201;i.e. read and possibly change&#8201;&#8212;&#8201;its configuration.</p>
</div>
<div class="paragraph">
<p>The ability to read and change the Jetty configuration is very important for troubleshooting Jetty&#8201;&#8212;&#8201;please refer to the <a href="#og-troubleshooting">troubleshooting section</a> for more information.</p>
</div>
<div class="paragraph">
<p>Jetty relies on the Java Management Extensions (JMX) APIs included in OpenJDK to provide monitoring and management.</p>
</div>
<div class="paragraph">
<p>The JMX APIs support a JVM-local <code>MBeanServer</code>, accessible only from within the JVM itself (or by tools that can <em>attach</em> to a running JVM), and a way to expose the <code>MBeanServer</code> to remote clients via Java&#8217;s RMI (Remote Method Invocation).</p>
</div>
<div class="sect3">
<h4 id="og-jmx-local"><a class="anchor" href="#og-jmx-local"></a><a class="link" href="#og-jmx-local">Enabling Local JMX Support</a></h4>
<div class="paragraph">
<p>As with many other Jetty features, local JMX support is enabled with the <code>jmx</code> Jetty module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=jmx</pre>
</div>
</div>
<div class="paragraph">
<p>With the <code>jmx</code> Jetty module enabled, Jetty components will be exported as JMX <em>MBeans</em> to the JVM platform <code>MBeanServer</code>, so that they can be accessed by JMX compliant tools.</p>
</div>
<div class="paragraph">
<p>Each Jetty component will export to its correspondent MBean relevant configuration parameters, so that a JMX tool can read and possibly change the component configuration through the MBean.</p>
</div>
<div class="paragraph">
<p>Note that the Jetty MBeans are registered into the platform <code>MBeanServer</code>, but are not available to remote clients: they are <em>local</em> to the JVM.</p>
</div>
<div class="paragraph">
<p>This configuration is useful when you develop and test your Jetty server locally.</p>
</div>
<div class="paragraph">
<p>JMX compliant tools such as <a href="https://adoptopenjdk.net/jmc.html">Java Mission Control (JMC)</a> can be started locally on your machine and can attach to other JVMs running on your machine, showing you the registered MBeans among which you will find the Jetty MBeans.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Enabling only the local JMX support is the most secure option for monitoring and management, but only users that have local access to the JVM will be able to browse the MBeans.
If you need to access the MBeans from a remote machine, read <a href="#og-jmx-remote">this section</a>.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="og-jmx-remote"><a class="anchor" href="#og-jmx-remote"></a><a class="link" href="#og-jmx-remote">Enabling Remote JMX Support</a></h4>
<div class="paragraph">
<p>There are two ways to configure a Jetty server so that it is possible to access the JVM platform MBeans from remote clients:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Use the <code>com.sun.management.jmxremote</code> and related system properties when starting Jetty.
Unfortunately, this solution does not work well with firewalls, and will not be discussed further.</p>
</li>
<li>
<p>Use the <code>jmx-remote</code> Jetty module.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Both ways use Java&#8217;s Remote Method Invocation (RMI) to communicate between the client and the server.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="title">Refresher: How RMI Works</div>
<div class="paragraph">
<p>A server application that wants to make an object available to remote clients must <em>export</em> the object.</p>
</div>
<div class="paragraph">
<p>Exporting an object creates an RMI <em>stub</em> that contains the host/port of the RMI <em>server</em> that accepts incoming invocations from clients and forwards them to the object.
During the creation of the RMI stub, the host stored in the RMI stub is retrieved from the local name resolution system (for example, in Linux, from <code>/etc/hosts</code>).</p>
</div>
<div class="paragraph">
<p>The RMI stub is then sent, along with a name that uniquely identifies the object, to the RMI <em>registry</em>.
The RMI registry is a service that maps names to RMI stubs; it may be external to both clients and server, although often it is part of the server JVM.</p>
</div>
<div class="paragraph">
<p>When a client application wants to connect to the server object using RMI, it first connects to the RMI registry to download the RMI stub for the RMI server; recall that the RMI stub contains the host/port to connect to the RMI server.
Then, the client uses the RMI stub to connect to the RMI server, typically to a host/port that may be different from the RMI registry host/port (in particular, by default the RMI server port will be different from the RMI registry port).</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Remote access to the platform MBeans, and therefore the Jetty MBeans, is enabled by the <code>jmx-remote</code> Jetty module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=jmx-remote</pre>
</div>
</div>
<div class="paragraph">
<p>This command creates the <code>jmx-remote.ini</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>JETTY_BASE
└── start.d
└── <mark>jmx-remote.ini</mark></code></pre>
</div>
</div>
<div class="paragraph">
<p>Enabling the <code>jmx-remote</code> module transitively enables the <a href="#og-jmx-local"><code>jmx</code> module</a> as well.</p>
</div>
<div class="paragraph">
<p>The configuration for the RMI registry and the RMI server is specified by a <code>JMXServiceURL</code>.
The string format of an RMI <code>JMXServiceURL</code> is the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>service:jmx:rmi://&lt;rmi_server_host&gt;:&lt;rmi_server_port&gt;/jndi/rmi://&lt;rmi_registry_host&gt;:&lt;rmi_registry_port&gt;/jmxrmi</pre>
</div>
</div>
<div class="paragraph">
<p>Below you can find examples of <code>JMXServiceURL</code>s:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code><strong>service:jmx:rmi:///jndi/rmi:///jmxrmi</strong>
where:
rmi_server_host = local host address
rmi_server_port = randomly chosen
rmi_registry_host = local host address
rmi_registry_port = 1099
<strong>service:jmx:rmi://0.0.0.0:1099/jndi/rmi://0.0.0.0:1099/jmxrmi</strong>
where:
rmi_server_host = any address
rmi_server_port = 1099
rmi_registry_host = any address
rmi_registry_port = 1099
<strong>service:jmx:rmi://localhost:1100/jndi/rmi://localhost:1099/jmxrmi</strong>
where:
rmi_server_host = loopback address
rmi_server_port = 1100
rmi_registry_host = loopback address
rmi_registry_port = 1099</code></pre>
</div>
</div>
<div class="paragraph">
<p>The default <code>JMXServiceURL</code> configured by the <code>jmx-remote</code> module is the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>service:jmx:rmi://localhost:1099/jndi/rmi://localhost:1099/jmxrmi</pre>
</div>
</div>
<div class="paragraph">
<p>With the default configuration, only clients that are local to the server machine can connect to the RMI registry and RMI server - this is done for security reasons.
However, even with this local-only configuration, it would still be possible to access the MBeans from remote using an SSH tunnel, as explained in <a href="#og-jmx-remote-ssh-tunnel">this section</a>.</p>
</div>
<div class="paragraph">
<p>By specifying an appropriate <code>JMXServiceURL</code>, you can fine tune the network address the RMI registry and the RMI server bind to, and the ports that the RMI registry and the RMI server listen to.
The RMI server and RMI registry hosts and ports can be the same (as in the default configuration) because RMI is able to multiplex traffic arriving to one port to multiple RMI objects.</p>
</div>
<div class="paragraph">
<p>If you need to allow JMX remote access through a firewall, you must open both the RMI registry and the RMI server ports.
The default configuration simplifies the firewall configuration because you only need to open port <code>1099</code>.</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>When Jetty is started with the <code>jmx-remote</code> module enabled, the RMI stub of the Jetty component that provides access to the MBeans is exported to the RMI registry.</p>
</div>
<div class="paragraph">
<p>The RMI stub contains the host/port to connect to the RMI server, but the host is typically the machine host name, not the host specified in the <code>JMXServiceURL</code> (the latter is only used to specify the network address the RMI server binds to).</p>
</div>
<div class="paragraph">
<p>To control the host stored in the RMI stub you need to set the system property <code>java.rmi.server.hostname</code> with the desired value in the module configuration file, <code>jmx-remote.ini</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 client cannot connect to the server, the most common cause is a mismatch between the RMI server host of the <code>JMXServiceURL</code> and the RMI server host of the RMI stub.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>You can customize the RMI server host/port, the RMI registry host/port and the system property <code>java.rmi.server.hostname</code> by editing the <code>jmx-remote.ini</code> configuration file.
Further information about the <code>jmx-remote</code> module configuration can be found <a href="#og-module-jmx-remote">here</a>.</p>
</div>
<div class="sect4">
<h5 id="og-jmx-remote-ssh-tunnel"><a class="anchor" href="#og-jmx-remote-ssh-tunnel"></a><a class="link" href="#og-jmx-remote-ssh-tunnel">Remote JMX Access with Port Forwarding via SSH Tunnel</a></h5>
<div class="paragraph">
<p>You can access JMX MBeans on a remote machine when the RMI ports are not open, for example because of firewall policies, but you have SSH access to the machine, using local port forwarding via an SSH tunnel.</p>
</div>
<div class="paragraph">
<p>In this case you want to configure the <code>JMXServiceURL</code> that binds the RMI server and the RMI registry to the loopback interface only and to the same port:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>service:jmx:rmi://localhost:1099/jndi/rmi://localhost:1099/jmxrmi</pre>
</div>
</div>
<div class="paragraph">
<p>You must set the system property <code>-Djava.rmi.server.hostname=localhost</code> so that the RMI stub contains <code>localhost</code> as the host name to connect to.
This is, incidentally, the default configuration of the <code>jmx-remote</code> module.</p>
</div>
<div class="paragraph">
<p>Then you set up the local port forwarding with the SSH tunnel:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ ssh -L 1099:localhost:1099 &lt;user&gt;@&lt;machine_host&gt;</pre>
</div>
</div>
<div class="paragraph">
<p>Thanks to the local port forwarding of the SSH tunnel, when the client connects to <code>localhost:1099</code> on your local computer, the traffic will be forwarded to <code>machine_host</code> and when there, the SSH daemon will forward the traffic to <code>localhost:1099</code> on <code>machine_host</code>, which is exactly where the RMI server and the RMI registry listens to.</p>
</div>
<div class="paragraph">
<p>The client first contacts the RMI registry, so it connects to <code>localhost:1099</code> on your local computer; the traffic is forwarded to <code>machine_host</code> through the SSH tunnel, connects to the RMI registry and the RMI stub is downloaded to the client.</p>
</div>
<div class="paragraph">
<p>Then the client uses the RMI stub to connect to the RMI server. The RMI stub contains <code>localhost</code> as the RMI server host because that is what you have configured with the system property <code>java.rmi.server.hostname</code>.</p>
</div>
<div class="paragraph">
<p>The client will connect again to <code>localhost:1099</code> on your local computer, this time to contact the RMI server; the traffic is forwarded to <code>machine_host</code> through the SSH tunnel, arrives to <code>machine_host</code> and connects to the RMI server.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-jmx-remote-auth"><a class="anchor" href="#og-jmx-remote-auth"></a><a class="link" href="#og-jmx-remote-auth">Remote JMX Access Authentication &amp; Authorization</a></h5>
<div class="paragraph">
<p>The standard <code>javax.management.remote.JMXConnectorServer</code> class, used by the <code>jmx-remote</code> module to provide remote JMX access to Jetty MBeans, provides several options to authenticate and authorize users.
For a complete guide to controlling authentication and authorization in JMX, see <a href="https://docs.oracle.com/en/java/javase/11/management/monitoring-and-management-using-jmx-technology.html">the official JMX documentation</a>.</p>
</div>
<div class="paragraph">
<p>The simplest way to control JMX authentication and authorization is to specify two files: one contains username and password pairs, and the other contains username and permission pairs.</p>
</div>
<div class="paragraph">
<p>This is achieved by enabling the <code>jmx-remote-auth</code> Jetty module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=jmx-remote-auth</pre>
</div>
</div>
<div class="paragraph">
<p>Enabling the <code>jmx-remote-auth</code> Jetty module creates the following files:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$JETTY_BASE
├── etc
│ ├── jmxremote.access
│ ├── jmxremote.password
│ └── jmx-remote-auth.xml
└── start.d
├── jmx-remote-auth.ini
└── jmx-remote.ini</pre>
</div>
</div>
<div class="paragraph">
<p>Then you edit the <code>$JETTY_BASE/etc/jmxremote.password</code> file, adding the username/password pairs that you need:</p>
</div>
<div class="listingblock">
<div class="title">$JETTY_BASE/etc/jmxremote.password</div>
<div class="content">
<pre># The file format is: &lt;username&gt; &lt;password&gt;
alice wonderland
bob marley</pre>
</div>
</div>
<div class="paragraph">
<p>You must also edit the <code>$JETTY_BASE/etc/jmxremote.access</code> file to give permissions to your users:</p>
</div>
<div class="listingblock">
<div class="title">$JETTY_BASE/etc/jmxremote.access</div>
<div class="content">
<pre># The file format is: &lt;username&gt; &lt;readonly|readwrite&gt;
alice readwrite
bob readonly</pre>
</div>
</div>
<div class="paragraph">
<p>The above files define user <code>alice</code> with password <code>wonderland</code> to have <code>readwrite</code> access, and user <code>bob</code> with password <code>marley</code> to have <code>readonly</code> access.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-jmx-remote-secure"><a class="anchor" href="#og-jmx-remote-secure"></a><a class="link" href="#og-jmx-remote-secure">Securing Remote JMX Access with TLS</a></h5>
<div class="paragraph">
<p>The JMX communication via RMI happens by default in clear-text, but it is possible to secure the JMX communication via RMI with TLS.</p>
</div>
<div class="paragraph">
<p>If you want to reuse the configuration that you are using for the <a href="#og-protocols-https"><code>https</code> module</a>, you can just enable the <code>jmx-remote-ssl.xml</code> Jetty module:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-module=jmx-remote-ssl</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>The <code>jmx-remote-ssl</code> Jetty module depends on the <code>ssl</code> Jetty module that in turn requires a KeyStore (read <a href="#og-protocols-ssl">this section</a> for more information).</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The KeyStore must contain a valid certificate signed by a Certification Authority.
Having certificates signed by a Certification Authority simplifies by a lot the configuration needed to get the RMI communication over TLS working properly.</p>
</div>
<div class="paragraph">
<p>The RMI mechanic is the usual one: the RMI client (typically a monitoring console) will connect first to the RMI registry (using TLS), download the RMI stub that contains the address and port of the RMI server to connect to, then connect to the RMI server (using TLS).</p>
</div>
<div class="paragraph">
<p>This also mean that if the RMI registry and the RMI server are on different hosts, the RMI client must have available the cryptographic material to validate the certificates from both hosts.
This is where having certificates signed by a Certification Authority simplifies the configuration: if they are signed by a well known Certification Authority, the client does not need any extra configuration&#8201;&#8212;&#8201;everything will be handled by the Java runtime.</p>
</div>
<div class="paragraph">
<p>If the certificates are not signed by a Certification Authority (for example the certificate is self-signed), then you need to specify the TLS system properties that allow RMI (especially when acting as an RMI client) to retrieve the cryptographic material necessary to establish the TLS connection.</p>
</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>When the RMI server exports the <code>JMXConnectorServer</code> it acts as an RMI <em>client</em> towards the RMI registry, and as such you must specify the TLS system properties as detailed below.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>You must edit the <code>$JETTY_BASE/start.d/jmx-remote-ssl.ini</code> file and add the TrustStore path and password:</p>
</div>
<div class="listingblock">
<div class="title">$JETTY_BASE/start.d/jmx-remote-ssl.ini</div>
<div class="content">
<pre>--module=jmx-remote-ssl
# System properties necessary for non-trusted certificates.
-Djavax.net.ssl.trustStore=/path/to/trustStore.p12
-Djavax.net.ssl.trustStorePassword=password</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>The TrustStore must contain the certificate you want to trust.</p>
</div>
<div class="paragraph">
<p>If you are using self-signed certificates, the KeyStore already contains the self-signed certificate and therefore the KeyStore can be used as a TrustStore, and the system properties above can refer to the KeyStore path and password.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>JMX compliant tools that offer a graphical user interface also must be started specifying the TrustStore path and password.</p>
</div>
<div class="paragraph">
<p>For example, to launch <a href="https://adoptopenjdk.net/jmc.html">Java Mission Control (JMC)</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ jmc -vmargs -Djavax.net.ssl.trustStore=/path/to/trustStore.p12 -Djavax.net.ssl.trustStorePassword=password</pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-logging"><a class="anchor" href="#og-logging"></a><a class="link" href="#og-logging">Logging</a></h3>
<div class="paragraph">
<p>There are two types of logging that can be configured in Jetty:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The logging of Jetty itself, that logs the server activity</p>
</li>
<li>
<p>The HTTP request logging, that logs information about HTTP requests and responses processed by Jetty</p>
</li>
</ul>
</div>
<div class="sect3">
<h4 id="og-logging-server"><a class="anchor" href="#og-logging-server"></a><a class="link" href="#og-logging-server">Server Logging</a></h4>
<div class="paragraph">
<p>The Jetty code uses the <a href="http://slf4j.org/">SLF4J</a> API for its logging.</p>
</div>
<div class="paragraph">
<p>Thanks to the SLF4J library, the logging of the Jetty server can therefore be directed to the implementation (called SLF4J <em>binding</em>) of your choice.</p>
</div>
<div class="paragraph">
<p>The Jetty project provides an SLF4J binding (via the <code>jetty-slf4j-impl</code> Maven artifact) that is used as the default SLF4J binding.</p>
</div>
<div class="paragraph">
<p>The logging of the Jetty server itself is enabled by default with the <code>logging</code> Jetty module, which is a transitive dependency of the <code>server</code> module and therefore it is typically always enabled.</p>
</div>
<div class="paragraph">
<p>The <code>logging</code> Jetty module is a <em>virtual</em> module (see <a href="#og-modules-names">this section</a>) and its default implementation is provided by the <code>logging-jetty</code> Jetty module, which uses the Jetty SLF4J binding.</p>
</div>
<div class="sect4">
<h5 id="og-logging-server-default"><a class="anchor" href="#og-logging-server-default"></a><a class="link" href="#og-logging-server-default">Default Configuration</a></h5>
<div class="paragraph">
<p>The Jetty SLF4J binding is configured with an appender (<code>org.eclipse.jetty.logging.StdErrAppender</code>) that directs the logging to <code>System.err</code>, and reads its configuration from a file named <code>jetty-logging.properties</code> that must be found in the class-path.</p>
</div>
<div class="paragraph">
<p>The <code>StdErrAppender</code> format is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>&lt;datetime&gt;:&lt;level&gt;:&lt;logger name&gt;:&lt;thread name&gt;:&lt;message&gt;</pre>
</div>
</div>
<div class="paragraph">
<p>where <code>&lt;datetime&gt;=yyyy-MM-dd HH:mm:ss.SSS</code>.</p>
</div>
<div class="paragraph">
<p>You can configure <code>StdErrAppender</code> by specifying the following properties in <code>jetty-logging.properties</code>:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">org.eclipse.jetty.logging.appender.NAME_CONDENSE=&lt;boolean&gt;</dt>
<dd>
<p>Specifies whether to condense logger names, so that for example <code>org.eclipse.jetty.util.QueuedThreadPool</code> becomes <code>oeju.QueuedThreadPool</code>.
Default value is <code>true</code>.</p>
</dd>
<dt class="hdlist1">org.eclipse.jetty.logging.appender.MESSAGE_ALIGN=&lt;integer&gt;</dt>
<dd>
<p>Specifies the column at which the logging <code>&lt;message&gt;</code> should be printed.
The value <code>0</code> specifies no alignment.
Default value is <code>0</code>.</p>
</dd>
<dt class="hdlist1">org.eclipse.jetty.logging.appender.MESSAGE_ESCAPE=&lt;boolean&gt;</dt>
<dd>
<p>Specifies whether to escape ISO control characters such as <code>\r</code> or <code>\n</code> present in the message.
Character <code>\r</code> is replaced with <code>&lt;</code> and character <code>\n</code> is replaced with <code>|</code>; all other ISO control characters are replaced with <code>?</code>.
Default value is <code>false</code>.</p>
</dd>
<dt class="hdlist1">org.eclipse.jetty.logging.appender.ZONE_ID=&lt;timezone id&gt;</dt>
<dd>
<p>Specifies the timezone ID (such as <code>PST</code>, or <code>America/Los_Angeles</code> or <code>GMT-8:00</code>) for the <code>&lt;datetime&gt;</code> part of the logging line.
The empty string specifies the <code>UTC</code> timezone.
Default value is the local timezone.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The <code>logging-jetty</code> Jetty module, enabled transitively, provides the configuration file <code>$JETTY_BASE/resources/jetty-logging.properties</code> to configure the logging levels, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ cd $JETTY_BASE
$ java -jar $JETTY_HOME/start.jar --add-modules=http</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>$JETTY_BASE
├── resources
│ └── jetty-logging.properties
└── start.d
└── http.ini</pre>
</div>
</div>
<div class="listingblock">
<div class="title">jetty-logging.properties</div>
<div class="content">
<pre class="CodeRay highlight"><code data-lang="properties"># Do not condense logger names.
org.eclipse.jetty.logging.appender.NAME_CONDENSE=false
# By default, log at INFO level all Jetty loggers.
org.eclipse.jetty.LEVEL=INFO
# However, the Jetty client loggers log at DEBUG level.
org.eclipse.jetty.client.LEVEL=DEBUG</code></pre>
</div>
</div>
<div class="paragraph">
<p>The logging levels that you can specify in the <code>jetty-logging.properties</code> file are the usual SLF4J logging levels, <code>TRACE</code>, <code>DEBUG</code>, <code>INFO</code>, <code>WARN</code> and <code>ERROR</code>, plus two additional levels:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>ALL</code>, which is an alias for <code>TRACE</code></p>
</li>
<li>
<p><code>OFF</code>, which disables entirely the logging (not even <code>ERROR</code> level messages are logged)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>When using the Jetty SLF4J binding, the logging levels can be dynamically changed via JMX, see <a href="#og-troubleshooting-logging">the troubleshooting section</a> for more information.</p>
</div>
<div class="sect5">
<h6 id="og-logging-server-default-rolling"><a class="anchor" href="#og-logging-server-default-rolling"></a><a class="link" href="#og-logging-server-default-rolling">Capturing Logs to a Rolling File</a></h6>
<div class="paragraph">
<p>Having the logging output on <code>System.err</code> may be fine at development time, but you typically want the logs to be captured in a file so that they can be looked at even if you don&#8217;t have a terminal (for example, you started Jetty as a service).</p>
</div>
<div class="paragraph">
<p>The <code>console-capture</code> Jetty module allows you to capture what is written to <code>System.out</code> and <code>System.err</code> and write it to a log file, by default under the <code>$JETTY_BASE/logs/</code> directory.</p>
</div>
<div class="paragraph">
<p>The <code>console-capture</code> Jetty module defines a number of properties that you can customize to control the log directory, the number of days rolled files are retained, etc.
See the <a href="#og-module-console-capture"><code>console-capture</code> module</a> for more information.</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>console-capture</code> Jetty module should be used only in conjunction with the <code>logging-jetty</code> module, as other SLF4J bindings such as LogBack or Log4J2 have their own, more sophisticated, rolling file appenders.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-logging-server-custom"><a class="anchor" href="#og-logging-server-custom"></a><a class="link" href="#og-logging-server-custom">Custom Configuration</a></h5>
<div class="paragraph">
<p>You can use a different SLF4J binding if you are more familiar with other logging libraries, or if you need custom logging appenders.
There are a number of out-of-the-box Jetty modules that you can use:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>logging-logback</code>, to use the <a href="http://logback.qos.ch/">LogBack</a> binding</p>
</li>
<li>
<p><code>logging-log4j2</code>, to use the <a href="https://logging.apache.org/log4j/2.x/">Log4J2</a> binding</p>
</li>
<li>
<p><code>logging-log4j1</code>, to use the <a href="https://logging.apache.org/log4j/1.2/">Log4J1</a> binding (note that Log4J 1.x is end-of-life)</p>
</li>
<li>
<p><code>logging-jul</code>, to use the <code>java.util.logging</code> binding</p>
</li>
<li>
<p><code>logging-noop</code>, to use the SLF4J no-operation binding (discards all logging)</p>
</li>
</ul>
</div>
<div class="sect5">
<h6 id="og-logging-server-custom-logback"><a class="anchor" href="#og-logging-server-custom-logback"></a><a class="link" href="#og-logging-server-custom-logback">Logging with LogBack</a></h6>
<div class="paragraph">
<p>You can enable, for example, the <code>logging-logback</code> Jetty module in this way (from the <code>$JETTY_BASE</code> directory):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=logging-logback,http</pre>
</div>
</div>
<div class="paragraph">
<p>Since LogBack is released under a license that is different from Jetty&#8217;s, you will be prompted to accept the LogBack license.
Once you accept the LogBack license, you will have the following directory structure:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$JETTY_BASE
├── lib
│ └── logging
│ ├── logback-classic-&lt;version&gt;.jar
│ └── logback-core-&lt;version&gt;.jar
├── resources
│ └── logback.xml
└── start.d
├── http.ini
└── logging-logback.ini</pre>
</div>
</div>
<div class="paragraph">
<p>As you can see, the Jetty module system downloaded the required LogBack <code>*.jar</code> files, and created a <code>$JETTY_BASE/resources/logback.xml</code> file that you can configure to customize your LogBack logging.
Please refer to the <a href="http://logback.qos.ch/manual/configuration.html">LogBack configuration manual</a> for more information about how to configure LogBack.</p>
</div>
</div>
<div class="sect5">
<h6 id="og-logging-server-custom-log4j2"><a class="anchor" href="#og-logging-server-custom-log4j2"></a><a class="link" href="#og-logging-server-custom-log4j2">Logging with Log4J2</a></h6>
<div class="paragraph">
<p>Similarly to <a href="#og-logging-server-custom-logback">logging with LogBack</a>, you can enable the <code>logging-log4j2</code> Jetty module in this way (from the <code>$JETTY_BASE</code> directory):</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=logging-log4j2,http</pre>
</div>
</div>
<div class="paragraph">
<p>After accepting the Log4J2 license, you will have the following directory structure:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$JETTY_BASE
├── lib
│ └── logging
│ ├── log4j-api-&lt;version&gt;.jar
│ ├── log4j-core-&lt;version&gt;.jar
│ └── log4j-slf4j18-impl-&lt;version&gt;.jar
├── resources
│ └── log4j2.xml
└── start.d
├── http.ini
└── logging-log4j2.ini</pre>
</div>
</div>
<div class="paragraph">
<p>The Jetty module system downloaded the required Log4J2 <code>*.jar</code> files, and created a <code>$JETTY_BASE/resources/log4j2.xml</code> file that you can configure to customize your Log4J2 logging.</p>
</div>
</div>
</div>
<div class="sect4">
<h5 id="og-logging-server-bridges"><a class="anchor" href="#og-logging-server-bridges"></a><a class="link" href="#og-logging-server-bridges">Bridging Logging to SLF4J</a></h5>
<div class="paragraph">
<p>When you use libraries that provide the features you need (for example, JDBC drivers), it may be possible that those libraries use a different logging framework than SLF4J.</p>
</div>
<div class="paragraph">
<p>SLF4J provides <a href="http://www.slf4j.org/legacy.html">bridges for legacy logging APIs</a> that allows you to bridge logging from one of these legacy logging frameworks to SLF4J.
Once the logging is bridged to SLF4J, you can use the <a href="#og-logging-server-default">default configuration</a> or the <a href="#og-logging-server-custom">custom configuration</a> so that your logging is centralized in one place only.</p>
</div>
<div class="paragraph">
<p>Jetty provides out-of-the-box modules that you can enable to bridge logging from other logging frameworks to SLF4J.</p>
</div>
<div class="sect5">
<h6 id="og-logging-server-bridge-jul"><a class="anchor" href="#og-logging-server-bridge-jul"></a><a class="link" href="#og-logging-server-bridge-jul">Bridging <code>java.util.logging</code></a></h6>
<div class="paragraph">
<p>For libraries that use <code>java.util.logging</code> as their logging framework you can enable the <code>logging-jul-capture</code> Jetty module.</p>
</div>
<div class="listingblock">
<div class="content">
<pre>$ java -jar $JETTY_HOME/start.jar --add-modules=logging-jul-capture</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>logging-jul-capture</code> Jetty module implies <code>--exec</code> and therefore spawns a second JVM (see <a href="#og-start-start">this section</a>) because it needs to provide the system property <code>java.util.logging.config.file</code> (so that <code>java.util.logging</code> can read the configuration from the specified file), and because it needs to make available on the System ClassLoader the class <code>org.slf4j.bridge.SLF4JBridgeHandler</code>.</p>
</div>
<div class="paragraph">
<p>For example, a library that uses <code>java.util.logging</code> as its logging library is the Postgresql JDBC driver.
With the <code>logging-jul-capture</code> Jetty module, the logging follows this diagram:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/diag-792f4cd700f2b5af8fedd7b0249d25b4.png" alt="Diagram" width="686" height="174">
</div>
</div>
<div class="paragraph">
<p>Note how Jetty logs directly to SLF4J, while the Postgresql JDBC driver logs to SLF4J through the <code>SLF4JBridgeHandler</code>.
They both arrive to the SLF4J binding, in this case the Jetty SLF4J binding (but could be any other SLF4J binding such as LogBack).</p>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-logging-request"><a class="anchor" href="#og-logging-request"></a><a class="link" href="#og-logging-request">Request Logging</a></h4>
<div class="paragraph">
<p>TODO</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="og-troubleshooting"><a class="anchor" href="#og-troubleshooting"></a><a class="link" href="#og-troubleshooting">Troubleshooting</a></h3>
<div class="paragraph">
<p>To troubleshoot Jetty when used as a production server, there are two main tools: the Jetty Server Dump and enabling DEBUG level logging.</p>
</div>
<div class="paragraph">
<p>Jetty is based on components organized as a tree, with the <code>Server</code> instance at the root of the tree.</p>
</div>
<div class="paragraph">
<p>As explained in the <a href="#og-jmx">JMX section</a>, these components can be exported as JMX MBeans and therefore be accessible from JMX Consoles such as Java Missions Control (JMC).</p>
</div>
<div class="paragraph">
<p>Being able to take a snapshot of the state of Jetty while it is running is the most useful information that can be attached when reporting an issue.
Such state includes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The thread pool configuration and its current state, including how many threads are in use, and their stack trace.</p>
</li>
<li>
<p>The TLS configuration.</p>
</li>
<li>
<p>The I/O configuration and its current state, including the ports Jetty listens to, how many connections are currently open, and he state of each connection, and the state of the request/response handling for each connection.</p>
</li>
<li>
<p>The <code>Handler</code> structure and its configuration.</p>
</li>
<li>
<p>The web applications deployed and their configurations, including the class loader information.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The prerequisite for troubleshooting is to enable JMX, so that Jetty&#8201;&#8212;&#8201;possibly a production server&#8201;&#8212;&#8201;can be accessed from a remote location to obtain the information exported via JMX, and possibly be able to reconfigure Jetty to solve the issue.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
Make sure you read about how to secure the access to Jetty when using <a href="#og-jmx-remote">remote JMX</a>.
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="og-troubleshooting-dump"><a class="anchor" href="#og-troubleshooting-dump"></a><a class="link" href="#og-troubleshooting-dump">Server Dump</a></h4>
<div class="paragraph">
<p>The Jetty Server Dump is obtained by invoking, via JMX, the <code>Server.dump()</code> operation, as shown below.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/jmc-server-dump.png" alt="jmc server dump">
</div>
</div>
<div class="paragraph">
<p>Find the <code>Server</code> MBean in the MBean Tree, under <code>org.eclipse.jetty.server:type=server,id=0</code>.
Then click on the "Operations" tab, select the <code>dump()</code> operation, and then click the <code>Execute</code> button.
In the bottom panel you will see the result of the invocation, that you can copy into a text editor and save to your file system.</p>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Taking a Jetty Server Dump is a relatively expensive operation, as it dumps the state of all connections (which can be thousands), and the state of all threads.</p>
</div>
<div class="paragraph">
<p>The result of the invocation may produce a large string, possibly few MiB, that may impact the server memory usage.</p>
</div>
<div class="paragraph">
<p>Furthermore, dumping the state of the I/O Jetty components takes a little CPU time off the handling of the actual I/O, possibly slowing it down temporarily.</p>
</div>
<div class="paragraph">
<p>While the slow-down caused by taking the Jetty Server Dump may be noticeable on highly loaded systems, it is typically a very small price to pay to obtain the information about the Jetty state that may be critical to the resolution of an issue.</p>
</div>
</td>
</tr>
</table>
</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 format of the Jetty Server Dump output is subject to change at any time, as Jetty developers modify the Jetty code and decide to include more state, or remove state that is no longer relevant.</p>
</div>
<div class="paragraph">
<p>The Jetty Server Dump is organized in a tree whose structure is similar to the runtime Jetty component tree.</p>
</div>
<div class="paragraph">
<p>At the end of the dump output there is a legend that explains the type of tree node: whether it is a node that represent a <em>managed</em> component, or an <em>array</em> node (or a <em>map</em> node) that represent some component state, etc.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="og-troubleshooting-dump-start-stop"><a class="anchor" href="#og-troubleshooting-dump-start-stop"></a><a class="link" href="#og-troubleshooting-dump-start-stop">Dump at Server Start/Stop</a></h5>
<div class="paragraph">
<p>The <code>Server.dump()</code> operation may also be invoked just after the <code>Server</code> starts (to log the state of the freshly started server), and just before the <code>Server</code> stops (which may be useful to log the state of server that is not working properly).</p>
</div>
<div class="paragraph">
<p>You can temporarily enable the Jetty Server Dump at start time by overriding the <code>jetty.server.dumpAfterStart</code> property on the command line:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>$ java -jar $JETTY_HOME/start.jar <strong>jetty.server.dumpAfterStart=true</strong></code></pre>
</div>
</div>
<div class="paragraph">
<p>To make this change persistent across server restarts, see the <a href="#og-module-server"><code>server</code> module</a> configuration for more information about how to configure the server to dump at start/stop time.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-troubleshooting-dump-detailed"><a class="anchor" href="#og-troubleshooting-dump-detailed"></a><a class="link" href="#og-troubleshooting-dump-detailed">Detailed ThreadPool Information</a></h5>
<div class="paragraph">
<p>By default, the dump of the thread pool will only dump the topmost stack frame of each thread.
It is possible to configure the thread pool to dump the whole stack trace for each thread; while this may be a little more expensive, it provides complete information about the state of each thread, which may be important to diagnose the issue.</p>
</div>
<div class="paragraph">
<p>See the <a href="#og-module-threadpool"><code>threadpool</code> module</a> configuration for more information about how to configure the thread pool to dump detailed thread information.</p>
</div>
<div class="paragraph">
<p>Detailed thread pool information can also be turned on/off on-the-fly via JMX, by finding the <code>ThreadPool</code> MBean under <code>org.eclipse.jetty.util.thread:type=queuedthreadpool,id=0</code>, then selecting the <code>detailedDump</code> attribute and setting it to <code>true</code>. You can now perform the <code>Server.dump()</code> operation as explained above, and then set <code>detailedDump</code> back to <code>false</code>.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-troubleshooting-dump-example"><a class="anchor" href="#og-troubleshooting-dump-example"></a><a class="link" href="#og-troubleshooting-dump-example">Dump Example</a></h5>
<div class="paragraph">
<p>Below you can find a simple example of a Jetty Server Dump, with annotations for the principal components:</p>
</div>
<div class="listingblock small">
<div class="content">
<pre class="CodeRay highlight nowrap"><code>Server@6295d394{STARTING}[10.0.7,sto=5000] - STARTING <i class="conum" data-value="1"></i><b>(1)</b>
+= QueuedThreadPool[qtp143110009]@887af79{STARTED,4&lt;=4&lt;=200,i=2,r=-1,q=0}[ReservedThreadExecutor@57c758ac{reserved=0/8,pending=0}] - STARTED <i class="conum" data-value="2"></i><b>(2)</b>
| +- org.eclipse.jetty.util.thread.ThreadPoolBudget@a9cd3b1
| += ReservedThreadExecutor@57c758ac{reserved=0/8,pending=0} - STARTED
| | +&gt; threads size=0
| +&gt; threads size=4
| +&gt; qtp143110009-18 TIMED_WAITING tid=18 prio=5 IDLE
| +&gt; qtp143110009-15 RUNNABLE tid=15 prio=5 SELECTING
| +&gt; qtp143110009-16 TIMED_WAITING tid=16 prio=5 IDLE
| +&gt; qtp143110009-17-acceptor-0@6a61babe-ServerConnector@1184ab05{HTTP/1.1, (http/1.1)}{0.0.0.0:8080} RUNNABLE tid=17 prio=3 ACCEPTING
+- org.eclipse.jetty.io.ArrayByteBufferPool@21de60b4
+= ScheduledExecutorScheduler@47db50c5{STARTED} - STARTED
+= HandlerList@c267ef4{STARTED} - STARTED <i class="conum" data-value="3"></i><b>(3)</b>
| += ContextHandlerCollection@30ee2816{STARTED} - STARTED
| += DefaultHandler@31d7b7bf{STARTED} - STARTED
+= ServerConnector@1184ab05{HTTP/1.1, (http/1.1)}{0.0.0.0:8080} - STARTED <i class="conum" data-value="4"></i><b>(4)</b>
| +~ QueuedThreadPool[qtp143110009]@887af79{STARTED,4&lt;=4&lt;=200,i=2,r=-1,q=0}[ReservedThreadExecutor@57c758ac{reserved=0/8,pending=0}] - STARTED
| +~ ScheduledExecutorScheduler@47db50c5{STARTED} - STARTED
| +- org.eclipse.jetty.io.ArrayByteBufferPool@21de60b4
| +- org.eclipse.jetty.io.ArrayRetainableByteBufferPool@635eaaf1{min=0,max=65536,buckets=64,heap=0/-1,direct=0/-1}
| | +&gt; direct size=64
| | | +&gt; Bucket@5c30a9b0[inUse=0,size=0,max=2147483647,closed=false]{capacity=1024,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@3f197a46[inUse=0,size=0,max=2147483647,closed=false]{capacity=2048,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@636be97c[inUse=0,size=0,max=2147483647,closed=false]{capacity=3072,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@50a638b5[inUse=0,size=0,max=2147483647,closed=false]{capacity=4096,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@1817d444[inUse=0,size=0,max=2147483647,closed=false]{capacity=5120,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@6ca8564a[inUse=0,size=0,max=2147483647,closed=false]{capacity=6144,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@50b472aa[inUse=0,size=0,max=2147483647,closed=false]{capacity=7168,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@31368b99[inUse=0,size=0,max=2147483647,closed=false]{capacity=8192,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@1725dc0f[inUse=0,size=0,max=2147483647,closed=false]{capacity=9216,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@3911c2a7[inUse=0,size=0,max=2147483647,closed=false]{capacity=10240,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@4ac3c60d[inUse=0,size=0,max=2147483647,closed=false]{capacity=11264,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@4facf68f[inUse=0,size=0,max=2147483647,closed=false]{capacity=12288,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@76508ed1[inUse=0,size=0,max=2147483647,closed=false]{capacity=13312,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@41e36e46[inUse=0,size=0,max=2147483647,closed=false]{capacity=14336,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@15c43bd9[inUse=0,size=0,max=2147483647,closed=false]{capacity=15360,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@3d74bf60[inUse=0,size=0,max=2147483647,closed=false]{capacity=16384,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@4f209819[inUse=0,size=0,max=2147483647,closed=false]{capacity=17408,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@15eb5ee5[inUse=0,size=0,max=2147483647,closed=false]{capacity=18432,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@2145b572[inUse=0,size=0,max=2147483647,closed=false]{capacity=19456,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@39529185[inUse=0,size=0,max=2147483647,closed=false]{capacity=20480,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@72f926e6[inUse=0,size=0,max=2147483647,closed=false]{capacity=21504,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@3daa422a[inUse=0,size=0,max=2147483647,closed=false]{capacity=22528,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@31c88ec8[inUse=0,size=0,max=2147483647,closed=false]{capacity=23552,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@1cbbffcd[inUse=0,size=0,max=2147483647,closed=false]{capacity=24576,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@27ce24aa[inUse=0,size=0,max=2147483647,closed=false]{capacity=25600,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@481a996b[inUse=0,size=0,max=2147483647,closed=false]{capacity=26624,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@3d51f06e[inUse=0,size=0,max=2147483647,closed=false]{capacity=27648,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@7ed7259e[inUse=0,size=0,max=2147483647,closed=false]{capacity=28672,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@28eaa59a[inUse=0,size=0,max=2147483647,closed=false]{capacity=29696,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@3427b02d[inUse=0,size=0,max=2147483647,closed=false]{capacity=30720,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@647e447[inUse=0,size=0,max=2147483647,closed=false]{capacity=31744,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@41fbdac4[inUse=0,size=0,max=2147483647,closed=false]{capacity=32768,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@3c407114[inUse=0,size=0,max=2147483647,closed=false]{capacity=33792,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@35ef1869[inUse=0,size=0,max=2147483647,closed=false]{capacity=34816,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@c33b74f[inUse=0,size=0,max=2147483647,closed=false]{capacity=35840,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@130161f7[inUse=0,size=0,max=2147483647,closed=false]{capacity=36864,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@2c767a52[inUse=0,size=0,max=2147483647,closed=false]{capacity=37888,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@619713e5[inUse=0,size=0,max=2147483647,closed=false]{capacity=38912,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@708f5957[inUse=0,size=0,max=2147483647,closed=false]{capacity=39936,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@68999068[inUse=0,size=0,max=2147483647,closed=false]{capacity=40960,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@7722c3c3[inUse=0,size=0,max=2147483647,closed=false]{capacity=41984,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@2ef3eef9[inUse=0,size=0,max=2147483647,closed=false]{capacity=43008,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@243c4f91[inUse=0,size=0,max=2147483647,closed=false]{capacity=44032,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@291ae[inUse=0,size=0,max=2147483647,closed=false]{capacity=45056,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@61df66b6[inUse=0,size=0,max=2147483647,closed=false]{capacity=46080,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@50eac852[inUse=0,size=0,max=2147483647,closed=false]{capacity=47104,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@16ec5519[inUse=0,size=0,max=2147483647,closed=false]{capacity=48128,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@2f7298b[inUse=0,size=0,max=2147483647,closed=false]{capacity=49152,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@188715b5[inUse=0,size=0,max=2147483647,closed=false]{capacity=50176,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@1ea9f6af[inUse=0,size=0,max=2147483647,closed=false]{capacity=51200,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@6a192cfe[inUse=0,size=0,max=2147483647,closed=false]{capacity=52224,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@5119fb47[inUse=0,size=0,max=2147483647,closed=false]{capacity=53248,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@7193666c[inUse=0,size=0,max=2147483647,closed=false]{capacity=54272,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@20deea7f[inUse=0,size=0,max=2147483647,closed=false]{capacity=55296,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@3835c46[inUse=0,size=0,max=2147483647,closed=false]{capacity=56320,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@1dde4cb2[inUse=0,size=0,max=2147483647,closed=false]{capacity=57344,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@7714e963[inUse=0,size=0,max=2147483647,closed=false]{capacity=58368,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@20ce78ec[inUse=0,size=0,max=2147483647,closed=false]{capacity=59392,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@393671df[inUse=0,size=0,max=2147483647,closed=false]{capacity=60416,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@56620197[inUse=0,size=0,max=2147483647,closed=false]{capacity=61440,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@6eda5c9[inUse=0,size=0,max=2147483647,closed=false]{capacity=62464,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@55b7a4e0[inUse=0,size=0,max=2147483647,closed=false]{capacity=63488,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@5f058f00[inUse=0,size=0,max=2147483647,closed=false]{capacity=64512,inuse=0(0%)}
| | | | +&gt; entries size=0
| | | +&gt; Bucket@192d43ce[inUse=0,size=0,max=2147483647,closed=false]{capacity=65536,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; indirect size=64
| | +&gt; Bucket@72057ecf[inUse=0,size=0,max=2147483647,closed=false]{capacity=1024,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@1afd44cb[inUse=0,size=0,max=2147483647,closed=false]{capacity=2048,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@6973b51b[inUse=0,size=0,max=2147483647,closed=false]{capacity=3072,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@1ab3a8c8[inUse=0,size=0,max=2147483647,closed=false]{capacity=4096,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@43195e57[inUse=0,size=0,max=2147483647,closed=false]{capacity=5120,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@333291e3[inUse=0,size=0,max=2147483647,closed=false]{capacity=6144,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@479d31f3[inUse=0,size=0,max=2147483647,closed=false]{capacity=7168,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@40ef3420[inUse=0,size=0,max=2147483647,closed=false]{capacity=8192,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@498d318c[inUse=0,size=0,max=2147483647,closed=false]{capacity=9216,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@6e171cd7[inUse=0,size=0,max=2147483647,closed=false]{capacity=10240,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@402bba4f[inUse=0,size=0,max=2147483647,closed=false]{capacity=11264,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@795cd85e[inUse=0,size=0,max=2147483647,closed=false]{capacity=12288,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@59fd97a8[inUse=0,size=0,max=2147483647,closed=false]{capacity=13312,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@f5ac9e4[inUse=0,size=0,max=2147483647,closed=false]{capacity=14336,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@123ef382[inUse=0,size=0,max=2147483647,closed=false]{capacity=15360,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@dbf57b3[inUse=0,size=0,max=2147483647,closed=false]{capacity=16384,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@384ad17b[inUse=0,size=0,max=2147483647,closed=false]{capacity=17408,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@61862a7f[inUse=0,size=0,max=2147483647,closed=false]{capacity=18432,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@441772e[inUse=0,size=0,max=2147483647,closed=false]{capacity=19456,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@7334aada[inUse=0,size=0,max=2147483647,closed=false]{capacity=20480,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@1d9b7cce[inUse=0,size=0,max=2147483647,closed=false]{capacity=21504,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@4d9e68d0[inUse=0,size=0,max=2147483647,closed=false]{capacity=22528,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@42e99e4a[inUse=0,size=0,max=2147483647,closed=false]{capacity=23552,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@14dd9eb7[inUse=0,size=0,max=2147483647,closed=false]{capacity=24576,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@52e6fdee[inUse=0,size=0,max=2147483647,closed=false]{capacity=25600,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@6c80d78a[inUse=0,size=0,max=2147483647,closed=false]{capacity=26624,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@62150f9e[inUse=0,size=0,max=2147483647,closed=false]{capacity=27648,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@1a451d4d[inUse=0,size=0,max=2147483647,closed=false]{capacity=28672,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@7fa98a66[inUse=0,size=0,max=2147483647,closed=false]{capacity=29696,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@15ff3e9e[inUse=0,size=0,max=2147483647,closed=false]{capacity=30720,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@5fdcaa40[inUse=0,size=0,max=2147483647,closed=false]{capacity=31744,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@6dc17b83[inUse=0,size=0,max=2147483647,closed=false]{capacity=32768,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@5e0826e7[inUse=0,size=0,max=2147483647,closed=false]{capacity=33792,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@32eff876[inUse=0,size=0,max=2147483647,closed=false]{capacity=34816,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@8dbdac1[inUse=0,size=0,max=2147483647,closed=false]{capacity=35840,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@6e20b53a[inUse=0,size=0,max=2147483647,closed=false]{capacity=36864,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@71809907[inUse=0,size=0,max=2147483647,closed=false]{capacity=37888,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@3ce1e309[inUse=0,size=0,max=2147483647,closed=false]{capacity=38912,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@6aba2b86[inUse=0,size=0,max=2147483647,closed=false]{capacity=39936,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@158da8e[inUse=0,size=0,max=2147483647,closed=false]{capacity=40960,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@74e52303[inUse=0,size=0,max=2147483647,closed=false]{capacity=41984,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@47af7f3d[inUse=0,size=0,max=2147483647,closed=false]{capacity=43008,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@7c729a55[inUse=0,size=0,max=2147483647,closed=false]{capacity=44032,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@3bb9a3ff[inUse=0,size=0,max=2147483647,closed=false]{capacity=45056,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@661972b0[inUse=0,size=0,max=2147483647,closed=false]{capacity=46080,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@5af3afd9[inUse=0,size=0,max=2147483647,closed=false]{capacity=47104,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@323b36e0[inUse=0,size=0,max=2147483647,closed=false]{capacity=48128,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@44ebcd03[inUse=0,size=0,max=2147483647,closed=false]{capacity=49152,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@694abbdc[inUse=0,size=0,max=2147483647,closed=false]{capacity=50176,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@2e005c4b[inUse=0,size=0,max=2147483647,closed=false]{capacity=51200,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@4567f35d[inUse=0,size=0,max=2147483647,closed=false]{capacity=52224,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@5ffead27[inUse=0,size=0,max=2147483647,closed=false]{capacity=53248,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@6356695f[inUse=0,size=0,max=2147483647,closed=false]{capacity=54272,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@4f18837a[inUse=0,size=0,max=2147483647,closed=false]{capacity=55296,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@359f7cdf[inUse=0,size=0,max=2147483647,closed=false]{capacity=56320,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@1fa268de[inUse=0,size=0,max=2147483647,closed=false]{capacity=57344,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@4f6ee6e4[inUse=0,size=0,max=2147483647,closed=false]{capacity=58368,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@4466af20[inUse=0,size=0,max=2147483647,closed=false]{capacity=59392,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@a514af7[inUse=0,size=0,max=2147483647,closed=false]{capacity=60416,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@6b927fb[inUse=0,size=0,max=2147483647,closed=false]{capacity=61440,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@3e58a80e[inUse=0,size=0,max=2147483647,closed=false]{capacity=62464,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@4fb61f4a[inUse=0,size=0,max=2147483647,closed=false]{capacity=63488,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@4fb0f2b9[inUse=0,size=0,max=2147483647,closed=false]{capacity=64512,inuse=0(0%)}
| | | +&gt; entries size=0
| | +&gt; Bucket@79924b[inUse=0,size=0,max=2147483647,closed=false]{capacity=65536,inuse=0(0%)}
| | +&gt; entries size=0
| +- org.eclipse.jetty.server.AbstractConnector$1@7b9a4292
| += HttpConnectionFactory@62e136d3[HTTP/1.1] - STARTED
| | +- HttpConfiguration@9f116cc{32768/8192,8192/8192,https://:0,[]}
| | +&gt; customizers size=0
| | +&gt; formEncodedMethods size=2
| | | +&gt; POST
| | | +&gt; PUT
| | +&gt; outputBufferSize=32768
| | +&gt; outputAggregationSize=8192
| | +&gt; requestHeaderSize=8192
| | +&gt; responseHeaderSize=8192
| | +&gt; headerCacheSize=1024
| | +&gt; secureScheme=https
| | +&gt; securePort=0
| | +&gt; idleTimeout=-1
| | +&gt; sendDateHeader=false
| | +&gt; sendServerVersion=true
| | +&gt; sendXPoweredBy=false
| | +&gt; delayDispatchUntilContent=true
| | +&gt; persistentConnectionsEnabled=true
| | +&gt; maxErrorDispatches=10
| | +&gt; minRequestDataRate=0
| | +&gt; minResponseDataRate=0
| | +&gt; requestCookieCompliance=org.eclipse.jetty.http.CookieCompliance@67d48005
| | +&gt; responseCookieCompliance=org.eclipse.jetty.http.CookieCompliance@67d48005
| | +&gt; notifyRemoteAsyncErrors=true
| | +&gt; relativeRedirectAllowed=false
| += SelectorManager@ServerConnector@1184ab05{HTTP/1.1, (http/1.1)}{0.0.0.0:8080} - STARTED
| | += ManagedSelector@5876a9af{STARTED} id=0 keys=0 selected=0 updates=0 - STARTED <i class="conum" data-value="5"></i><b>(5)</b>
| | += AdaptiveExecutionStrategy@7ec7ffd3/SelectorProducer@5b239d7d/PRODUCING/p=false/QueuedThreadPool[qtp143110009]@887af79{STARTED,4&lt;=4&lt;=200,i=2,r=-1,q=0}[ReservedThreadExecutor@57c758ac{reserved=0/8,pending=0}][pc=0,pic=0,pec=0,epc=0]@2021-10-06T14:48:38.047619-05:00 - STARTED
| | | +- SelectorProducer@5b239d7d
| | | +~ QueuedThreadPool[qtp143110009]@887af79{STARTED,4&lt;=4&lt;=200,i=2,r=-1,q=0}[ReservedThreadExecutor@57c758ac{reserved=0/8,pending=0}] - STARTED
| | +&gt; updates @ 2021-10-06T14:48:38.044713-05:00 size=0
| | +&gt; keys @ 2021-10-06T14:48:38.04669-05:00 size=0 <i class="conum" data-value="6"></i><b>(6)</b>
| +- sun.nio.ch.ServerSocketChannelImpl[/[0:0:0:0:0:0:0:0]:8080]
| +- qtp143110009-17-acceptor-0@6a61babe-ServerConnector@1184ab05{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
+- org.eclipse.jetty.util.component.HaltLifeCycleListener@6572421
+= ErrorHandler@6b81ce95{STARTED} - STARTED
+&gt; startJarLoader@28ba21f3 <i class="conum" data-value="7"></i><b>(7)</b>
+&gt; URLs size=9
| +&gt; file:/path/to/jetty.base/resources/
| +&gt; file:/path/to/jetty.home/lib/logging/slf4j-api-2.0.0-alpha5.jar
| +&gt; file:/path/to/jetty.home/lib/logging/jetty-slf4j-impl-10.0.7.jar
| +&gt; file:/path/to/jetty.home/lib/jetty-servlet-api-4.0.6.jar
| +&gt; file:/path/to/jetty.home/lib/jetty-http-10.0.7.jar
| +&gt; file:/path/to/jetty.home/lib/jetty-server-10.0.7.jar
| +&gt; file:/path/to/jetty.home/lib/jetty-xml-10.0.7.jar
| +&gt; file:/path/to/jetty.home/lib/jetty-util-10.0.7.jar
| +&gt; file:/path/to/jetty.home/lib/jetty-io-10.0.7.jar
+&gt; jdk.internal.loader.ClassLoaders$AppClassLoader@42110406
+&gt; packages size=4
| +&gt; package org.eclipse.jetty.start.config
| +&gt; package org.eclipse.jetty.start.builders
| +&gt; package org.eclipse.jetty.start.shaded.util
| +&gt; package org.eclipse.jetty.start
+&gt; jdk.internal.loader.ClassLoaders$PlatformClassLoader@3f5f02d7
+&gt; packages size=2
+&gt; package sun.util.resources.provider
+&gt; package sun.util.resources.cldr.provider
key: +- bean, += managed, +~ unmanaged, +? auto, +: iterable, +] array, +@ map, +&gt; undefined <i class="conum" data-value="8"></i><b>(8)</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>Server</code> instance at the root of the tree</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>The thread pool component</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>The root of the <code>Handler</code> structure</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>The connector listening on port <code>8080</code> for the HTTP/1.1 protocol</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>A selector component that manages connections</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>The connections currently managed by the selector component</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>The server <code>ClassLoader</code> and its classpath</td>
</tr>
<tr>
<td><i class="conum" data-value="8"></i><b>8</b></td>
<td>The legend for the dump nodes</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="og-troubleshooting-logging"><a class="anchor" href="#og-troubleshooting-logging"></a><a class="link" href="#og-troubleshooting-logging">Enabling DEBUG Logging</a></h4>
<div class="paragraph">
<p>Enabling DEBUG level logging for the <code>org.eclipse.jetty</code> logger name provides the maximum amount of information to troubleshoot Jetty issues.</p>
</div>
<div class="paragraph">
<p>Refer to the <a href="#og-logging">logging section</a> for more information about how to configure logging in Jetty.</p>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Enabling DEBUG level logging for <code>org.eclipse.jetty</code> is very, <strong>very</strong> expensive.</p>
</div>
<div class="paragraph">
<p>Your server could be slowed down to almost a halt, especially if it is under heavy load.
Furthermore, the log file could quickly fill up the entire filesystem (unless configured to roll over), so you want to be really careful using DEBUG logging.</p>
</div>
<div class="paragraph">
<p>For production servers, consider using the <a href="#og-troubleshooting-dump">Jetty Server Dump</a> first, and enable DEBUG logging only as a last resort.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>However, sometimes issues are such that only DEBUG logging can really tell what&#8217;s going on in the system, and enabling DEBUG logging is your best chance to figure the issue out.
Below you can find few suggestions that can help you reduce the impact when you have to enable DEBUG logging.</p>
</div>
<div class="sect4">
<h5 id="og-troubleshooting-logging-backend"><a class="anchor" href="#og-troubleshooting-logging-backend"></a><a class="link" href="#og-troubleshooting-logging-backend">Jetty Behind a Load Balancer</a></h5>
<div class="paragraph">
<p>If Jetty instances are behind a load balancer, you may configure the load balancer to send less load to a particular Jetty instance, and enable DEBUG logging in that instance only.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-troubleshooting-logging-jmx"><a class="anchor" href="#og-troubleshooting-logging-jmx"></a><a class="link" href="#og-troubleshooting-logging-jmx">Enabling DEBUG Logging for a Short Time</a></h5>
<div class="paragraph">
<p>In certain cases the issue can be reproduced reliably, but only in the production environment.</p>
</div>
<div class="paragraph">
<p>You can use JMX to temporarily enable DEBUG logging, reproduce the issue, and then disable DEBUG logging.</p>
</div>
<div class="paragraph">
<p>Alternatively, if you cannot reliably reproduce the issue, but you <em>know</em> it is happening, you can temporarily enable DEBUG logging for a small period of time, let&#8217;s say 10-60 seconds, and then disable DEBUG logging.</p>
</div>
<div class="paragraph">
<p>Changing the log level at runtime is a feature of the logging implementation that you are using.</p>
</div>
<div class="paragraph">
<p>The Jetty SLF4J implementation, used by default, exposes via JMX method <code>boolean JettyLoggerFactoryMBean.setLoggerLevel(String loggerName, String levelName)</code> that you can invoke via a JMX console to change the level for the specified logger name.
The method returns <code>true</code> if the logger level was successfully changed.</p>
</div>
<div class="paragraph">
<p>For example, you can pass the string <code>org.eclipse.jetty</code> as the first parameter, and the string <code>DEBUG</code> (upper case) as the second parameter.
You can then use the string <code>INFO</code> or <code>WARN</code> (upper case) to restore the logging level to its previous value.</p>
</div>
</div>
<div class="sect4">
<h5 id="og-troubleshooting-logging-subpackages"><a class="anchor" href="#og-troubleshooting-logging-subpackages"></a><a class="link" href="#og-troubleshooting-logging-subpackages">Enabling DEBUG Logging for SubPackages</a></h5>
<div class="paragraph">
<p>Enabling DEBUG logging for the <code>org.eclipse.jetty</code> logger name implies that all children logger names, recursively, inherit the DEBUG level.</p>
</div>
<div class="paragraph">
<p>Processing a single HTTP request involves many Jetty components: the I/O subsystem (under <code>org.eclipse.jetty.io</code>), the thread pool (under <code>org.eclipse.jetty.util</code>), the HTTP/1.1 parsing (under <code>org.eclipse.jetty.http</code>), etc.</p>
</div>
<div class="paragraph">
<p>If you can cut the amount of DEBUG logging to just what you need to troubleshoot the issue, the impact of enabling DEBUG logging will be much less than enabling it for all Jetty components.</p>
</div>
<div class="paragraph">
<p>For example, if you need to troubleshoot a client that sends bad HTTP/1.1 requests, it may be enough to enable only the <code>org.eclipse.jetty.http</code> logger name, therefore saving the large amount of DEBUG logging produced by the I/O subsystem and by the thread pool.</p>
</div>
<div class="paragraph">
<p>In another case, you may need to troubleshoot only HTTP/2 requests, and therefore enabling only the <code>org.eclipse.jetty.http2</code> logger name could be enough.</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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Get</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">stderr</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.System</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">err</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">println</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">arg</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">HELLO</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>
<span class="tag">&lt;/Get&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Get&gt;</span>
<span class="tag">&lt;Id&gt;</span>stderr<span class="tag">&lt;/Id&gt;</span>
<span class="tag">&lt;Name&gt;</span>err<span class="tag">&lt;/Name&gt;</span>
<span class="tag">&lt;Class&gt;</span>java.lang.System<span class="tag">&lt;/Class&gt;</span>
<span class="tag">&lt;Call&gt;</span>
<span class="tag">&lt;Name&gt;</span>println<span class="tag">&lt;/Name&gt;</span>
<span class="tag">&lt;Arg&gt;</span>HELLO<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Get&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">mystring</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.String</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span></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="CodeRay highlight"><code data-lang="java"><span class="type">var</span> mystring = <span class="keyword">new</span> <span class="predefined-type">String</span>();</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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.Server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">int</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>8080<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.Server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">port</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">int</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>8080<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">mylist</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.util.ArrayList</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">int</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>16<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="java"><span class="type">var</span> mylist = <span class="keyword">new</span> <span class="predefined-type">ArrayList</span>(<span class="integer">16</span>);</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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.util.ArrayList</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">listIterator</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">int</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>0<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">next</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="java"><span class="keyword">new</span> <span class="predefined-type">ArrayList</span>().listIterator(<span class="integer">0</span>).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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">myhost</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">getByName</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.net.InetAddress</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>jdk.java.net<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="java"><span class="type">var</span> myhost = <span class="predefined-type">InetAddress</span>.getByName(<span class="string"><span class="delimiter">&quot;</span><span class="content">jdk.java.net</span><span class="delimiter">&quot;</span></span>);</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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">server</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.Server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- Invokes getter method server.getVersion() --&gt;</span>
<span class="tag">&lt;Get</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">version</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">version</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>
<span class="comment">&lt;!-- Gets the System.err field --&gt;</span>
<span class="tag">&lt;Get</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.System</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">err</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">println</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>Jetty<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Get&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">server</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.Server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- The value in the &lt;Set&gt; scope is the string &quot;true&quot; --&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">dryRun</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>true<span class="tag">&lt;/Set&gt;</span>
<span class="comment">&lt;!-- The value in the &lt;Set&gt; scope is the instance created by &lt;New&gt; --&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">requestLog</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.CustomRequestLog</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Map</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.util.concurrent.ConcurrentHashMap</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Entry&gt;</span>
<span class="tag">&lt;Item&gt;</span>host<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.net.InetAddress</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">getByName</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>localhost<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Entry&gt;</span>
<span class="tag">&lt;/Map&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.util.Properties</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Put</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">host</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.net.InetAddress</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">getByName</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>localhost<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Put&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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, or by a <code>Type</code> child element.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure&gt;</span>
<span class="tag">&lt;Array</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.Object</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Item</span> <span class="tag">/&gt;</span> <span class="comment">&lt;!-- null --&gt;</span>
<span class="tag">&lt;Item&gt;</span>literalString<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">String</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span><span class="tag">&lt;/Item&gt;</span> <span class="comment">&lt;!-- empty string --&gt;</span>
<span class="tag">&lt;Item</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Double</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>1.0D<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;Item&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.Exception</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>
<span class="tag">&lt;/Item&gt;</span>
<span class="tag">&lt;/Array&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="comment">&lt;!-- The Jetty Server has id=&quot;server&quot; --&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">server</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.Server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Get</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.System</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">err</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- Here the System.err field is in scope, but you
want to operate on the server to get its version --&gt;</span>
<span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- Store the server version under id=&quot;myversion&quot; --&gt;</span>
<span class="tag">&lt;Get</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">myversion</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">version</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>
<span class="tag">&lt;/Ref&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">println</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- Reference the server version stored above --&gt;</span>
<span class="tag">&lt;Arg&gt;</span>Server version is: <span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">myversion</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Get&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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">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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;<a href="https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt" class="bare">https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt</a>;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.webapp.WebAppContext</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">contextPath</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<mark><span class="tag">&lt;Property</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">com.myapps.mywiki.context.path</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">default</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">/wiki</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span></mark>
<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">war</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>/opt/myapps/mywiki.war<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">server</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.Server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">int</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;SystemProperty</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">com.acme.http.port</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">default</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">8080</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">server</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.Server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">int</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Env</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">COM_ACME_HTTP_PORT</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">default</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">8080</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>
<span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></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="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="doctype">&lt;!DOCTYPE Configure PUBLIC &quot;-//Jetty//Configure//EN&quot; &quot;https://www.eclipse.org/jetty/configure_10_0.dtd&quot;&gt;</span>
<span class="tag">&lt;Configure</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">server</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.Server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg</span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">int</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>8080<span class="tag">&lt;/Arg&gt;</span>
<span class="comment">&lt;!-- Here the Server object has been created and is in scope --&gt;</span>
<span class="comment">&lt;!-- Calls the setter on the Server object that is in scope --&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">stopTimeout</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>5000<span class="tag">&lt;/Set&gt;</span>
<span class="comment">&lt;!-- Creates a new object --&gt;</span>
<span class="tag">&lt;New</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">httpConfig</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">org.eclipse.jetty.server.HttpConfiguration</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- Here the HttpConfiguration just created is in a nested scope --&gt;</span>
<span class="comment">&lt;!-- Calls the setter on the HttpConfiguration object that is in scope --&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">secureScheme</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>https<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/New&gt;</span>
<span class="comment">&lt;!-- Calls the getter on the Server object that is in scope --&gt;</span>
<span class="tag">&lt;Get</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">ThreadPool</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- Here the ThreadPool object returned by the getter is in a nested scope --&gt;</span>
<span class="comment">&lt;!-- Calls the setter on the ThreadPool object that is in scope --&gt;</span>
<span class="tag">&lt;Set</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">maxThreads</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">type</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">int</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>256<span class="tag">&lt;/Set&gt;</span>
<span class="tag">&lt;/Get&gt;</span>
<span class="comment">&lt;!-- Gets the System.err field --&gt;</span>
<span class="tag">&lt;Get</span> <span class="attribute-name">class</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">java.lang.System</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">err</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- Here the System.err object is in scope --&gt;</span>
<span class="comment">&lt;!-- Equivalent to: var myversion = server.getVersion() --&gt;</span>
<span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="comment">&lt;!-- Here the &quot;server&quot; object is in scope --&gt;</span>
<span class="tag">&lt;Get</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">myversion</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">version</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>
<span class="tag">&lt;/Ref&gt;</span>
<span class="comment">&lt;!-- Calls println() on the System.err object --&gt;</span>
<span class="tag">&lt;Call</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">println</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
<span class="tag">&lt;Arg&gt;</span>Server version is: <span class="tag">&lt;Ref</span> <span class="attribute-name">refid</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">myversion</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span><span class="tag">&lt;/Arg&gt;</span>
<span class="tag">&lt;/Call&gt;</span>
<span class="tag">&lt;/Get&gt;</span>
<span class="tag">&lt;/Configure&gt;</span></code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Version 10.0.7<br>
Last updated 2021-10-06 12:51:45 -0500
</div>
</div>
</body>
</html>