| <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="generator" content="Asciidoctor 1.5.7.1"><title>Eclipse Jetty: Embedded Guide</title><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><!--Google Tag Manager--><script>(function(w,d,s,l,i){ |
| w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'}); |
| var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:''; |
| j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl; |
| f.parentNode.insertBefore(j,f); |
| })(window,document,'script','dataLayer','GTM-5WLCZXC');</script><!--End Google Tag Manager--><link rel="shortcut icon" href="images/favicon.ico"><link rel="stylesheet" href="https://www.eclipse.org/eclipse.org-common/themes/solstice/public/stylesheets/quicksilver.min.css?v1.3"><meta name="description" content="The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 350 open source projects, including runtimes, tools and frameworks."><meta property="og:description" content="The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 350 open source projects, including runtimes, tools and frameworks."><meta property="og:image" content="https://www.eclipse.org/eclipse.org-common/themes/solstice/public/images/logo/eclipse-foundation-200x200.png"><meta property="og:title" content="Eclipse Jetty"><meta property="og:image:width" content="200"><meta property="og:image:height" content="200"><meta itemprop="name" content="Eclipse Jetty"><meta itemprop="description" content="The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 350 open source projects, including runtimes, tools and frameworks."><meta itemprop="image" content="https://www.eclipse.org/eclipse.org-common/themes/solstice/public/images/logo/eclipse-foundation-400x400.png"><meta name="twitter:site" content="@EclipseFdn"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="Eclipse Jetty"><meta name="twitter:url" content="https://www.eclipse.org/eclipse.org-common/themes/solstice/html_template/index.php?theme=default&layout=thin"><meta name="twitter:description" content="The Eclipse Foundation - home to a global community, the Eclipse IDE, Jakarta EE and over 350 open source projects, including runtimes, tools and frameworks."><meta name="twitter:image" content="https://www.eclipse.org/eclipse.org-common/themes/solstice/public/images/logo/eclipse-foundation-400x400.png"><link href="https://fonts.googleapis.com/css?family=Libre+Franklin:400,700,300,600,100" rel="stylesheet" type="text/css"><script>var eclipse_org_common = {"settings":{"cookies_class":{"name":"eclipse_settings","enabled":1}}}</script><link rel="stylesheet" href="../common/css/jetty.css"> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"></head><body id="body_solstice"><!--Google Tag Manager (noscript)--><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5WLCZXC" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript><!--End Google Tag Manager (noscript)--><a class="sr-only" href="#content">Skip to main content</a><header class="header-wrapper" id="header-wrapper"><div class="clearfix toolbar-container-wrapper"><div class="container"><div class="text-right toolbar-row row hidden-print"><div class="col-md-24 row-toolbar-col"></div></div></div></div><div class="container"><div class="row" id="header-row"><div class="col-sm-5 col-md-4" id="header-left"><div class="wrapper-logo-default"><a href="https://www.eclipse.org/"><img class="logo-eclipse-default hidden-xs" alt="logo" width="160" src="https://www.eclipse.org/eclipse.org-common/themes/solstice/public/images/logo/eclipse-foundation-white-orange.svg"></a></div></div></div></div></header><section class="default-breadcrumbs hidden-print breadcrumbs-default-margin" id="breadcrumb-thin"><div class="container"><h3 class="sr-only">Breadcrumbs</h3><div class="row"><div class="col-sm-24"><ol class="breadcrumb"><li><a href="../index.html ">Home</a></li><li><a href="./index.html"> Embedded Guide</a></li></ol></div></div></div></section><main id="main-wrapper"><div id="toc" class="toc2"><div id="toctitle">Embedded Guide</div><ul class="sectlevel1"><li><!--client--><a href="#client">Jetty Client Libraries</a><ul class="sectlevel2"><li><!--client-concepts--><a href="#client-concepts">Client Libraries Concepts</a></li></ul></li><li><!--server--><a href="#server">Jetty Server Libraries</a></li><li><!--advanced-embedding--><a href="#advanced-embedding">Embedding</a><ul class="sectlevel2"><li><!--jetty-helloworld--><a href="#jetty-helloworld">Jetty Embedded HelloWorld</a></li><li><!--embedding-jetty--><a href="#embedding-jetty">Embedding Jetty</a></li><li><!--embedded-examples--><a href="#embedded-examples">Embedded Examples</a></li></ul></li><li><!--maven-and-jetty--><a href="#maven-and-jetty">Maven and Jetty</a><ul class="sectlevel2"><li><!--jetty-maven-helloworld--><a href="#jetty-maven-helloworld">Using Maven</a></li><li><!--jetty-maven-plugin--><a href="#jetty-maven-plugin">Configuring the Jetty Maven Plugin</a></li><li><!--jetty-maven-scanning--><a href="#jetty-maven-scanning">Files Scanned by the Jetty Maven Plugin</a></li><li><!--jetty-jspc-maven-plugin--><a href="#jetty-jspc-maven-plugin">Jetty Jspc Maven Plugin</a></li></ul></li><li><!--http-client--><a href="#http-client">HTTP Client</a><ul class="sectlevel2"><li><!--http-client-intro--><a href="#http-client-intro">Introduction</a></li><li><!--http-client-api--><a href="#http-client-api">API Usage</a></li><li><!--http-client-cookie--><a href="#http-client-cookie">Cookies Support</a></li><li><!--http-client-authentication--><a href="#http-client-authentication">Authentication Support</a></li><li><!--http-client-proxy--><a href="#http-client-proxy">Proxy Support</a></li><li><!--http-client-transport--><a href="#http-client-transport">Pluggable Transports</a></li></ul></li><li><!--jetty-handlers--><a href="#jetty-handlers">Handlers</a><ul class="sectlevel2"><li><!--writing-custom-handlers--><a href="#writing-custom-handlers">Writing Custom Handlers</a></li></ul></li><li><!--websocket-intro--><a href="#websocket-intro">WebSocket Introduction</a><ul class="sectlevel2"><li><!--ws-intro-provides--><a href="#ws-intro-provides">What Jetty provides</a></li><li><!--ws-intro-api--><a href="#ws-intro-api">WebSocket APIs</a></li><li><!----><a href="#">Enabling WebSocket</a></li></ul></li><li><!--websocket-jetty--><a href="#websocket-jetty">Jetty Websocket API</a></li><li><!--ant-and-jetty--><a href="#ant-and-jetty">Ant and Jetty</a><ul class="sectlevel2"><li><!--jetty-ant--><a href="#jetty-ant">Ant Jetty Plugin</a></li></ul></li><li><!--frameworks--><a href="#frameworks">Frameworks</a><ul class="sectlevel2"><li><!--framework-jetty-spring--><a href="#framework-jetty-spring">Spring Setup</a></li><li><!--framework-jetty-osgi--><a href="#framework-jetty-osgi">OSGI</a></li><li><!--framework-weld--><a href="#framework-weld">Weld</a></li><li><!--framework-metro--><a href="#framework-metro">Metro</a></li></ul></li><li><!--architecture--><a href="#architecture">Architecture</a><ul class="sectlevel2"><li><!--basic-architecture--><a href="#basic-architecture">Jetty Architecture</a></li><li><!--jetty-classloading--><a href="#jetty-classloading">Jetty Classloading</a></li><li><!--jetty-1xx-responses--><a href="#jetty-1xx-responses">Managing 1xx Responses</a></li><li><!--creating-custom-protocol--><a href="#creating-custom-protocol">Creating a Custom Protocol</a></li></ul></li><li><!--platforms--><a href="#platforms">Platforms, Stacks and Alternative Distributions</a><ul class="sectlevel2"><li><!----><a href="#">Many many options…​</a></li><li><!--jelastic--><a href="#jelastic">Jelastic</a></li><li><!--cloudfoundry--><a href="#cloudfoundry">CloudFoundry</a></li><li><!--elastic-beanstalk--><a href="#elastic-beanstalk">Amazon Elastic Beanstalk</a></li><li><!--fedora--><a href="#fedora">Fedora</a></li><li><!--ubuntu--><a href="#ubuntu">Ubuntu</a></li></ul></li><li><!--reference-section--><a href="#reference-section">Jetty XML Reference</a><ul class="sectlevel2"><li><!--jetty-xml-syntax--><a href="#jetty-xml-syntax">Jetty XML Syntax</a></li><li><!--jetty-xml-usage--><a href="#jetty-xml-usage">Jetty XML Usage</a></li><li><!--jetty-xml-config--><a href="#jetty-xml-config">jetty.xml</a></li><li><!--jetty-web-xml-config--><a href="#jetty-web-xml-config">jetty-web.xml</a></li><li><!--jetty-env-xml--><a href="#jetty-env-xml">jetty-env.xml</a></li><li><!--webdefault-xml--><a href="#webdefault-xml">webdefault.xml</a></li><li><!--override-web-xml--><a href="#override-web-xml">Jetty override-web.xml</a></li></ul></li><li><!--troubleshooting--><a href="#troubleshooting">Troubleshooting</a><ul class="sectlevel2"><li><!--troubleshooting-zip-exceptions--><a href="#troubleshooting-zip-exceptions">Troubleshooting Zip Exceptions</a></li><li><!--troubleshooting-locked-files-on-windows--><a href="#troubleshooting-locked-files-on-windows">Troubleshooting Locked Files on Windows</a></li><li><!--preventing-memory-leaks--><a href="#preventing-memory-leaks">Preventing Memory Leaks</a></li><li><!--troubleshooting-slow-deployment--><a href="#troubleshooting-slow-deployment">Troubleshooting Slow Deployment</a></li><li><!--security-reports--><a href="#security-reports">Jetty Security Reports</a></li><li><!--watchservice--><a href="#watchservice">Java WatchService</a></li></ul></li><li><!--advanced-debugging--><a href="#advanced-debugging">Debugging</a><ul class="sectlevel2"><li><!----><a href="#">Options</a></li><li><!--enable-remote-debugging--><a href="#enable-remote-debugging">Enable remote debugging</a></li><li><!--debugging-with-intellij--><a href="#debugging-with-intellij">Debugging With IntelliJ</a></li><li><!--debugging-with-eclipse--><a href="#debugging-with-eclipse">Debugging With Eclipse</a></li></ul></li><li><!--io-arch--><a href="#io-arch">Appendix A: Jetty I/O Architecture</a><ul class="sectlevel2"><li><!--io-arch-selector-manager--><a href="#io-arch-selector-manager">Jetty I/O: <code>SelectorManager</code></a></li><li><!--io-arch-endpoint-connection--><a href="#io-arch-endpoint-connection">Jetty I/O: <code>EndPoint</code> and <code>Connection</code></a></li><li><!--io-arch-endpoint--><a href="#io-arch-endpoint">Jetty I/O: <code>EndPoint</code></a></li><li><!--io-arch-connection--><a href="#io-arch-connection">Jetty I/O: Implementing <code>Connection</code></a></li></ul></li></ul></div><div id="content-container"><div id="header"><h1>Eclipse Jetty: Embedded Guide</h1><div class="details"><span class="author" id="author">Jetty Developers</span><br><span class="email" id="email"><a href="mailto:jetty-dev@eclipse.org">jetty-dev@eclipse.org</a></span><br><span id="revnumber">version 1.0,</span> <span id="revdate">2020-03-18 17:03</span></div></div><div id="content"><div class="sect1"> |
| <h2 id="client">Jetty Client Libraries</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>The Eclipse Jetty Project provides not only server-side libraries so that you |
| can embed a server in your code, but it also provides client-side libraries |
| that allow you to embed a client - for example a HTTP client invoking a third |
| party HTTP service - in your application.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The client libraries are designed to be non-blocking and offer both synchronous |
| and asynchronous APIs and come with a large number of configuration options.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There are primarily two client libraries:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#client-http">The HTTP client library</a></p> |
| </li> |
| <li> |
| <p><a href="#client-websocket">The WebSocket client library</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect2"> |
| <h3 id="client-concepts">Client Libraries Concepts</h3> |
| <div class="paragraph"> |
| <p>The Jetty client libraries implement a network client speaking different protocols |
| such as HTTP/1.1, HTTP/2, WebSocket and FastCGI.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is possible to implement your own custom protocol on top of the Jetty client |
| libraries.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| TODO: perhaps add a section about this. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>There are conceptually three layers that compose the Jetty client libraries, from |
| more abstract to more concrete:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>The API layer, that exposes semantic APIs to applications so that they can write |
| code such as "GET me the resource at this URI"</p> |
| </li> |
| <li> |
| <p>The protocol layer, where the API request is converted into the appropriate |
| protocol bytes, for example encrypted HTTP/2</p> |
| </li> |
| <li> |
| <p>The infrastructure layer, that handles the low level I/O and deals with network, |
| buffer, threads, etc.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>Let’s look at these layers starting from the more concrete (and low level) one |
| and build up to the more abstract layer.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="client-concepts-infrastructure">Client Libraries Infrastructure Layer</h4> |
| <div class="paragraph"> |
| <p>The Jetty client libraries use the common I/O design described in |
| <a href="#io-arch">this section</a>. |
| The main client-side component is the |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/ClientConnector.html"><code>ClientConnector</code></a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>ClientConnector</code> primarily wraps the |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/SelectorManager.html"><code>SelectorManager</code></a> |
| and aggregates other four components: the thread pool (in form of an <code>Executor</code>), |
| the <code>Scheduler</code>, the <code>ByteBufferPool</code> and the <code>SslContextFactory.Client</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>ClientConnector</code> is where you want to set those components after you |
| have configured them. |
| If you don’t explicitly set those components on the <code>ClientConnector</code>, then |
| appropriate defaults will be chosen when the <code>ClientConnector</code> starts.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The simplest example that creates and starts a <code>ClientConnector</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ClientConnector clientConnector = new ClientConnector(); |
| clientConnector.start();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A more typical example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// Create and configure the SslContextFactory. |
| SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); |
| sslContextFactory.addExcludeProtocols("TLSv1", "TLSv1.1"); |
| |
| // Create and configure the thread pool. |
| QueuedThreadPool threadPool = new QueuedThreadPool(); |
| threadPool.setName("client"); |
| |
| // Create and configure the ClientConnector. |
| ClientConnector clientConnector = new ClientConnector(); |
| clientConnector.setSslContextFactory(sslContextFactory); |
| clientConnector.setExecutor(threadPool); |
| clientConnector.start();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A more advanced example that customizes the <code>ClientConnector</code> by overriding |
| factory methods:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">class CustomClientConnector extends ClientConnector |
| { |
| @Override |
| protected SelectorManager newSelectorManager() |
| { |
| return new ClientSelectorManager(getExecutor(), getScheduler(), getSelectors()) |
| { |
| @Override |
| protected void endPointOpened(EndPoint endpoint) |
| { |
| System.getLogger("endpoint").log(INFO, "opened %s", endpoint); |
| } |
| |
| @Override |
| protected void endPointClosed(EndPoint endpoint) |
| { |
| System.getLogger("endpoint").log(INFO, "closed %s", endpoint); |
| } |
| }; |
| } |
| } |
| |
| // Create and configure the thread pool. |
| QueuedThreadPool threadPool = new QueuedThreadPool(); |
| threadPool.setName("client"); |
| |
| // Create and configure the scheduler. |
| Scheduler scheduler = new ScheduledExecutorScheduler("scheduler-client", false); |
| |
| // Create and configure the custom ClientConnector. |
| CustomClientConnector clientConnector = new CustomClientConnector(); |
| clientConnector.setExecutor(threadPool); |
| clientConnector.setScheduler(scheduler); |
| clientConnector.start();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Since <code>ClientConnector</code> is the component that handles the low-level network, it |
| is also the component where you want to configure the parameters that control |
| how it should handle the low-level network.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The most common parameters are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>ClientConnector.selectors</code>: the number of <code>java.nio.Selector</code>s components |
| (defaults to <code>1</code>) that are present to handle the <code>SocketChannel</code>s opened by |
| the <code>ClientConnector</code>. You typically want to increase the number of selectors |
| only for those use cases where each selector should handle more than few hundreds |
| <em>concurrent</em> socket events. |
| For example, one selector typically runs well for <code>250</code> <em>concurrent</em> socket |
| events; as a rule of thumb, you can multiply that number by <code>10</code> to obtain the |
| number of opened sockets a selector can handle (<code>2500</code>), based on the assumption |
| that not all the <code>2500</code> sockets will be active <em>at the same time</em>.</p> |
| </li> |
| <li> |
| <p><code>ClientConnector.idleTimeout</code>: the duration of time after which |
| <code>ClientConnector</code> closes a socket due to inactivity (defaults to <code>30</code> seconds). |
| This is an important parameter to configure, and you typically want the client |
| idle timeout to be shorter than the server idle timeout, to avoid race |
| conditions where the client attempts to use a socket just before the client-side |
| idle timeout expires, but the server-side idle timeout has already expired and |
| the is already closing the socket.</p> |
| </li> |
| <li> |
| <p><code>ClientConnector.connectBlocking</code>: whether the operation of connecting a |
| socket to the server (i.e. <code>SocketChannel.connect(SocketAddress)</code>) must be a |
| blocking or a non-blocking operation (defaults to <code>false</code>). |
| For <code>localhost</code> or same datacenter hosts you want to set this parameter to |
| <code>true</code> because DNS resolution will be immediate (and likely never fail). |
| For generic Internet hosts (e.g. when you are implementing a web spider) you |
| want to set this parameter to <code>false</code>.</p> |
| </li> |
| <li> |
| <p><code>ClientConnector.connectTimeout</code>: the duration of time after which |
| <code>ClientConnector</code> aborts a connection attempt to the server (defaults to <code>5</code> |
| seconds). |
| This time includes the DNS lookup time <em>and</em> the TCP connect time.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Please refer to the <code>ClientConnector</code> |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/ClientConnector.html">javadocs</a> |
| for the complete list of configurable parameters.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Once the <code>ClientConnector</code> is configured and started, it can be used to connect |
| to the server via <code>ClientConnector.connect(SocketAddress, Map<String, Object>)</code> |
| which in turn will call <code>SocketChannel.connect(SocketAddress)</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When establishing a TCP connection to a server, applications need to tell |
| <code>ClientConnector</code> how to create the <code>Connection</code> for that particular |
| TCP connection. |
| This is done via a |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/ClientConnectionFactory.html"><code>ClientConnectionFactory</code></a>. |
| that must be passed in the context <code>Map</code> as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java"></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>TODO: expand on what is the API to use, what parameters the context Map must |
| have, and basically how we can write a generic network client with it.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="client-concepts-protocol">Client Libraries Protocol Layer</h4> |
| <div class="paragraph"> |
| <p>The protocol layer builds on top of the infrastructure layer to generate the |
| bytes to be written to the network and to parse the bytes received from the |
| network.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="server">Jetty Server Libraries</h2> |
| <div class="sectionbody"> |
| |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="advanced-embedding">Embedding</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="jetty-helloworld">Jetty Embedded HelloWorld</h3> |
| <div class="paragraph"> |
| <p>This section provides a tutorial that shows how you can quickly develop embedded code against the Jetty API.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="downloading-jars">Downloading the Jars</h4> |
| <div class="paragraph"> |
| <p>Jetty is decomposed into many jars and dependencies to achieve a minimal footprint by selecting the minimal set of jars. |
| Typically it is best to use something like <a href="#jetty-maven-helloworld">Maven</a> to manage jars, however this tutorial uses an aggregate Jar that contains all of the required Jetty classes in one Jar. |
| You can manually download the aggregate <a href="https://repo1.maven.org/maven2/org/eclipse/jetty/aggregate/jetty-all/10.0.0-SNAPSHOT/jetty-all-10.0.0-SNAPSHOT-uber.jar"><code>jetty-all.jar</code></a> using <code>curl</code> or a browser.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| The central Maven repository has started to aggressively reject/deny access to the repository from the <code>wget</code> command line tool (due to abusive use of the tool by some groups). |
| The administrators of the central maven repository have stated that the recommended command line download tool is now curl. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock important"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-important" title="Important"></i> |
| </td> |
| <td class="content"> |
| The <code>jetty-all</code> jar referenced in this section is for example purposes only and should not be used outside of this context. |
| Please consider using <a href="#jetty-maven-helloworld">Maven</a> to manage your project dependencies. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>Use curl as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> mkdir Demo |
| > cd Demo |
| > curl -o jetty-all-uber.jar https://repo1.maven.org/maven2/org/eclipse/jetty/aggregate/jetty-all/10.0.0-SNAPSHOT/jetty-all-10.0.0-SNAPSHOT-uber.jar</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="writing-helloworld-example">Writing a HelloWorld Example</h4> |
| <div class="paragraph"> |
| <p>The <a href="#embedding">Embedding Jetty</a> section contains many examples of writing against the Jetty API. |
| This tutorial uses a simple HelloWorld handler with a main method to run the server. |
| You can either <a href="https://github.com/eclipse/jetty.project/tree/master/examples/embedded/src/main/java/org/eclipse/jetty/embedded/HelloWorld.java">download</a> or create in an editor the file <code>HelloWorld.java</code> with the following content:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.IOException; |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.jetty.server.Request; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.handler.AbstractHandler; |
| |
| public class HelloWorld extends AbstractHandler |
| { |
| @Override |
| public void handle(String target, |
| Request baseRequest, |
| HttpServletRequest request, |
| HttpServletResponse response) throws IOException, |
| ServletException |
| { |
| // Declare response encoding and types |
| response.setContentType("text/html; charset=utf-8"); |
| |
| // Declare response status code |
| response.setStatus(HttpServletResponse.SC_OK); |
| |
| // Write back response |
| response.getWriter().println("<h1>Hello World</h1>"); |
| |
| // Inform jetty that this request has now been handled |
| baseRequest.setHandled(true); |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = new Server(port); |
| server.setHandler(new HelloWorld()); |
| |
| server.start(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="compiling-helloworld-example">Compiling the HelloWord example</h4> |
| <div class="paragraph"> |
| <p>The following command compiles the HelloWorld class:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> mkdir classes |
| > javac -d classes -cp jetty-all-uber.jar HelloWorld.java</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="running-handler-and-server">Running the Handler and Server</h4> |
| <div class="paragraph"> |
| <p>The following command runs the HelloWorld example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> java -cp classes:jetty-all-uber.jar org.eclipse.jetty.embedded.HelloWorld</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You can now point your browser at <a href="http://localhost:8080/">http://localhost:8080</a> to see your hello world page.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="next-steps">Next Steps</h4> |
| <div class="paragraph"> |
| <p>To learn more about Jetty, take these next steps:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Follow the examples in <a href="#embedding-jetty">Embedding Jetty</a> to better understand the jetty APIs.</p> |
| </li> |
| <li> |
| <p>Explore the complete <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/">Jetty javadoc</a></p> |
| </li> |
| <li> |
| <p>Consider using <a href="#maven-and-jetty">Jetty and Maven</a> to manage your Jars and dependencies.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="embedding-jetty">Embedding Jetty</h3> |
| <div class="paragraph"> |
| <p>Jetty has a slogan, "<em>Don’t deploy your application in Jetty, deploy Jetty in your application!</em>" |
| What this means is that as an alternative to bundling your application as a standard WAR to be deployed in Jetty, Jetty is designed to be a software component that can be instantiated and used in a Java program just like any POJO. |
| Put another way, running Jetty in embedded mode means putting an HTTP module into your application, rather than putting your application into an HTTP server.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This tutorial takes you step-by-step from the simplest Jetty server instantiation to running multiple web applications with standards-based deployment descriptors. |
| The source for most of these examples is part of the standard Jetty project.</p> |
| </div> |
| <div class="sect3"> |
| <h4>Overview</h4> |
| <div class="paragraph"> |
| <p>To embed a Jetty server the following steps are typical and are illustrated by the examples in this tutorial:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>Create a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/Server.html">Server</a> instance.</p> |
| </li> |
| <li> |
| <p>Add/Configure <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/Connector.html">Connectors</a>.</p> |
| </li> |
| <li> |
| <p>Add/Configure <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/Handler.html">Handlers</a> and/or <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/ContextHandler.html">Contexts</a> and/or <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/Servlet.html">Servlets</a>.</p> |
| </li> |
| <li> |
| <p>Start the Server.</p> |
| </li> |
| <li> |
| <p>Wait on the server or do something else with your thread.</p> |
| </li> |
| </ol> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Creating the Server</h4> |
| <div class="paragraph"> |
| <p>The following code from SimplestServer.java instantiates and runs the simplest possible Jetty server:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import org.eclipse.jetty.server.Server; |
| |
| /** |
| * The simplest possible Jetty server. |
| */ |
| public class SimplestServer |
| { |
| public static Server createServer(int port) |
| { |
| Server server = new Server(port); |
| // This has a connector listening on port specified |
| // and no handlers, meaning all requests will result |
| // in a 404 response |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| server.start(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This runs an HTTP server on port 8080. It is not a very useful server as it has no handlers, and thus returns a 404 error for every request.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Using Handlers</h4> |
| <div class="paragraph"> |
| <p>To produce a response to a request, Jetty requires that you set a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/Handler.html">Handler</a> on the server. |
| A handler may:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Examine/modify the HTTP request.</p> |
| </li> |
| <li> |
| <p>Generate the complete HTTP response.</p> |
| </li> |
| <li> |
| <p>Call another Handler (see <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/HandlerWrapper.html"><code>HandlerWrapper</code></a>).</p> |
| </li> |
| <li> |
| <p>Select one or many Handlers to call (see <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/HandlerCollection.html"><code>HandlerCollection</code></a>).</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect4"> |
| <h5>HelloWorld Handler</h5> |
| <div class="paragraph"> |
| <p>The following code based on HelloHandler.java shows a simple hello world handler:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.jetty.server.Request; |
| import org.eclipse.jetty.server.handler.AbstractHandler; |
| |
| public class HelloHandler extends AbstractHandler |
| { |
| final String greeting; |
| final String body; |
| |
| public HelloHandler() |
| { |
| this("Hello World"); |
| } |
| |
| public HelloHandler(String greeting) |
| { |
| this(greeting, null); |
| } |
| |
| public HelloHandler(String greeting, String body) |
| { |
| this.greeting = greeting; |
| this.body = body; |
| } |
| |
| @Override |
| public void handle(String target, |
| Request baseRequest, |
| HttpServletRequest request, |
| HttpServletResponse response) throws IOException, |
| ServletException |
| { |
| response.setContentType("text/html; charset=utf-8"); |
| response.setStatus(HttpServletResponse.SC_OK); |
| |
| PrintWriter out = response.getWriter(); |
| |
| out.println("<h1>" + greeting + "</h1>"); |
| if (body != null) |
| { |
| out.println(body); |
| } |
| |
| baseRequest.setHandled(true); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The parameters passed to the handle method are:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>target</code> – the target of the request, which is either a URI or a name from a named dispatcher.</p> |
| </li> |
| <li> |
| <p><code>baseRequest</code> – the Jetty mutable request object, which is always unwrapped.</p> |
| </li> |
| <li> |
| <p><code>request</code> – the immutable request object, which may have been wrapped by a filter or servlet.</p> |
| </li> |
| <li> |
| <p><code>response</code> – the response, which may have been wrapped by a filter or servlet.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The handler sets the response status, content-type, and marks the request as handled before it generates the body of the response using a writer.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Running HelloWorldHandler</h5> |
| <div class="paragraph"> |
| <p>To allow a Handler to handle HTTP requests, you must add it to a Server instance. |
| The following code from OneHandler.java shows how a Jetty server can use the HelloWorld handler:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import org.eclipse.jetty.server.Server; |
| |
| public class OneHandler |
| { |
| public static Server createServer(int port) |
| { |
| Server server = new Server(port); |
| server.setHandler(new HelloHandler()); |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| server.start(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>One or more handlers do all request handling in Jetty. |
| Some handlers select other specific handlers (for example, a <code>ContextHandlerCollection</code> uses the context path to select a <code>ContextHandler</code>); others use application logic to generate a response (for example, the <code>ServletHandler</code> passes the request to an application Servlet), while others do tasks unrelated to generating the response (for example, <code>RequestLogHandler</code> or <code>StatisticsHandler</code>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Later sections describe how you can combine handlers like aspects. |
| You can see some of the handlers available in Jetty in the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/package-summary.html">org.eclipse.jetty.server.handler</a> package.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Handler Collections and Wrappers</h5> |
| <div class="paragraph"> |
| <p>Complex request handling is typically built from multiple Handlers that you can combine in various ways. |
| Jetty has several implementations of the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/HandlerContainer.html"><code>HandlerContainer</code></a> interface:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/HandlerCollection.html"><code>HandlerCollection</code></a></dt> |
| <dd> |
| <p>Holds a collection of other handlers and calls each handler in order. |
| This is useful for combining statistics and logging handlers with the handler that generates the response.</p> |
| </dd> |
| <dt class="hdlist1"><a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/HandlerList.html"><code>HandlerList</code></a></dt> |
| <dd> |
| <p>A Handler Collection that calls each handler in turn until either an exception is thrown, the response is committed or the <code>request.isHandled()</code> returns true. |
| You can use it to combine handlers that conditionally handle a request, such as calling multiple contexts until one matches a virtual host.</p> |
| </dd> |
| <dt class="hdlist1"><a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/HandlerWrapper.html"><code>HandlerWrapper</code></a></dt> |
| <dd> |
| <p>A Handler base class that you can use to daisy chain handlers together in the style of aspect-oriented programming. |
| For example, a standard web application is implemented by a chain of a context, session, security and servlet handlers.</p> |
| </dd> |
| <dt class="hdlist1"><a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/ContextHandlerCollection.html"><code>ContextHandlerCollection</code></a></dt> |
| <dd> |
| <p>A specialized <code>HandlerCollection</code> that uses the longest prefix of the request URI (the <code>contextPath</code>) to select a contained <code>ContextHandler</code> to handle the request.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Scoped Handlers</h5> |
| <div class="paragraph"> |
| <p>Much of the standard Servlet container in Jetty is implemented with <code>HandlerWrappers</code> that daisy chain handlers together: <code>ContextHandler</code> to <code>SessionHandler</code> to <code>SecurityHandler</code> to <code>ServletHandler</code>. |
| However, because of the nature of the servlet specification, this chaining cannot be a pure nesting of handlers as the outer handlers sometimes need information that the inner handlers process. |
| For example, when a <code>ContextHandler</code> calls some application listeners to inform them of a request entering the context, it must already know which servlet the <code>ServletHandler</code> will dispatch the request to so that the <code>servletPath</code> method returns the correct value.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>HandlerWrapper</code> is specialized to the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/ScopedHandler.html"><code>ScopedHandler</code></a> abstract class, which supports a daisy chain of scopes. |
| For example if a <code>ServletHandler</code> is nested within a <code>ContextHandler</code>, the order and nesting of execution of methods is:</p> |
| </div> |
| <div class="literalblock"> |
| <div class="content"> |
| <pre>Server.handle(...) |
| ContextHandler.doScope(...) |
| ServletHandler.doScope(...) |
| ContextHandler.doHandle(...) |
| ServletHandler.doHandle(...) |
| SomeServlet.service(...)</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Thus when the <code>ContextHandler</code> handles the request, it does so within the scope the <code>ServletHandler</code> has established.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Resource Handler</h5> |
| <div class="paragraph"> |
| <p>The <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/FileServer.html">FileServer example</a> shows how you can use a <code>ResourceHandler</code> to serve static content from the current working directory:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| |
| import org.eclipse.jetty.server.Handler; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.handler.DefaultHandler; |
| import org.eclipse.jetty.server.handler.HandlerList; |
| import org.eclipse.jetty.server.handler.ResourceHandler; |
| import org.eclipse.jetty.util.resource.PathResource; |
| import org.eclipse.jetty.util.resource.Resource; |
| |
| /** |
| * Simple Jetty FileServer. |
| * This is a simple example of Jetty configured as a FileServer. |
| */ |
| public class FileServer |
| { |
| public static Server createServer(int port, Resource baseResource) throws Exception |
| { |
| // Create a basic Jetty server object that will listen on port 8080. Note that if you set this to port 0 |
| // then a randomly available port will be assigned that you can either look in the logs for the port, |
| // or programmatically obtain it for use in test cases. |
| Server server = new Server(port); |
| |
| // Create the ResourceHandler. It is the object that will actually handle the request for a given file. It is |
| // a Jetty Handler object so it is suitable for chaining with other handlers as you will see in other examples. |
| ResourceHandler resourceHandler = new ResourceHandler(); |
| |
| // Configure the ResourceHandler. Setting the resource base indicates where the files should be served out of. |
| // In this example it is the current directory but it can be configured to anything that the jvm has access to. |
| resourceHandler.setDirectoriesListed(true); |
| resourceHandler.setWelcomeFiles(new String[]{"index.html"}); |
| resourceHandler.setBaseResource(baseResource); |
| |
| // Add the ResourceHandler to the server. |
| HandlerList handlers = new HandlerList(); |
| handlers.setHandlers(new Handler[]{resourceHandler, new DefaultHandler()}); |
| server.setHandler(handlers); |
| |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Path userDir = Paths.get(System.getProperty("user.dir")); |
| PathResource pathResource = new PathResource(userDir); |
| |
| Server server = createServer(port, pathResource); |
| |
| // Start things up! By using the server.join() the server thread will join with the current thread. |
| // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. |
| server.start(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Notice that a <code>HandlerList</code> is used with the <code>ResourceHandler</code> and a <code>DefaultHandler</code>, so that the <code>DefaultHandler</code> generates a good 404 response for any requests that do not match a static resource.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Embedding Connectors</h4> |
| <div class="paragraph"> |
| <p>In the previous examples, the Server instance is passed a port number and it internally creates a default instance of a Connector that listens for requests on that port. |
| However, often when embedding Jetty it is desirable to explicitly instantiate and configure one or more Connectors for a Server instance.</p> |
| </div> |
| <div class="sect4"> |
| <h5>One Connector</h5> |
| <div class="paragraph"> |
| <p>The following example, <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/OneConnector.html">OneConnector.java</a>, |
| instantiates, configures, and adds a single HTTP connector instance to the server:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.ServerConnector; |
| |
| /** |
| * A Jetty server with one connectors. |
| */ |
| public class OneConnector |
| { |
| public static Server createServer(int port) throws Exception |
| { |
| // The Server |
| Server server = new Server(); |
| |
| // HTTP connector |
| ServerConnector http = new ServerConnector(server); |
| http.setHost("localhost"); |
| http.setPort(port); |
| http.setIdleTimeout(30000); |
| |
| // Set the connector |
| server.addConnector(http); |
| |
| // Set a handler |
| server.setHandler(new HelloHandler()); |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| |
| // Start the server |
| server.start(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In this example the connector handles the HTTP protocol, as that is the default for the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/ServerConnector.html"><code>ServerConnector</code></a> class.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Many Connectors</h5> |
| <div class="paragraph"> |
| <p>When configuring multiple connectors (for example, HTTP and HTTPS), it may be desirable to share configuration of common parameters for HTTP. |
| To achieve this you need to explicitly configure the <code>ServerConnector</code> class with <code>ConnectionFactory</code> instances, and provide them with common HTTP configuration.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/ManyConnectors.html">ManyConnectors example</a>, configures a server with two <code>ServerConnector</code> instances: the http connector has a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/HttpConnectionFactory.html"><code>HTTPConnectionFactory</code></a> instance; the https connector has a <code>SslConnectionFactory</code> chained to a <code>HttpConnectionFactory</code>. |
| Both <code>HttpConnectionFactory</code> are configured based on the same <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/HttpConfiguration.html"><code>HttpConfiguration</code></a> instance, however the HTTPS factory uses a wrapped configuration so that a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/SecureRequestCustomizer.html"><code>SecureRequestCustomizer</code></a> can be added.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Embedding Servlets</h4> |
| <div class="paragraph"> |
| <p><a href="http://en.wikipedia.org/wiki/Java_Servlet">Servlets</a> are the standard way to provide application logic that handles HTTP requests. |
| Servlets are similar to a Jetty Handler except that the request object is not mutable and thus cannot be modified. |
| Servlets are handled in Jetty by a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/MinimalServlets.html"><code>ServletHandler</code></a>. |
| It uses standard path mappings to match a Servlet to a request; sets the requests <code>servletPath</code> and <code>pathInfo</code>; passes the request to the servlet, possibly via Filters to produce a response.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/MinimalServlets.html">MinimalServlets example</a> creates a <code>ServletHandler</code> instance and configures a single HelloServlet:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.IOException; |
| import javax.servlet.http.HttpServlet; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.servlet.ServletHandler; |
| |
| public class MinimalServlets |
| { |
| |
| public static Server createServer(int port) |
| { |
| // Note that if you set this to port 0 then a randomly available port |
| // will be assigned that you can either look in the logs for the port, |
| // or programmatically obtain it for use in test cases. |
| Server server = new Server(port); |
| |
| // The ServletHandler is a dead simple way to create a context handler |
| // that is backed by an instance of a Servlet. |
| // This handler then needs to be registered with the Server object. |
| ServletHandler handler = new ServletHandler(); |
| server.setHandler(handler); |
| |
| // Passing in the class for the Servlet allows jetty to instantiate an |
| // instance of that Servlet and mount it on a given context path. |
| |
| // IMPORTANT: |
| // This is a raw Servlet, not a Servlet that has been configured |
| // through a web.xml @WebServlet annotation, or anything similar. |
| handler.addServletWithMapping(HelloServlet.class, "/*"); |
| |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| // Create a basic jetty server object that will listen on port 8080. |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| |
| // Start things up! |
| server.start(); |
| |
| // The use of server.join() the will make the current thread join and |
| // wait until the server thread is done executing. |
| server.join(); |
| } |
| |
| @SuppressWarnings("serial") |
| public static class HelloServlet extends HttpServlet |
| { |
| @Override |
| protected void doGet(HttpServletRequest request, |
| HttpServletResponse response) throws IOException |
| { |
| response.setStatus(HttpServletResponse.SC_OK); |
| response.setContentType("text/html"); |
| response.setCharacterEncoding("utf-8"); |
| response.getWriter().println("<h1>Hello from HelloServlet</h1>"); |
| } |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Embedding Contexts</h4> |
| <div class="paragraph"> |
| <p>A <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/OneContext.html"><code>ContextHandler</code></a> is a <code>ScopedHandler</code> that responds only to requests that have a URI prefix that matches the configured context path. |
| Requests that match the context path have their path methods updated accordingly and the contexts scope is available, which optionally may include:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A <code>Classloader</code> that is set as the Thread context <code>classloader</code> while request handling is in scope.</p> |
| </li> |
| <li> |
| <p>A set of attributes that is available via the <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html"><code>ServletContext</code></a> API.</p> |
| </li> |
| <li> |
| <p>A set of init parameters that is available via the <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html"><code>ServletContext</code></a> API.</p> |
| </li> |
| <li> |
| <p>A base Resource which is used as the document root for static resource requests via the <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html"><code>ServletContext</code></a> API.</p> |
| </li> |
| <li> |
| <p>A set of virtual host names.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The following <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/OneContext.html">OneContext example</a> shows a context being established that wraps the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/HelloHandler.html">HelloHandler</a>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.handler.ContextHandler; |
| |
| public class OneContext |
| { |
| public static Server createServer(int port) |
| { |
| Server server = new Server(port); |
| |
| // Add a single handler on context "/hello" |
| ContextHandler context = new ContextHandler(); |
| context.setContextPath("/hello"); |
| context.setHandler(new HelloHandler()); |
| |
| // Can be accessed using http://localhost:8080/hello |
| |
| server.setHandler(context); |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| |
| // Start the server |
| server.start(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When many contexts are present, you can embed a <code>ContextHandlerCollection</code> to efficiently examine a request URI to then select the matching <code>ContextHandler</code>(s) for the request. |
| The <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/ManyContexts.html">ManyContexts example</a> shows how many such contexts you can configure:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.handler.ContextHandler; |
| import org.eclipse.jetty.server.handler.ContextHandlerCollection; |
| |
| public class ManyContexts |
| { |
| public static Server createServer(int port) |
| { |
| Server server = new Server(port); |
| |
| ContextHandler context = new ContextHandler("/"); |
| context.setContextPath("/"); |
| context.setHandler(new HelloHandler("Root Hello")); |
| |
| ContextHandler contextFR = new ContextHandler("/fr"); |
| contextFR.setHandler(new HelloHandler("Bonjour")); |
| |
| ContextHandler contextIT = new ContextHandler("/it"); |
| contextIT.setHandler(new HelloHandler("Buongiorno")); |
| |
| ContextHandler contextV = new ContextHandler("/"); |
| contextV.setVirtualHosts(new String[]{"127.0.0.2"}); |
| contextV.setHandler(new HelloHandler("Virtual Hello")); |
| |
| ContextHandlerCollection contexts = new ContextHandlerCollection( |
| context, contextFR, contextIT, contextV |
| ); |
| |
| server.setHandler(contexts); |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| server.start(); |
| server.dumpStdErr(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Embedding ServletContexts</h4> |
| <div class="paragraph"> |
| <p>A <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/servlet/ServletContextHandler.html"><code>ServletContextHandler</code></a> is a specialization of <code>ContextHandler</code> with support for standard sessions and Servlets. |
| The following <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/OneServletContext.html">OneServletContext example</a> instantiates a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/servlet/DefaultServlet.html"><code>DefaultServlet</code></a> to server static content from /tmp/ and a <code>DumpServlet</code> that creates a session and dumps basic details about the request:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.IOException; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.EnumSet; |
| import javax.servlet.Filter; |
| import javax.servlet.FilterChain; |
| import javax.servlet.FilterConfig; |
| import javax.servlet.ServletContextEvent; |
| import javax.servlet.ServletContextListener; |
| import javax.servlet.ServletException; |
| import javax.servlet.ServletRequest; |
| import javax.servlet.ServletRequestEvent; |
| import javax.servlet.ServletRequestListener; |
| import javax.servlet.ServletResponse; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.servlet.DefaultServlet; |
| import org.eclipse.jetty.servlet.ListenerHolder; |
| import org.eclipse.jetty.servlet.ServletContextHandler; |
| import org.eclipse.jetty.servlet.ServletHolder; |
| import org.eclipse.jetty.util.resource.PathResource; |
| import org.eclipse.jetty.util.resource.Resource; |
| |
| import static javax.servlet.DispatcherType.ASYNC; |
| import static javax.servlet.DispatcherType.REQUEST; |
| |
| public class OneServletContext |
| { |
| public static Server createServer(int port, Resource baseResource) |
| { |
| Server server = new Server(port); |
| |
| ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); |
| context.setContextPath("/"); |
| context.setBaseResource(baseResource); |
| server.setHandler(context); |
| |
| // add hello servlet |
| context.addServlet(HelloServlet.class, "/hello/*"); |
| |
| // Add dump servlet on multiple url-patterns |
| ServletHolder debugHolder = new ServletHolder("debug", DumpServlet.class); |
| context.addServlet(debugHolder, "/dump/*"); |
| context.addServlet(debugHolder, "*.dump"); |
| |
| // add default servlet (for error handling and static resources) |
| context.addServlet(DefaultServlet.class, "/"); |
| |
| // sprinkle in a few filters to demonstrate behaviors |
| context.addFilter(TestFilter.class, "/test/*", EnumSet.of(REQUEST)); |
| context.addFilter(TestFilter.class, "*.test", EnumSet.of(REQUEST, ASYNC)); |
| |
| // and a few listeners to show other ways of working with servlets |
| context.getServletHandler().addListener(new ListenerHolder(InitListener.class)); |
| context.getServletHandler().addListener(new ListenerHolder(RequestListener.class)); |
| |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Path tempDir = Paths.get(System.getProperty("java.io.tmpdir")); |
| |
| Server server = createServer(port, new PathResource(tempDir)); |
| |
| server.start(); |
| server.dumpStdErr(); |
| server.join(); |
| } |
| |
| public static class TestFilter implements Filter |
| { |
| @Override |
| public void init(FilterConfig filterConfig) |
| { |
| } |
| |
| @Override |
| public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException |
| { |
| if (response instanceof HttpServletResponse) |
| { |
| HttpServletResponse httpServletResponse = (HttpServletResponse)response; |
| httpServletResponse.setHeader("X-TestFilter", "true"); |
| } |
| chain.doFilter(request, response); |
| } |
| |
| @Override |
| public void destroy() |
| { |
| |
| } |
| } |
| |
| public static class InitListener implements ServletContextListener |
| { |
| @Override |
| public void contextInitialized(ServletContextEvent sce) |
| { |
| sce.getServletContext().setAttribute("X-Init", "true"); |
| } |
| |
| @Override |
| public void contextDestroyed(ServletContextEvent sce) |
| { |
| } |
| } |
| |
| public static class RequestListener implements ServletRequestListener |
| { |
| @Override |
| public void requestInitialized(ServletRequestEvent sre) |
| { |
| sre.getServletRequest().setAttribute("X-ReqListener", "true"); |
| } |
| |
| @Override |
| public void requestDestroyed(ServletRequestEvent sre) |
| { |
| } |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Embedding Web Applications</h4> |
| <div class="paragraph"> |
| <p>A <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html"><code>WebAppContext</code></a> is an extension of a <code>ServletContextHandler</code> that uses the <a href="http://en.wikipedia.org/wiki/WAR_%28Sun_file_format%29">standard layout</a> and web.xml to configure the servlets, filters and other features from a web.xml and/or annotations. |
| The following <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/OneWebApp.html">OneWebApp example</a> configures the Jetty test webapp. |
| Web applications can use resources the container provides, and in this case a <code>LoginService</code> is needed and also configured:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.File; |
| |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.webapp.Configurations; |
| import org.eclipse.jetty.webapp.WebAppContext; |
| |
| public class OneWebApp |
| { |
| public static Server createServer(int port) |
| { |
| // Create a basic jetty server object that will listen on port 8080. |
| // Note that if you set this to port 0 then a randomly available port |
| // will be assigned that you can either look in the logs for the port, |
| // or programmatically obtain it for use in test cases. |
| Server server = new Server(port); |
| |
| // The WebAppContext is the entity that controls the environment in |
| // which a web application lives and breathes. In this example the |
| // context path is being set to "/" so it is suitable for serving root |
| // context requests and then we see it setting the location of the war. |
| // A whole host of other configurations are available, ranging from |
| // configuring to support annotation scanning in the webapp (through |
| // PlusConfiguration) to choosing where the webapp will unpack itself. |
| WebAppContext webapp = new WebAppContext(); |
| webapp.setContextPath("/"); |
| File warFile = JettyDistribution.resolve("demo-base/webapps/async-rest.war").toFile(); |
| webapp.setWar(warFile.getAbsolutePath()); |
| |
| // A WebAppContext is a ContextHandler as well so it needs to be set to |
| // the server so it is aware of where to send the appropriate requests. |
| server.setHandler(webapp); |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| |
| Configurations.setServerDefault(server); |
| |
| // Start things up! |
| server.start(); |
| |
| server.dumpStdErr(); |
| |
| // The use of server.join() the will make the current thread join and |
| // wait until the server is done executing. |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Like Jetty XML</h4> |
| <div class="paragraph"> |
| <p>The typical way to configure an instance of the Jetty server is via <code>jetty.xml</code> and associated configuration files. |
| However the Jetty XML configuration format is just a simple rendering of what you can do in code; it is very simple to write embedded code that does precisely what the jetty.xml configuration does. |
| The <a href="https://github.com/eclipse/jetty.project/tree/master/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java">LikeJettyXml example</a> following renders in code the behavior obtained from the configuration files:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="https://github.com/eclipse/jetty.project/tree/master/jetty-server/src/main/config/etc/jetty.xml">jetty.xml</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/eclipse/jetty.project/tree/master/jetty-jmx/src/main/config/etc/jetty-jmx.xml">jetty-jmx.xml</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/eclipse/jetty.project/tree/master/jetty-server/src/main/config/etc/jetty-http.xml">jetty-http.xml</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/eclipse/jetty.project/tree/master/jetty-server/src/main/config/etc/jetty-https.xml">jetty-https.xml</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/eclipse/jetty.project/tree/master/jetty-deploy/src/main/config/etc/jetty-deploy.xml">jetty-deploy.xml</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/eclipse/jetty.project/tree/master/jetty-server/src/main/config/etc/jetty-stats.xml">jetty-stats.xml</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/eclipse/jetty.project/tree/master/jetty-server/src/main/config/etc/jetty-requestlog.xml">jetty-requestlog.xml</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/eclipse/jetty.project/tree/master/jetty-server/src/main/config/etc/jetty-lowresources.xml">jetty-lowresources.xml</a></p> |
| </li> |
| <li> |
| <p><a href="https://github.com/eclipse/jetty.project/tree/master/tests/test-webapps/test-jetty-webapp/src/main/config/etc/test-realm.xml">test-realm.xml</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.FileNotFoundException; |
| import java.lang.management.ManagementFactory; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| |
| import org.eclipse.jetty.annotations.AnnotationConfiguration; |
| import org.eclipse.jetty.deploy.DeploymentManager; |
| import org.eclipse.jetty.deploy.PropertiesConfigurationManager; |
| import org.eclipse.jetty.deploy.bindings.DebugListenerBinding; |
| import org.eclipse.jetty.deploy.providers.WebAppProvider; |
| import org.eclipse.jetty.http.HttpVersion; |
| import org.eclipse.jetty.jmx.MBeanContainer; |
| import org.eclipse.jetty.plus.webapp.EnvConfiguration; |
| import org.eclipse.jetty.plus.webapp.PlusConfiguration; |
| import org.eclipse.jetty.rewrite.handler.MsieSslRule; |
| import org.eclipse.jetty.rewrite.handler.RewriteHandler; |
| import org.eclipse.jetty.rewrite.handler.ValidUrlRule; |
| import org.eclipse.jetty.security.HashLoginService; |
| import org.eclipse.jetty.server.AsyncRequestLogWriter; |
| import org.eclipse.jetty.server.CustomRequestLog; |
| import org.eclipse.jetty.server.DebugListener; |
| import org.eclipse.jetty.server.Handler; |
| import org.eclipse.jetty.server.HttpConfiguration; |
| import org.eclipse.jetty.server.HttpConnectionFactory; |
| import org.eclipse.jetty.server.LowResourceMonitor; |
| import org.eclipse.jetty.server.SecureRequestCustomizer; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.ServerConnectionStatistics; |
| import org.eclipse.jetty.server.ServerConnector; |
| import org.eclipse.jetty.server.SslConnectionFactory; |
| import org.eclipse.jetty.server.handler.ContextHandlerCollection; |
| import org.eclipse.jetty.server.handler.DefaultHandler; |
| import org.eclipse.jetty.server.handler.HandlerCollection; |
| import org.eclipse.jetty.server.handler.StatisticsHandler; |
| import org.eclipse.jetty.util.ssl.SslContextFactory; |
| import org.eclipse.jetty.util.thread.QueuedThreadPool; |
| import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; |
| import org.eclipse.jetty.webapp.Configurations; |
| |
| /** |
| * Starts the Jetty Distribution's demo-base directory using entirely |
| * embedded jetty techniques. |
| */ |
| public class LikeJettyXml |
| { |
| public static Server createServer(int port, int securePort, boolean addDebugListener) throws Exception |
| { |
| // Path to as-built jetty-distribution directory |
| Path jettyHomeBuild = JettyDistribution.get(); |
| |
| // Find jetty home and base directories |
| String homePath = System.getProperty("jetty.home", jettyHomeBuild.toString()); |
| Path homeDir = Paths.get(homePath); |
| |
| String basePath = System.getProperty("jetty.base", homeDir.resolve("demo-base").toString()); |
| Path baseDir = Paths.get(basePath); |
| |
| // Configure jetty.home and jetty.base system properties |
| String jettyHome = homeDir.toAbsolutePath().toString(); |
| String jettyBase = baseDir.toAbsolutePath().toString(); |
| System.setProperty("jetty.home", jettyHome); |
| System.setProperty("jetty.base", jettyBase); |
| |
| // === jetty.xml === |
| // Setup Threadpool |
| QueuedThreadPool threadPool = new QueuedThreadPool(); |
| threadPool.setMaxThreads(500); |
| |
| // Server |
| Server server = new Server(threadPool); |
| |
| // Scheduler |
| server.addBean(new ScheduledExecutorScheduler(null, false)); |
| |
| // HTTP Configuration |
| HttpConfiguration httpConfig = new HttpConfiguration(); |
| httpConfig.setSecureScheme("https"); |
| httpConfig.setSecurePort(securePort); |
| httpConfig.setOutputBufferSize(32768); |
| httpConfig.setRequestHeaderSize(8192); |
| httpConfig.setResponseHeaderSize(8192); |
| httpConfig.setSendServerVersion(true); |
| httpConfig.setSendDateHeader(false); |
| // httpConfig.addCustomizer(new ForwardedRequestCustomizer()); |
| |
| // Handler Structure |
| HandlerCollection handlers = new HandlerCollection(); |
| ContextHandlerCollection contexts = new ContextHandlerCollection(); |
| handlers.setHandlers(new Handler[]{contexts, new DefaultHandler()}); |
| server.setHandler(handlers); |
| |
| // === jetty-jmx.xml === |
| MBeanContainer mbContainer = new MBeanContainer( |
| ManagementFactory.getPlatformMBeanServer()); |
| server.addBean(mbContainer); |
| |
| // === jetty-http.xml === |
| ServerConnector http = new ServerConnector(server, |
| new HttpConnectionFactory(httpConfig)); |
| http.setPort(port); |
| http.setIdleTimeout(30000); |
| server.addConnector(http); |
| |
| // === jetty-https.xml === |
| // SSL Context Factory |
| Path keystorePath = Paths.get("src/main/resources/etc/keystore.p12").toAbsolutePath(); |
| if (!Files.exists(keystorePath)) |
| throw new FileNotFoundException(keystorePath.toString()); |
| SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); |
| sslContextFactory.setKeyStorePath(keystorePath.toString()); |
| sslContextFactory.setKeyStorePassword("storepwd"); |
| sslContextFactory.setTrustStorePath(keystorePath.toString()); |
| sslContextFactory.setTrustStorePassword("storepwd"); |
| |
| // SSL HTTP Configuration |
| HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig); |
| httpsConfig.addCustomizer(new SecureRequestCustomizer()); |
| |
| // SSL Connector |
| ServerConnector sslConnector = new ServerConnector(server, |
| new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), |
| new HttpConnectionFactory(httpsConfig)); |
| sslConnector.setPort(securePort); |
| server.addConnector(sslConnector); |
| |
| // === jetty-deploy.xml === |
| DeploymentManager deployer = new DeploymentManager(); |
| if (addDebugListener) |
| { |
| DebugListener debug = new DebugListener(System.err, true, true, true); |
| server.addBean(debug); |
| deployer.addLifeCycleBinding(new DebugListenerBinding(debug)); |
| } |
| deployer.setContexts(contexts); |
| deployer.setContextAttribute( |
| "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", |
| ".*/jetty-servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$"); |
| |
| WebAppProvider webAppProvider = new WebAppProvider(); |
| webAppProvider.setMonitoredDirName(jettyBase + "/webapps"); |
| webAppProvider.setDefaultsDescriptor(jettyHome + "/etc/webdefault.xml"); |
| webAppProvider.setScanInterval(1); |
| webAppProvider.setExtractWars(true); |
| webAppProvider.setConfigurationManager(new PropertiesConfigurationManager()); |
| |
| deployer.addAppProvider(webAppProvider); |
| server.addBean(deployer); |
| |
| // === setup jetty plus == |
| Configurations.setServerDefault(server).add(new EnvConfiguration(), new PlusConfiguration(), new AnnotationConfiguration()); |
| |
| // === jetty-stats.xml === |
| StatisticsHandler stats = new StatisticsHandler(); |
| stats.setHandler(server.getHandler()); |
| server.setHandler(stats); |
| ServerConnectionStatistics.addToAllConnectors(server); |
| |
| // === Rewrite Handler |
| RewriteHandler rewrite = new RewriteHandler(); |
| rewrite.setHandler(server.getHandler()); |
| server.setHandler(rewrite); |
| rewrite.addRule(new MsieSslRule()); |
| rewrite.addRule(new ValidUrlRule()); |
| |
| // === jetty-requestlog.xml === |
| AsyncRequestLogWriter logWriter = new AsyncRequestLogWriter(jettyHome + "/logs/yyyy_mm_dd.request.log"); |
| logWriter.setFilenameDateFormat("yyyy_MM_dd"); |
| logWriter.setRetainDays(90); |
| logWriter.setTimeZone("GMT"); |
| CustomRequestLog requestLog = new CustomRequestLog(logWriter, CustomRequestLog.EXTENDED_NCSA_FORMAT + " \"%C\""); |
| server.setRequestLog(requestLog); |
| |
| // === jetty-lowresources.xml === |
| LowResourceMonitor lowResourcesMonitor = new LowResourceMonitor(server); |
| lowResourcesMonitor.setPeriod(1000); |
| lowResourcesMonitor.setLowResourcesIdleTimeout(200); |
| lowResourcesMonitor.setMonitorThreads(true); |
| lowResourcesMonitor.setMaxMemory(0); |
| lowResourcesMonitor.setMaxLowResourcesTime(5000); |
| server.addBean(lowResourcesMonitor); |
| |
| // === test-realm.xml === |
| HashLoginService login = new HashLoginService(); |
| login.setName("Test Realm"); |
| login.setConfig(jettyBase + "/etc/realm.properties"); |
| login.setHotReload(false); |
| server.addBean(login); |
| |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| int securePort = ExampleUtil.getPort(args, "jetty.https.port", 8443); |
| Server server = createServer(port, securePort, true); |
| |
| // Extra options |
| server.setDumpAfterStart(true); |
| server.setDumpBeforeStop(false); |
| server.setStopAtShutdown(true); |
| |
| // Start the server |
| server.start(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="embedded-examples">Embedded Examples</h3> |
| <div class="paragraph"> |
| <p>Jetty has a rich history of being embedded into a wide variety of applications. |
| In this section we will walk you through a number of our simple examples under our embedded-jetty-examples project in our git repository.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock important"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-important" title="Important"></i> |
| </td> |
| <td class="content"> |
| These files are pulled directly from our git repository when this document is generated. |
| If the line numbers do not line up feel free to fix this documentation in github and give us a pull request, or at least open an issue to notify us of the discrepancy. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="sect3"> |
| <h4 id="embedded-file-server">Simple File Server</h4> |
| <div class="paragraph"> |
| <p>This example shows how to create a simple file server in Jetty. |
| It is perfectly suitable for test cases where you need an actual web server to obtain a file from, it could easily be configured to serve files from a directory under <code>src/test/resources</code>. |
| Note that this does not have any logic for caching of files, either within the server or setting the appropriate headers on the response. |
| It is simply a few lines that illustrate how easy it is to serve out some files.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| |
| import org.eclipse.jetty.server.Handler; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.handler.DefaultHandler; |
| import org.eclipse.jetty.server.handler.HandlerList; |
| import org.eclipse.jetty.server.handler.ResourceHandler; |
| import org.eclipse.jetty.util.resource.PathResource; |
| import org.eclipse.jetty.util.resource.Resource; |
| |
| /** |
| * Simple Jetty FileServer. |
| * This is a simple example of Jetty configured as a FileServer. |
| */ |
| public class FileServer |
| { |
| public static Server createServer(int port, Resource baseResource) throws Exception |
| { |
| // Create a basic Jetty server object that will listen on port 8080. Note that if you set this to port 0 |
| // then a randomly available port will be assigned that you can either look in the logs for the port, |
| // or programmatically obtain it for use in test cases. |
| Server server = new Server(port); |
| |
| // Create the ResourceHandler. It is the object that will actually handle the request for a given file. It is |
| // a Jetty Handler object so it is suitable for chaining with other handlers as you will see in other examples. |
| ResourceHandler resourceHandler = new ResourceHandler(); |
| |
| // Configure the ResourceHandler. Setting the resource base indicates where the files should be served out of. |
| // In this example it is the current directory but it can be configured to anything that the jvm has access to. |
| resourceHandler.setDirectoriesListed(true); |
| resourceHandler.setWelcomeFiles(new String[]{"index.html"}); |
| resourceHandler.setBaseResource(baseResource); |
| |
| // Add the ResourceHandler to the server. |
| HandlerList handlers = new HandlerList(); |
| handlers.setHandlers(new Handler[]{resourceHandler, new DefaultHandler()}); |
| server.setHandler(handlers); |
| |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Path userDir = Paths.get(System.getProperty("user.dir")); |
| PathResource pathResource = new PathResource(userDir); |
| |
| Server server = createServer(port, pathResource); |
| |
| // Start things up! By using the server.join() the server thread will join with the current thread. |
| // See "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" for more details. |
| server.start(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Run it!</h5> |
| <div class="paragraph"> |
| <p>After you have started things up you should be able to navigate to <a href="http://localhost:8080/index.html" class="bare">http://localhost:8080/index.html</a> (assuming one is in the resource base directory) and you are good to go.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Maven Coordinates</h5> |
| <div class="paragraph"> |
| <p>To use this example in your project you will need the following Maven dependencies declared.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-server</artifactId> |
| <version>${project.version}</version> |
| </dependency></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="embedded-split-file-server">Split File Server</h4> |
| <div class="paragraph"> |
| <p>This example builds on the <a href="#emebedded-file-server">Simple File Server</a> to show how chaining multiple <code>ResourceHandlers</code> together can let you aggregate multiple directories to serve content on a single path and how you can link these together with <code>ContextHandlers</code>.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.nio.file.Paths; |
| |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.ServerConnector; |
| import org.eclipse.jetty.server.handler.ContextHandler; |
| import org.eclipse.jetty.server.handler.ContextHandlerCollection; |
| import org.eclipse.jetty.server.handler.ResourceHandler; |
| import org.eclipse.jetty.util.resource.PathResource; |
| import org.eclipse.jetty.util.resource.Resource; |
| |
| /** |
| * A {@link ContextHandlerCollection} handler may be used to direct a request to |
| * a specific Context. The URI path prefix and optional virtual host is used to |
| * select the context. |
| */ |
| public class SplitFileServer |
| { |
| public static Server createServer(int port, Resource baseResource0, Resource baseResource1) |
| { |
| // Create the Server object and a corresponding ServerConnector and then |
| // set the port for the connector. In this example the server will |
| // listen on port 8080. If you set this to port 0 then when the server |
| // has been started you can called connector.getLocalPort() to |
| // programmatically get the port the server started on. |
| Server server = new Server(); |
| ServerConnector connector = new ServerConnector(server); |
| connector.setPort(port); |
| server.addConnector(connector); |
| |
| // Create a Context Handler and ResourceHandler. The ContextHandler is |
| // getting set to "/" path but this could be anything you like for |
| // building out your url. Note how we are setting the ResourceBase using |
| // our jetty maven testing utilities to get the proper resource |
| // directory, you needn't use these, you simply need to supply the paths |
| // you are looking to serve content from. |
| ResourceHandler rh0 = new ResourceHandler(); |
| rh0.setDirectoriesListed(false); |
| |
| ContextHandler context0 = new ContextHandler(); |
| context0.setContextPath("/"); |
| context0.setBaseResource(baseResource0); |
| context0.setHandler(rh0); |
| |
| // Rinse and repeat the previous item, only specifying a different |
| // resource base. |
| ResourceHandler rh1 = new ResourceHandler(); |
| rh1.setDirectoriesListed(false); |
| |
| ContextHandler context1 = new ContextHandler(); |
| context1.setContextPath("/"); |
| context1.setBaseResource(baseResource1); |
| context1.setHandler(rh1); |
| |
| // Create a ContextHandlerCollection and set the context handlers to it. |
| // This will let jetty process urls against the declared contexts in |
| // order to match up content. |
| ContextHandlerCollection contexts = new ContextHandlerCollection( |
| context0, context1 |
| ); |
| server.setHandler(contexts); |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Resource resource0 = new PathResource(Paths.get("src/test/resources/dir0")); |
| Resource resource1 = new PathResource(Paths.get("src/test/resources/dir1")); |
| |
| Server server = createServer(port, resource0, resource1); |
| |
| // Dump the server state |
| server.setDumpAfterStart(true); |
| |
| // Start things up! |
| server.start(); |
| |
| // The use of server.join() the will make the current thread join and |
| // wait until the server is done executing. |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Run it!</h5> |
| <div class="paragraph"> |
| <p>After you have started things up you should be able to navigate to <a href="http://localhost:8090/index.html" class="bare">http://localhost:8090/index.html</a> (assuming one is in the resource base directory) and you are good to go. |
| Any requests for files will be looked for in the first resource handler, then the second, and so on and so forth.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Maven Coordinates</h5> |
| <div class="paragraph"> |
| <p>To use this example as is in your project you will need the following maven dependencies declared. |
| We would recommend not using the toolchain dependency in your actual application.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-server</artifactId> |
| <version>${project.version}</version> |
| </dependency> |
| <dependency> |
| <groupId>org.eclipse.jetty.toolchain</groupId> |
| <artifactId>jetty-test-helper</artifactId> |
| <version>2.2</version> |
| </dependency></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="embedded-many-connectors">Multiple Connectors</h4> |
| <div class="paragraph"> |
| <p>This example shows how to configure Jetty to use multiple connectors, specifically so it can process both http and https requests. |
| Since the meat of this example is the server and connector configuration it only uses a simple HelloHandler but this example should be easily merged with other examples like those deploying servlets or webapps.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.FileNotFoundException; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| |
| import org.eclipse.jetty.http.HttpVersion; |
| import org.eclipse.jetty.server.Connector; |
| import org.eclipse.jetty.server.HttpConfiguration; |
| import org.eclipse.jetty.server.HttpConnectionFactory; |
| import org.eclipse.jetty.server.SecureRequestCustomizer; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.ServerConnector; |
| import org.eclipse.jetty.server.SslConnectionFactory; |
| import org.eclipse.jetty.util.ssl.SslContextFactory; |
| |
| /** |
| * A Jetty server with multiple connectors. |
| */ |
| public class ManyConnectors |
| { |
| public static Server createServer(int plainPort, int securePort) throws Exception |
| { |
| // Since this example shows off SSL configuration, we need a keystore |
| // with the appropriate key. |
| Path keystorePath = Paths.get("src/main/resources/etc/keystore.p12").toAbsolutePath(); |
| if (!Files.exists(keystorePath)) |
| throw new FileNotFoundException(keystorePath.toString()); |
| |
| // Create a basic jetty server object without declaring the port. Since |
| // we are configuring connectors directly we'll be setting ports on |
| // those connectors. |
| Server server = new Server(); |
| |
| // HTTP Configuration |
| // HttpConfiguration is a collection of configuration information |
| // appropriate for http and https. The default scheme for http is |
| // <code>http</code> of course, as the default for secured http is |
| // <code>https</code> but we show setting the scheme to show it can be |
| // done. The port for secured communication is also set here. |
| HttpConfiguration httpConfig = new HttpConfiguration(); |
| httpConfig.setSecureScheme("https"); |
| httpConfig.setSecurePort(securePort); |
| httpConfig.setOutputBufferSize(32768); |
| |
| // HTTP connector |
| // The first server connector we create is the one for http, passing in |
| // the http configuration we configured above so it can get things like |
| // the output buffer size, etc. We also set the port (8080) and |
| // configure an idle timeout. |
| ServerConnector http = new ServerConnector(server, |
| new HttpConnectionFactory(httpConfig)); |
| http.setPort(plainPort); |
| http.setIdleTimeout(30000); |
| |
| // SSL Context Factory for HTTPS |
| // SSL requires a certificate so we configure a factory for ssl contents |
| // with information pointing to what keystore the ssl connection needs |
| // to know about. Much more configuration is available the ssl context, |
| // including things like choosing the particular certificate out of a |
| // keystore to be used. |
| |
| SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); |
| sslContextFactory.setKeyStorePath(keystorePath.toString()); |
| sslContextFactory.setKeyStorePassword("storepwd"); |
| |
| // OPTIONAL: Un-comment the following to use Conscrypt for SSL instead of |
| // the native JSSE implementation. |
| |
| //Security.addProvider(new OpenSSLProvider()); |
| //sslContextFactory.setProvider("Conscrypt"); |
| |
| // HTTPS Configuration |
| // A new HttpConfiguration object is needed for the next connector and |
| // you can pass the old one as an argument to effectively clone the |
| // contents. On this HttpConfiguration object we add a |
| // SecureRequestCustomizer which is how a new connector is able to |
| // resolve the https connection before handing control over to the Jetty |
| // Server. |
| HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig); |
| SecureRequestCustomizer src = new SecureRequestCustomizer(); |
| src.setStsMaxAge(2000); |
| src.setStsIncludeSubDomains(true); |
| httpsConfig.addCustomizer(src); |
| |
| // HTTPS connector |
| // We create a second ServerConnector, passing in the http configuration |
| // we just made along with the previously created ssl context factory. |
| // Next we set the port and a longer idle timeout. |
| ServerConnector https = new ServerConnector(server, |
| new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), |
| new HttpConnectionFactory(httpsConfig)); |
| https.setPort(securePort); |
| https.setIdleTimeout(500000); |
| |
| // Here you see the server having multiple connectors registered with |
| // it, now requests can flow into the server from both http and https |
| // urls to their respective ports and be processed accordingly by jetty. |
| // A simple handler is also registered with the server so the example |
| // has something to pass requests off to. |
| |
| // Set the connectors |
| server.setConnectors(new Connector[]{http, https}); |
| |
| // Set a handler |
| server.setHandler(new HelloHandler()); |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| int securePort = ExampleUtil.getPort(args, "jetty.https.port", 8443); |
| Server server = createServer(port, securePort); |
| // Start the server |
| server.start(); |
| server.dumpStdErr(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Walkthrough</h5> |
| <div class="paragraph"> |
| <p>Start things up! |
| By using the <code>server.join()</code> the server thread will join with the current thread. |
| See <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()"><code>Thread.join()</code></a> for more details.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Maven Coordinates</h5> |
| <div class="paragraph"> |
| <p>To use this example in your project you will need the following Maven dependencies declared.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-server</artifactId> |
| <version>${project.version}</version> |
| </dependency> |
| <dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-security</artifactId> |
| <version>${project.version}</version> |
| </dependency></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="embedded-secured-hello-handler">Secured Hello Handler</h4> |
| <div class="paragraph"> |
| <p>This example shows how to wrap one handler with another one that handles security. |
| We have a simple Hello Handler that just return a greeting but add on the restriction that to get this greeting you must authenticate. |
| Another thing to remember is that this example uses the <code>ConstraintSecurityHandler</code> which is what supports the security mappings inside of the servlet api, it could be easier to show just the <code>SecurityHandler</code> usage, but the constraint provides more configuration power. |
| If you don’t need that you can drop the Constraint bits and use just the <code>SecurityHandler</code>.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.FileNotFoundException; |
| import java.net.URL; |
| import java.util.Collections; |
| |
| import org.eclipse.jetty.security.ConstraintMapping; |
| import org.eclipse.jetty.security.ConstraintSecurityHandler; |
| import org.eclipse.jetty.security.HashLoginService; |
| import org.eclipse.jetty.security.LoginService; |
| import org.eclipse.jetty.security.authentication.BasicAuthenticator; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.util.security.Constraint; |
| |
| public class SecuredHelloHandler |
| { |
| public static Server createServer(int port) throws FileNotFoundException |
| { |
| // Create a basic jetty server object that will listen on port 8080. |
| // Note that if you set this to port 0 then a randomly available port |
| // will be assigned that you can either look in the logs for the port, |
| // or programmatically obtain it for use in test cases. |
| Server server = new Server(port); |
| |
| // Since this example is for our test webapp, we need to setup a |
| // LoginService so this shows how to create a very simple hashmap based |
| // one. The name of the LoginService needs to correspond to what is |
| // configured a webapp's web.xml and since it has a lifecycle of its own |
| // we register it as a bean with the Jetty server object so it can be |
| // started and stopped according to the lifecycle of the server itself. |
| // In this example the name can be whatever you like since we are not |
| // dealing with webapp realms. |
| String realmResourceName = "etc/realm.properties"; |
| ClassLoader classLoader = SecuredHelloHandler.class.getClassLoader(); |
| URL realmProps = classLoader.getResource(realmResourceName); |
| if (realmProps == null) |
| throw new FileNotFoundException("Unable to find " + realmResourceName); |
| |
| LoginService loginService = new HashLoginService("MyRealm", |
| realmProps.toExternalForm()); |
| server.addBean(loginService); |
| |
| // A security handler is a jetty handler that secures content behind a |
| // particular portion of a url space. The ConstraintSecurityHandler is a |
| // more specialized handler that allows matching of urls to different |
| // constraints. The server sets this as the first handler in the chain, |
| // effectively applying these constraints to all subsequent handlers in |
| // the chain. |
| ConstraintSecurityHandler security = new ConstraintSecurityHandler(); |
| server.setHandler(security); |
| |
| // This constraint requires authentication and in addition that an |
| // authenticated user be a member of a given set of roles for |
| // authorization purposes. |
| Constraint constraint = new Constraint(); |
| constraint.setName("auth"); |
| constraint.setAuthenticate(true); |
| constraint.setRoles(new String[]{"user", "admin"}); |
| |
| // Binds a url pattern with the previously created constraint. The roles |
| // for this constraint mapping are mined from the Constraint itself |
| // although methods exist to declare and bind roles separately as well. |
| ConstraintMapping mapping = new ConstraintMapping(); |
| mapping.setPathSpec("/*"); |
| mapping.setConstraint(constraint); |
| |
| // First you see the constraint mapping being applied to the handler as |
| // a singleton list, however you can passing in as many security |
| // constraint mappings as you like so long as they follow the mapping |
| // requirements of the servlet api. Next we set a BasicAuthenticator |
| // instance which is the object that actually checks the credentials |
| // followed by the LoginService which is the store of known users, etc. |
| security.setConstraintMappings(Collections.singletonList(mapping)); |
| security.setAuthenticator(new BasicAuthenticator()); |
| security.setLoginService(loginService); |
| |
| // The Hello Handler is the handler we are securing so we create one, |
| // and then set it as the handler on the |
| // security handler to complain the simple handler chain. |
| HelloHandler hh = new HelloHandler(); |
| |
| // chain the hello handler into the security handler |
| security.setHandler(hh); |
| |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| |
| // Start things up! |
| server.start(); |
| |
| // The use of server.join() the will make the current thread join and |
| // wait until the server is done executing. |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Run it!</h5> |
| <div class="paragraph"> |
| <p>After you have started things up you should be able to navigate to <a href="http://localhost:8080/index.html" class="bare">http://localhost:8080/index.html</a> (assuming one is in the resource base directory) and you are good to go.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>The Realm Properties File</h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-properties" data-lang="properties"># |
| # This file defines users passwords and roles for a HashUserRealm |
| # |
| # The format is |
| # <username>: <password>[,<rolename> ...] |
| # |
| # Passwords may be clear text, obfuscated or checksummed. The class |
| # org.eclipse.jetty.util.security.Password should be used to generate obfuscated |
| # passwords or password checksums |
| # |
| # If DIGEST Authentication is used, the password must be in a recoverable |
| # format, either plain text or OBF:. |
| # |
| jetty: MD5:164c88b302622e17050af52c89945d44,user |
| admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin,user |
| other: OBF:1xmk1w261u9r1w1c1xmq,user |
| plain: plain,user |
| user: password,user |
| |
| # This entry is for digest auth. The credential is a MD5 hash of username:realmname:password |
| digest: MD5:6e120743ad67abfbc385bc2bb754e297,user</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Maven Coordinates</h5> |
| <div class="paragraph"> |
| <p>To use this example in your project you will need the following Maven dependencies declared.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-server</artifactId> |
| <version>${project.version}</version> |
| </dependency></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="embedded-minimal-servlet">Minimal Servlet</h4> |
| <div class="paragraph"> |
| <p>This example shows the bare minimum required for deploying a servlet into Jetty. |
| Note that this is strictly a servlet, not a servlet in the context of a web application, that example comes later. |
| This is purely just a servlet deployed and mounted on a context and able to process requests. |
| This example is excellent for situations where you have a simple servlet that you need to unit test, just mount it on a context and issue requests using your favorite http client library (like our Jetty client found in <a href="#http-client">HTTP Client</a>).</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.IOException; |
| import javax.servlet.http.HttpServlet; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.servlet.ServletHandler; |
| |
| public class MinimalServlets |
| { |
| |
| public static Server createServer(int port) |
| { |
| // Note that if you set this to port 0 then a randomly available port |
| // will be assigned that you can either look in the logs for the port, |
| // or programmatically obtain it for use in test cases. |
| Server server = new Server(port); |
| |
| // The ServletHandler is a dead simple way to create a context handler |
| // that is backed by an instance of a Servlet. |
| // This handler then needs to be registered with the Server object. |
| ServletHandler handler = new ServletHandler(); |
| server.setHandler(handler); |
| |
| // Passing in the class for the Servlet allows jetty to instantiate an |
| // instance of that Servlet and mount it on a given context path. |
| |
| // IMPORTANT: |
| // This is a raw Servlet, not a Servlet that has been configured |
| // through a web.xml @WebServlet annotation, or anything similar. |
| handler.addServletWithMapping(HelloServlet.class, "/*"); |
| |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| // Create a basic jetty server object that will listen on port 8080. |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| |
| // Start things up! |
| server.start(); |
| |
| // The use of server.join() the will make the current thread join and |
| // wait until the server thread is done executing. |
| server.join(); |
| } |
| |
| @SuppressWarnings("serial") |
| public static class HelloServlet extends HttpServlet |
| { |
| @Override |
| protected void doGet(HttpServletRequest request, |
| HttpServletResponse response) throws IOException |
| { |
| response.setStatus(HttpServletResponse.SC_OK); |
| response.setContentType("text/html"); |
| response.setCharacterEncoding("utf-8"); |
| response.getWriter().println("<h1>Hello from HelloServlet</h1>"); |
| } |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Walkthrough</h5> |
| <div class="paragraph"> |
| <p>Start things up! By using the <code>server.join()</code> the server thread will join with the current thread. |
| See <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()"><code>Thread.join()</code></a> for more details.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is really simple to create useful servlets for testing behaviors. Sometimes you need a http server to run a unit test against that will return test content and wiring up a servlet like this makes it trivial.</p> |
| </div> |
| <div class="paragraph"> |
| <p>After you have started things up you should be able to navigate to <a href="http://localhost:8080/" class="bare">http://localhost:8080/</a> and you are good to go.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Maven Coordinates</h5> |
| <div class="paragraph"> |
| <p>To use this example in your project you will need the following Maven dependencies declared.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-servlet</artifactId> |
| <version>${project.version}</version> |
| </dependency></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="embedded-one-webapp">Web Application</h4> |
| <div class="paragraph"> |
| <p>This example shows how to deploy a simple webapp with an embedded instance of Jetty. |
| This is useful when you want to manage the lifecycle of a server programmatically, either within a production application or as a simple way to deploying and debugging a full scale application deployment. |
| In many ways it is easier then traditional deployment since you control the classpath yourself, making this easy to wire up in a test case in Maven and issue requests using your favorite http client library (like our Jetty client found in <a href="#http-client">HTTP Client</a>).</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.File; |
| |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.webapp.Configurations; |
| import org.eclipse.jetty.webapp.WebAppContext; |
| |
| public class OneWebApp |
| { |
| public static Server createServer(int port) |
| { |
| // Create a basic jetty server object that will listen on port 8080. |
| // Note that if you set this to port 0 then a randomly available port |
| // will be assigned that you can either look in the logs for the port, |
| // or programmatically obtain it for use in test cases. |
| Server server = new Server(port); |
| |
| // The WebAppContext is the entity that controls the environment in |
| // which a web application lives and breathes. In this example the |
| // context path is being set to "/" so it is suitable for serving root |
| // context requests and then we see it setting the location of the war. |
| // A whole host of other configurations are available, ranging from |
| // configuring to support annotation scanning in the webapp (through |
| // PlusConfiguration) to choosing where the webapp will unpack itself. |
| WebAppContext webapp = new WebAppContext(); |
| webapp.setContextPath("/"); |
| File warFile = JettyDistribution.resolve("demo-base/webapps/async-rest.war").toFile(); |
| webapp.setWar(warFile.getAbsolutePath()); |
| |
| // A WebAppContext is a ContextHandler as well so it needs to be set to |
| // the server so it is aware of where to send the appropriate requests. |
| server.setHandler(webapp); |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| |
| Configurations.setServerDefault(server); |
| |
| // Start things up! |
| server.start(); |
| |
| server.dumpStdErr(); |
| |
| // The use of server.join() the will make the current thread join and |
| // wait until the server is done executing. |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Run it!</h5> |
| <div class="paragraph"> |
| <p>After you have started things up you should be able to navigate to <a href="http://localhost:8080/" class="bare">http://localhost:8080/</a> and you are good to go.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Maven Coordinates</h5> |
| <div class="paragraph"> |
| <p>To use this example in your project you will need the following Maven dependencies declared.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-webapp</artifactId> |
| <version>${project.version}</version> |
| </dependency></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="embedded-webapp-jsp">Web Application with JSP</h4> |
| <div class="paragraph"> |
| <p>This example is very similar to the one in the previous section, although it enables the embedded webapp to use JSPs. |
| As of jetty-9.2, we use the JSP engine from Apache, which relies on a Servlet Specification 3.1 style <code>ServletContainerInitializer</code> to initialize itself. |
| To get this to work with Jetty, you need to enable annotations processing, as shown in this example code:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// |
| // ======================================================================== |
| // Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. |
| // |
| // This program and the accompanying materials are made available under |
| // the terms of the Eclipse Public License 2.0 which is available at |
| // https://www.eclipse.org/legal/epl-2.0 |
| // |
| // This Source Code may also be made available under the following |
| // Secondary Licenses when the conditions for such availability set |
| // forth in the Eclipse Public License, v. 2.0 are satisfied: |
| // the Apache License v2.0 which is available at |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.embedded; |
| |
| import java.io.FileNotFoundException; |
| import java.net.URL; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| |
| import org.eclipse.jetty.annotations.AnnotationConfiguration; |
| import org.eclipse.jetty.security.HashLoginService; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.util.resource.PathResource; |
| import org.eclipse.jetty.webapp.WebAppContext; |
| |
| public class OneWebAppWithJsp |
| { |
| public static Server createServer(int port) throws FileNotFoundException |
| { |
| // Create a basic jetty server object that will listen on port 8080. |
| // Note that if you set this to port 0 then |
| // a randomly available port will be assigned that you can either look |
| // in the logs for the port, |
| // or programmatically obtain it for use in test cases. |
| Server server = new Server(port); |
| |
| // The WebAppContext is the entity that controls the environment in |
| // which a web application lives and breathes. |
| // In this example the context path is being set to "/" so it |
| // is suitable for serving root context |
| // requests and then we see it setting the location of the war. |
| // A whole host of other configurations are |
| // available, ranging from configuring to support annotation scanning in |
| // the webapp (through PlusConfiguration), to choosing where |
| // the webapp will unpack itself. |
| WebAppContext webapp = new WebAppContext(); |
| webapp.setContextPath("/"); |
| Path warFile = JettyDistribution.resolve("demo-base/webapps/test.war"); |
| if (!Files.exists(warFile)) |
| { |
| throw new FileNotFoundException(warFile.toString()); |
| } |
| webapp.setWarResource(new PathResource(warFile)); |
| webapp.setExtractWAR(true); |
| |
| // This webapp will use jsps and jstl. We need to enable the |
| // AnnotationConfiguration in order to correctly |
| // set up the jsp container |
| webapp.addConfiguration(new AnnotationConfiguration()); |
| |
| // Set the ContainerIncludeJarPattern so that jetty examines these |
| // container-path jars for tlds, web-fragments etc. |
| // If you omit the jar that contains the jstl .tlds, the jsp engine will |
| // scan for them instead. |
| webapp.setAttribute( |
| "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", |
| ".*/jetty-servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$"); |
| |
| // A WebAppContext is a ContextHandler as well so it needs to be set to |
| // the server so it is aware of where to |
| // send the appropriate requests. |
| server.setHandler(webapp); |
| |
| // Configure a LoginService. |
| // Since this example is for our test webapp, we need to setup a |
| // LoginService so this shows how to create a very simple hashmap based |
| // one. The name of the LoginService needs to correspond to what is |
| // configured in the webapp's web.xml and since it has a lifecycle of |
| // its own we register it as a bean with the Jetty server object so it |
| // can be started and stopped according to the lifecycle of the server |
| // itself. |
| String realmResourceName = "etc/realm.properties"; |
| ClassLoader classLoader = OneWebAppWithJsp.class.getClassLoader(); |
| URL realmProps = classLoader.getResource(realmResourceName); |
| if (realmProps == null) |
| throw new FileNotFoundException("Unable to find " + realmResourceName); |
| |
| HashLoginService loginService = new HashLoginService(); |
| loginService.setName("Test Realm"); |
| loginService.setConfig(realmProps.toExternalForm()); |
| server.addBean(loginService); |
| |
| return server; |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| int port = ExampleUtil.getPort(args, "jetty.http.port", 8080); |
| Server server = createServer(port); |
| |
| // Start things up! |
| server.start(); |
| |
| server.dumpStdErr(); |
| |
| // The use of server.join() the will make the current thread join and |
| // wait until the server is done executing. |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Run it!</h5> |
| <div class="paragraph"> |
| <p>After you have started things up you should be able to navigate to <a href="http://localhost:8080/jsp/" class="bare">http://localhost:8080/jsp/</a> and click on any of the links to jsps.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Maven Coordinates</h5> |
| <div class="paragraph"> |
| <p>To use this example in your project, you will need the following Maven dependencies declared, in addition to those from the previous section:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-annotations</artifactId> |
| <version>${project.version}</version> |
| </dependency> |
| <dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>apache-jsp</artifactId> |
| <version>${project.version}</version> |
| </dependency> |
| <dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>apache-jstl</artifactId> |
| <version>${project.version}</version> |
| </dependency></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="adding-embedded-examples">Adding Examples</h4> |
| <div class="paragraph"> |
| <p>If you would like to add an example to this list, fork the documentation project from github (see the blue bar at the bottom of this page) and add the new page. |
| Feel free to add the example contents directly as a <code>[source.java]</code> and we will take it from there.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you feel and example is missing, feel free to open a bug to ask for it. |
| No guarantees, but the more helpful and demonstrative it is the better.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="maven-and-jetty">Maven and Jetty</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>This chapter explains how to use Jetty with Maven and the Jetty Maven plugin.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-maven-helloworld">Using Maven</h3> |
| <div class="paragraph"> |
| <p><a href="http://maven.apache.org/">Apache Maven</a> is a software project management and comprehension tool. |
| Based on the concept of a project object model (POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is an ideal tool to build a web application project, and such projects can use the <a href="#jetty-maven-plugin">jetty-maven-plugin</a> to easily run the web application and save time in development. |
| You can also use Maven to build, test and run a project which embeds Jetty.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| Use of Maven and the jetty-maven-plugin is <strong>not</strong> required. |
| Using Maven for Jetty implementations is a popular choice, but users encouraged to manage their projects in whatever way suits their needs. |
| Other popular tools include Ant and Gradle. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>First we’ll have a look at a very simple HelloWorld java application that embeds Jetty, then a simple webapp which makes use of the <a href="#jetty-maven-plugin">jetty-maven-plugin</a> to speed up the development cycle.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="configuring-embedded-jetty-with-maven">Using Embedded Jetty with Maven</h4> |
| <div class="paragraph"> |
| <p>To understand the basic operations of building and running against Jetty, first review:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#advanced-embedding">Embedding with Jetty</a></p> |
| </li> |
| <li> |
| <p><a href="#jetty-helloworld">Jetty HelloWorld example</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Maven uses convention over configuration, so it is best to use the project structure Maven recommends. |
| You can use <em><a href="#archetypes"><a href="http://maven.apache.org/guides/introduction/introduction-to-archetypes.html">archetypes</a></a></em> to quickly setup Maven projects, but we will set up the structure manually for this simple tutorial example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> mkdir JettyMavenHelloWorld |
| > cd JettyMavenHelloWorld |
| > mkdir -p src/main/java/org/example</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="creating-helloworld-class">Creating the HelloWorld Class</h5> |
| <div class="paragraph"> |
| <p>Use an editor to create the file <code>src/main/java/org/example/HelloWorld.java</code> with the following contents:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">package org.example; |
| |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.servlet.ServletException; |
| import java.io.IOException; |
| import org.eclipse.jetty.server.Server; |
| import org.eclipse.jetty.server.Request; |
| import org.eclipse.jetty.server.handler.AbstractHandler; |
| |
| public class HelloWorld extends AbstractHandler |
| { |
| public void handle(String target, |
| Request baseRequest, |
| HttpServletRequest request, |
| HttpServletResponse response) |
| throws IOException, ServletException |
| { |
| response.setContentType("text/html;charset=utf-8"); |
| response.setStatus(HttpServletResponse.SC_OK); |
| baseRequest.setHandled(true); |
| response.getWriter().println("<h1>Hello World</h1>"); |
| } |
| |
| public static void main(String[] args) throws Exception |
| { |
| Server server = new Server(8080); |
| server.setHandler(new HelloWorld()); |
| |
| server.start(); |
| server.join(); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="creating-embedded-pom-descriptor">Creating the POM Descriptor</h5> |
| <div class="paragraph"> |
| <p>The <code>pom.xml</code> file declares the project name and its dependencies. |
| Use an editor to create the file <code>pom.xml</code> in the <code>JettyMavenHelloWorld</code> directory with the following contents:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project xmlns="http://maven.apache.org/POM/4.0.0" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
| |
| <modelVersion>4.0.0</modelVersion> |
| <groupId>org.example</groupId> |
| <artifactId>hello-world</artifactId> |
| <version>0.1-SNAPSHOT</version> |
| <packaging>jar</packaging> |
| <name>Jetty HelloWorld</name> |
| |
| <properties> |
| <!-- Adapt this to a version found on |
| https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-maven-plugin/ |
| --> |
| <jettyVersion>10.0.0-SNAPSHOT</jettyVersion> |
| </properties> |
| |
| <dependencies> |
| <dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-server</artifactId> |
| <version>${jettyVersion}</version> |
| </dependency> |
| </dependencies> |
| |
| <build> |
| <plugins> |
| <plugin> |
| <groupId>org.codehaus.mojo</groupId> |
| <artifactId>exec-maven-plugin</artifactId> |
| <version>1.1</version> |
| <executions> |
| <execution><goals><goal>java</goal></goals></execution> |
| </executions> |
| <configuration> |
| <mainClass>org.example.HelloWorld</mainClass> |
| </configuration> |
| </plugin> |
| </plugins> |
| </build> |
| </project></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="buildng-and-running-embedded-helloworld">Building and Running Embedded HelloWorld</h5> |
| <div class="paragraph"> |
| <p>You can now compile and execute the HelloWorld class by using these commands:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> mvn clean compile exec:java</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You can point your browser to <code><a href="http://localhost:8080" class="bare">http://localhost:8080</a></code> to see the <em>Hello World</em> page. |
| You can observe what Maven is doing for you behind the scenes by using the <code>mvn dependency:tree</code> command, which reveals the transitive dependency resolved and downloaded as:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> mvn dependency:tree |
| [INFO] Scanning for projects... |
| ... |
| [INFO] |
| [INFO] ------------------------------------------------------------------------ |
| [INFO] Building Jetty HelloWorld 0.1-SNAPSHOT |
| [INFO] ------------------------------------------------------------------------ |
| [INFO] |
| [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ hello-world --- |
| ... |
| [INFO] org.example:hello-world:jar:0.1-SNAPSHOT |
| [INFO] \- org.eclipse.jetty:jetty-server:jar:9.3.9.v20160517:compile |
| [INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:compile |
| [INFO] +- org.eclipse.jetty:jetty-http:jar:9.3.9.v20160517:compile |
| [INFO] | \- org.eclipse.jetty:jetty-util:jar:9.3.9.v20160517:compile |
| [INFO] \- org.eclipse.jetty:jetty-io:jar:9.3.9.v20160517:compile |
| [INFO] ------------------------------------------------------------------------ |
| [INFO] BUILD SUCCESS |
| [INFO] ------------------------------------------------------------------------ |
| [INFO] Total time: 4.145 s |
| [INFO] Finished at: 2016-08-01T13:46:42-04:00 |
| [INFO] Final Memory: 15M/209M |
| [INFO] ------------------------------------------------------------------------</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="developing-standard-webapp-with-jetty-and-maven">Developing a Standard WebApp with Jetty and Maven</h4> |
| <div class="paragraph"> |
| <p>The previous section demonstrated how to use Maven with an application that embeds Jetty. |
| Now we will examine instead how to develop a standard webapp with Maven and Jetty. |
| First create the Maven structure (you can use the maven webapp archetype instead if you prefer):</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> mkdir JettyMavenHelloWarApp |
| > cd JettyMavenHelloWebApp |
| > mkdir -p src/main/java/org/example |
| > mkdir -p src/main/webapp/WEB-INF</code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="creating-servlet">Creating a Servlet</h5> |
| <div class="paragraph"> |
| <p>Use an editor to create the file <code>src/main/java/org/example/HelloServlet.java</code> with the following contents:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">package org.example; |
| |
| import java.io.IOException; |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServlet; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| public class HelloServlet extends HttpServlet |
| { |
| protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException |
| { |
| response.setContentType("text/html"); |
| response.setStatus(HttpServletResponse.SC_OK); |
| response.getWriter().println("<h1>Hello Servlet</h1>"); |
| response.getWriter().println("session=" + request.getSession(true).getId()); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You need to declare this servlet in the deployment descriptor, so create the file <code>src/main/webapp/WEB-INF/web.xml</code> and add the following contents:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <web-app |
| xmlns="http://xmlns.jcp.org/xml/ns/javaee" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" |
| metadata-complete="false" |
| version="3.1"> |
| |
| <servlet> |
| <servlet-name>Hello</servlet-name> |
| <servlet-class>org.example.HelloServlet</servlet-class> |
| </servlet> |
| <servlet-mapping> |
| <servlet-name>Hello</servlet-name> |
| <url-pattern>/hello/*</url-pattern> |
| </servlet-mapping> |
| |
| </web-app></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="creating-plugin-pom-descriptor">Creating the POM Descriptor</h5> |
| <div class="paragraph"> |
| <p>The <code>pom.xml</code> file declares the project name and its dependencies. |
| Use an editor to create the file <code>pom.xml</code> with the following contents in the <code>JettyMavenHelloWarApp</code> directory, noting particularly the declaration of the <a href="#jetty-maven-plugin">jetty-maven-plugin</a>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project xmlns="http://maven.apache.org/POM/4.0.0" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
| |
| <modelVersion>4.0.0</modelVersion> |
| <groupId>org.example</groupId> |
| <artifactId>hello-world</artifactId> |
| <version>0.1-SNAPSHOT</version> |
| <packaging>war</packaging> |
| <name>Jetty HelloWorld WebApp</name> |
| |
| <properties> |
| <jettyVersion>10.0.0-SNAPSHOT</jettyVersion> |
| </properties> |
| |
| <dependencies> |
| <dependency> |
| <groupId>javax.servlet</groupId> |
| <artifactId>javax.servlet-api</artifactId> |
| <version>3.1.0</version> |
| <scope>provided</scope> |
| </dependency> |
| </dependencies> |
| |
| <build> |
| <plugins> |
| <plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <version>${jettyVersion}</version> |
| </plugin> |
| </plugins> |
| </build> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="building-and-running-web-application">Building and Running the Web Application</h5> |
| <div class="paragraph"> |
| <p>Now you can both build and run the web application without needing to assemble it into a war by using the <a href="#jetty-maven-plugin">jetty-maven-plugin</a> via the command:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> mvn jetty:run</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You can see the static and dynamic content at <code><a href="http://localhost:8080/hello" class="bare">http://localhost:8080/hello</a></code></p> |
| </div> |
| <div class="paragraph"> |
| <p>There are a great deal of configuration options available for the jetty-maven-plugin to help you build and run your webapp. |
| The full reference is at <a href="#jetty-maven-plugin">Configuring the Jetty Maven Plugin</a>.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="building-war-file">Building a WAR file</h5> |
| <div class="paragraph"> |
| <p>You can create a Web Application Archive (WAR) file from the project with the command:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> mvn package</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The resulting war file is in the <code>target</code> directory and may be deployed on any standard servlet server, including <a href="#configuring-deployment">Jetty</a>.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-maven-plugin">Configuring the Jetty Maven Plugin</h3> |
| <div class="paragraph"> |
| <p>The Jetty Maven plugin is useful for rapid development and testing. |
| It can optionally periodically scan your project for changes and automatically redeploy the webapp if any are found. |
| This makes the development cycle more productive by eliminating the build and deploy steps: you use your IDE to make changes to the project, and the running web container automatically picks them up, allowing you to test them straight away.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The plugin has been substantially re-architected in jetty-10 to:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>have less goals</p> |
| </li> |
| <li> |
| <p>make deployment modes (embedded, forked or to a jetty distribution) apply uniformly across all goals</p> |
| </li> |
| <li> |
| <p>simplify configuration options</p> |
| </li> |
| <li> |
| <p>make the purpose and operation of each goal clearer</p> |
| </li> |
| <li> |
| <p>rearchitect with composition rather than inheritance to make future extensions easier</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>There are now only 4 goals to run a webapp in jetty:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#jetty-run-goal">jetty:run</a></p> |
| </li> |
| <li> |
| <p><a href="#jetty-run-war-goal">jetty:run-war</a></p> |
| </li> |
| <li> |
| <p><a href="#jetty-start-goal">jetty:start</a></p> |
| </li> |
| <li> |
| <p><a href="#jetty-start-war-goal">jetty:start-war</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Plus two utility goals:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#jetty-stop-goal">jetty:stop</a></p> |
| </li> |
| <li> |
| <p><a href="#jetty-effective-web-xml-goal">jetty:effective-web-xml</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p><code>jetty:run</code> and <code>jetty:start</code> are alike in that they both run an unassembled webapp in jetty,however <code>jetty:run</code> is designed to be used at the command line, whereas <code>jetty:start</code> is specifically designed to be bound to execution phases in the build lifecycle. |
| <code>jetty:run</code> will pause maven while jetty is running, echoing all output to the console, and then stop maven when jetty exits. |
| <code>jetty:start</code> will not pause maven, will write all its output to a file, and will not stop maven when jetty exits.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>jetty:run-war</code> and <code>jetty:start-war</code> are similar in that they both run an <em>assembled</em> war file in jetty. |
| However, <code>jetty:run-war</code> is designed to be run at the command line, whereas <code>jetty:start-war</code> is specifically designed to be bound to execution phases in the build lifecycle. |
| <code>jetty:run-war</code> will pause maven while jetty is running, echoing all output to the console, and then stop maven when jetty exits. |
| <code>jetty:start-war</code> will not not pause maven, will write all its output to a file, and will not stop maven when jetty exits.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock important"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-important" title="Important"></i> |
| </td> |
| <td class="content"> |
| While the Jetty Maven Plugin can be very useful for development we do not recommend its use in a <em>production capacity</em>. |
| In order for the plugin to work it needs to leverage many internal Maven apis and Maven itself it not a production deployment tool. |
| We recommend either the traditional <a href="../distribution-guide/index.html">distribution</a> deployment approach or using <a href="#advanced-embedding">embedded Jetty</a>. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="sect3"> |
| <h4 id="get-up-and-running">Quick Start: Get Up and Running</h4> |
| <div class="paragraph"> |
| <p>First, add <code>jetty-maven-plugin</code> to your <code>pom.xml</code> definition:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Then, from the same directory as your root <code>pom.xml</code>, type:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">mvn jetty:run</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This starts Jetty and serves up your project on <a href="http://localhost:8080/" class="bare">http://localhost:8080/</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty will continue to run until you stop it. |
| By default, it will not automatically restart your webapp: you can force a redeploy by hitting the <code>Enter</code> key. |
| Set a non-zero <scan> value to have jetty scan your webapp for changes and automatically redeploy.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can terminate the plugin with a <code>ctrl-c</code> in the terminal window where it is running.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| The classpath of the running Jetty instance and its deployed webapp are managed by Maven, and may not be exactly what you expect. |
| For example: a webapp’s dependent jars might be referenced via the local repository, or other projects in the reactor, not the <code>WEB-INF/lib</code> directory. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="supported-goals">Supported Goals</h4> |
| <div class="paragraph"> |
| <p>The goals prefixed with <code>"run"</code> are designed to be used at the <em>command line</em>. |
| They first run a maven build on your project to ensure at least the classes are all built. |
| They then start jetty and pause the maven build process until jetty is manually terminated, at which time the build will also be terminated. |
| Jetty can scan various files in your project for changes and redeploy the webapp as necessary, or you can choose to manually trigger a redeploy if you prefer. |
| All output from jetty is echoed to the console.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The goals prefixed with <code>"start"</code> are designed to be used with <em>build lifecycle bindings in the pom</em>, and <em>not</em> at the command line. |
| No part of your project will be rebuilt by invoking these goals - you should ensure that your bind the execution to a build phase where all necessary parts of your project have been built. |
| Maven will start and terminate jetty at the appropriate points in the build lifecycle, continuing with the build. |
| Jetty will <em>not</em> scan any files in your project for changes, and your webapp will <em>not</em> be redeployed either automatically or manually. |
| Output from jetty is directed to a file in the <code>target</code> directory.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To see a list of all goals supported by the Jetty Maven plugin, do:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">mvn jetty:help</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>To see the detailed list of parameters that can be configured for a particular goal, in addition to its description, do:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">mvn jetty:help -Ddetail=true -Dgoal= <goal name></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="deployment-modes">Deployment Modes</h4> |
| <div class="paragraph"> |
| <p>All of the <code>"run"</code> and <code>"start"</code> goals can deploy your webapp either into the running maven process, or forked into a new child process, or forked into a jetty distribution on disk.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This is controlled by setting the <code>deployMode</code> configuration parameter in the pom, but can also be set by defining the maven property 'jetty.deployMode'.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Embedded</h5> |
| <div class="paragraph"> |
| <p><code>deployMode</code> of <code>EMBED</code>. |
| This is the "classic" jetty maven plugin deployment mode, running in-process with maven. |
| This is the <em>default</em> mode.</p> |
| </div> |
| <div class="paragraph"> |
| <p>These extra configuration parameters are available:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">httpConnector</dt> |
| <dd> |
| <p>Optional. |
| NOTE to configure a https connector, you will need to use xml configuration files instead, setting the <code>jettyXmls</code> parameter. |
| This parameter can only be used to configure a standard http connector. |
| If not specified, Jetty will create a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/ServerConnector.html">ServerConnector</a> instance listening on port 8080. |
| You can change this default port number by using the system property <code>jetty.http.port</code> on the command line, for example, <code>mvn -Djetty.http.port=9999 jetty:run</code>. |
| Alternatively, you can use this configuration element to set up the information for the ServerConnector. |
| The following are the valid configuration sub-elements:</p> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">port</dt> |
| <dd> |
| <p>The port number for the connector to listen on. |
| By default it is 8080.</p> |
| </dd> |
| <dt class="hdlist1">host</dt> |
| <dd> |
| <p>The particular interface for the connector to listen on. |
| By default, all interfaces.</p> |
| </dd> |
| <dt class="hdlist1">name</dt> |
| <dd> |
| <p>The name of the connector, which is useful for <a href="#serving-webapp-from-particular-port">configuring contexts to respond only on particular connectors</a>.</p> |
| </dd> |
| <dt class="hdlist1">idleTimeout</dt> |
| <dd> |
| <p>Maximum idle time for a connection. |
| You could instead configure the connectors in a standard <a href="#jetty-xml-config">jetty xml config file</a> and put its location into the <code>jettyXml</code> parameter. |
| Note that since Jetty 9.0 it is no longer possible to configure a <a href="#maven-config-https">https connector</a> directly in the pom.xml: you need to <a href="#maven-config-https">use jetty xml config files to do it</a>.</p> |
| </dd> |
| </dl> |
| </div> |
| </dd> |
| <dt class="hdlist1">loginServices</dt> |
| <dd> |
| <p>Optional. |
| A list of <code>org.eclipse.jetty.security.LoginService</code> implementations. Note that there is no default realm. |
| If you use a realm in your <code>web.xml</code> you can specify a corresponding realm here. |
| You could instead configure the login services in a jetty xml file and add its location to the <code>jettyXml</code> parameter. |
| See <a href="#configuring-security-settings">Configuring Security</a>.</p> |
| </dd> |
| <dt class="hdlist1">requestLog</dt> |
| <dd> |
| <p>Optional. |
| An implementation of the <code>org.eclipse.jetty.server.RequestLog</code> request log interface. |
| An implementation that respects the NCSA format is available as <code>org.eclipse.jetty.server.NCSARequestLog</code>. |
| There are three other ways to configure the RequestLog:</p> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>In a jetty xml config file, as specified in the <code>jettyXml</code> parameter.</p> |
| </li> |
| <li> |
| <p>In a context xml config file, as specified in the <code>contextXml</code> parameter.</p> |
| </li> |
| <li> |
| <p>In the <code>webApp</code> element.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>See <a href="#configuring-jetty-request-logs">Configuring Request Logs</a> for more information.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">server</dt> |
| <dd> |
| <p>Optional as of Jetty 9.3.1. |
| This would configure an instance of the <a href="https://github.com/eclipse/jetty.project/tree/master/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java"><code>org.eclipse.jetty.server.Server</code></a> for the plugin to use, however it is usually <em>not</em> necessary to configure this, as the plugin will automatically configure one for you. |
| In particular, if you use the <code>jettyXmls</code> element, then you generally <em>don’t</em> want to define this element, as you are probably using the <code>jettyXmls</code> file/s to configure up a Server with a special constructor argument, such as a custom threadpool. |
| If you define both a <code>server</code> element and use a <code>jettyXmls</code> element which points to a config file that has a line like <code><Configure id="Server" class="org.eclipse.jetty.server.Server"></code> then the the xml configuration will override what you configure for the <code>server</code> in the <code>pom.xml</code>.</p> |
| </dd> |
| <dt class="hdlist1">useProvidedScope</dt> |
| <dd> |
| <p>Default value is <code>false</code>. |
| If true, the dependencies with <code><scope>provided</scope></code> are placed onto the <em>container classpath</em>. |
| Be aware that this is <em>not</em> the webapp classpath, as <code>provided</code> indicates that these dependencies would normally be expected to be provided by the container. |
| You should very rarely ever need to use this. |
| See <a href="#container-classpath">Container Classpath vs WebApp Classpath</a>.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Forked</h5> |
| <div class="paragraph"> |
| <p><code>deployMode</code> of <code>FORK</code>. |
| This is similar to the old "jetty:run-forked" goal - a separate process is forked to run your webapp embedded into jetty. |
| These extra configuration parameters are available:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">env</dt> |
| <dd> |
| <p>Optional. |
| Map of key/value pairs to pass as environment to the forked JVM.</p> |
| </dd> |
| <dt class="hdlist1">jvmArgs</dt> |
| <dd> |
| <p>Optional. |
| A string representing arbitrary arguments to pass to the forked JVM.</p> |
| </dd> |
| <dt class="hdlist1">forkWebXml</dt> |
| <dd> |
| <p>Optional. |
| Defaults to <code>target/fork-web.xml</code>. |
| This is the location of a quickstart web xml file that will be <em>generated</em> during the forking of the jetty process. |
| You should not need to set this parameter, but it is available if you wish to control the name and location of that file.</p> |
| </dd> |
| <dt class="hdlist1">useProvidedScope</dt> |
| <dd> |
| <p>Default value is <code>false</code>. |
| If true, the dependencies with <code><scope>provided</scope></code> are placed onto the <em>container classpath</em>. |
| Be aware that this is NOT the webapp classpath, as "provided" indicates that these dependencies would normally be expected to be provided by the container. |
| You should very rarely ever need to use this. |
| See <a href="#container-classpath">Container Classpath vs WebApp Classpath</a>.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>In a jetty distribution</h5> |
| <div class="paragraph"> |
| <p><code>deployMode</code> of <code>DISTRO</code>. |
| This is similar to the old "jetty:run-distro" goal - your webapp is deployed into a dynamically downloaded, unpacked and configured jetty distribution. |
| A separate process is forked to run the distro. |
| These extra configuration parameters are available:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">jettyBase</dt> |
| <dd> |
| <p>Optional. |
| The location of an existing jetty base directory to use to deploy the webapp. |
| The existing base will be copied to the <code>target/</code> directory before the webapp is deployed. |
| If there is no existing jetty base, a fresh one will be made in <code>target/jetty-base</code>.</p> |
| </dd> |
| <dt class="hdlist1">jettyHome</dt> |
| <dd> |
| <p>Optional. |
| The location of an existing unpacked jetty distribution. |
| If one does not exist, a fresh jetty distribution will be downloaded from maven and installed to the <code>target</code> directory.</p> |
| </dd> |
| <dt class="hdlist1">jvmArgs</dt> |
| <dd> |
| <p>Optional. |
| A string representing arguments that should be passed to the jvm of the child process running the distro.</p> |
| </dd> |
| <dt class="hdlist1">modules</dt> |
| <dd> |
| <p>Optional. |
| An array of names of additional jetty modules that the jetty child process will activate. |
| Use this to change the <a href="#container-classpath">container classpath</a> instead of <code>useProvidedScope</code>. |
| These modules are enabled by default: <code>server,http,webapp,deploy</code>.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="common-configuration">Common Configuration</h4> |
| <div class="paragraph"> |
| <p>The following configuration parameters are common to all of the <code>"run-"</code> and <code>"start-"</code> goals:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">deployMode</dt> |
| <dd> |
| <p>One of <code>EMBED</code>, <code>FORK</code> or <code>DISTRO</code>. |
| Default <code>EMBED</code>. |
| Can also be configured by setting the Maven property <code>jetty.deployMode</code>. |
| This parameter determines whether the webapp will run in jetty in-process with Maven, forked into a new process, or deployed into a jetty distribution. |
| See <a href="#deployment-modes">Deployment Modes</a>.</p> |
| </dd> |
| <dt class="hdlist1">jettyXmls</dt> |
| <dd> |
| <p>Optional. |
| A comma separated list of locations of jetty xml files to apply in addition to any plugin configuration parameters. |
| You might use it if you have other webapps, handlers, specific types of connectors etc., to deploy, or if you have other Jetty objects that you cannot configure from the plugin.</p> |
| </dd> |
| <dt class="hdlist1">skip</dt> |
| <dd> |
| <p>Default is false. |
| If true, the execution of the plugin exits. |
| Same as setting the SystemProperty <code>-Djetty.skip</code> on the command line. |
| This is most useful when configuring Jetty for execution during integration testing and you want to skip the tests.</p> |
| </dd> |
| <dt class="hdlist1">excludedGoals</dt> |
| <dd> |
| <p>Optional. |
| A list of Jetty plugin goal names that will cause the plugin to print an informative message and exit. |
| Useful if you want to prevent users from executing goals that you know cannot work with your project.</p> |
| </dd> |
| <dt class="hdlist1">supportedPackagings</dt> |
| <dd> |
| <p>Optional. |
| Defaults to <code>war</code>. |
| This is a list of maven <packaging> types that can work with the jetty plugin. |
| Usually, only <code>war</code> projects are suitable, however, you may configure other types. |
| The plugin will refuse to start if the <packaging> type in the pom is not in list of <code>supportedPackagings</code>.</p> |
| </dd> |
| <dt class="hdlist1">systemProperties</dt> |
| <dd> |
| <p>Optional. |
| Allows you to configure System properties for the execution of the plugin. |
| For more information, see <a href="#setting-system-properties">Setting System Properties</a>.</p> |
| </dd> |
| <dt class="hdlist1">systemPropertiesFile</dt> |
| <dd> |
| <p>Optional. |
| A file containing System properties to set for the execution of the plugin. |
| By default, settings that you make here <strong>do not</strong> override any system properties already set on the command line, by the JVM, or in the POM via <code>systemProperties</code>. |
| Read <a href="#setting-system-properties">Setting System Properties</a> for how to force overrides.</p> |
| </dd> |
| <dt class="hdlist1">jettyProperties</dt> |
| <dd> |
| <p>Optional. |
| A map of property name, value pairs. |
| Allows you to configure standard jetty properties.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="container-classpath">Container Classpath vs WebApp Classpath</h4> |
| <div class="paragraph"> |
| <p>The Servlet Specification makes a strong distinction between the classpath for a webapp, and the classpath of the container. |
| When running in maven, the plugin’s classpath is equivalent to the container classpath. |
| It will make a classpath for the webapp to be deployed comprised of <dependencies> specified in the pom.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If your production environment places specific jars onto the container’s classpath, the equivalent way to do this with maven is to define these as <dependencies> for the <em>plugin</em> itself, not the <em>project</em>. See <a href="http://maven.apache.org/pom.html#Plugins">configuring maven plugins</a>. |
| This is suitable if you are using either <code>EMBED</code> or <code>FORK</code> mode. |
| If you are using <code>DISTRO</code> mode, then you should configure the <code>modules</code> parameter with the names of the jetty modules that place these jars onto the container classpath.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Note that in <code>EMBED</code> or <code>FORK</code> mode, you could also influence the container classpath by setting the <code>useProvidedScope</code> parameter to <code>true</code>: this will place any dependencies with <scope>provided<scope> onto the plugin’s classpath. |
| Use this very cautiously: as the plugin already automatically places most jetty jars onto the classpath, you could wind up with duplicate jars.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-run-goal">jetty:run</h4> |
| <div class="paragraph"> |
| <p>The <code>run</code> goal deploys a webapp that is <em>not</em> first built into a WAR. |
| A virtual webapp is constructed from the project’s sources and its dependencies. |
| It looks for the constituent parts of a webapp in the maven default project locations, although you can override these in the plugin configuration. |
| For example, by default it looks for:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>resources in <code>${project.basedir}/src/main/webapp</code></p> |
| </li> |
| <li> |
| <p>classes in <code>${project.build.outputDirectory}</code></p> |
| </li> |
| <li> |
| <p><code>web.xml</code> in <code>${project.basedir}/src/main/webapp/WEB-INF/</code></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The plugin first runs a maven parallel build to ensure that the classes are built and up-to-date before deployment. |
| If you change the source of a class and your IDE automatically compiles it in the background, the plugin picks up the changed class (note you need to configure a non-zero <code>scan</code> interval for automatic redeployment, otherwise redeployment only occurs if you hit the <code>Enter</code> key).</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the plugin is invoked in a multi-module build, any dependencies that are also in the maven reactor are used from their compiled classes. |
| Prior to jetty-9.4.7 any dependencies needed to be built first.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Once invoked, you can configure the plugin to run continuously, scanning for changes in the project and automatically performing a hot redeploy when necessary. |
| Any changes you make are immediately reflected in the running instance of Jetty, letting you quickly jump from coding to testing, rather than going through the cycle of: code, compile, reassemble, redeploy, test.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The maven build will be paused until jetty exits, at which time maven will also exit.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Stopping jetty is accomplished by typing <code>cntrl-c</code> at the command line.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Output from jetty will be logged to the console.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here is an example, which turns on scanning for changes every ten seconds, and sets the webapp context path to <code>/test</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <configuration> |
| <scan>10</scan> |
| <webApp> |
| <contextPath>/test</contextPath> |
| </webApp> |
| </configuration> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Configuration</h5> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">webApp</dt> |
| <dd> |
| <p>This is an instance of <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/maven/plugin/MavenWebAppContext.html">org.eclipse.jetty.maven.plugin.MavenWebAppContext</a>, which is an extension to the class <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.hml"><code>org.eclipse.jetty.webapp.WebAppContext</code></a>. |
| You can use any of the setter methods on this object to configure your webapp. |
| Here are a few of the most useful ones:</p> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">contextPath</dt> |
| <dd> |
| <p>The context path for your webapp. By default, this is set to <code>/</code>. |
| If using a custom value for this parameter, you should include the leading <code>/</code>, example <code>/mycontext</code>.</p> |
| </dd> |
| <dt class="hdlist1">descriptor</dt> |
| <dd> |
| <p>The path to the <code>web.xml</code> file for your webapp. |
| By default, the plugin will look in <code>src/main/webapp/WEB-INF/web.xml</code>.</p> |
| </dd> |
| <dt class="hdlist1">defaultsDescriptor</dt> |
| <dd> |
| <p>The path to a <code>webdefault.xml</code> file that will be applied to your webapp before the <code>web.xml</code>. |
| If you don’t supply one, Jetty uses a default file baked into the <code>jetty-webapp.jar</code>.</p> |
| </dd> |
| <dt class="hdlist1">overrideDescriptor</dt> |
| <dd> |
| <p>The path to a <code>web.xml</code> file that Jetty applies after reading your <code>web.xml</code>. |
| You can use this to replace or add configuration.</p> |
| </dd> |
| <dt class="hdlist1">jettyEnvXml</dt> |
| <dd> |
| <p>Optional. |
| Location of a <code>jetty-env.xml</code> file, which allows you to make JNDI bindings that satisfy <code>env-entry</code>, <code>resource-env-ref</code>, and <code>resource-ref</code> linkages in the <code>web.xml</code> that are scoped only to the webapp and not shared with other webapps that you might be deploying at the same time (for example, by using a <code>jettyXml</code> file).</p> |
| </dd> |
| <dt class="hdlist1">tempDirectory</dt> |
| <dd> |
| <p>The path to a dir that Jetty can use to expand or copy jars and jsp compiles when your webapp is running. |
| The default is <code>${project.build.outputDirectory}/tmp</code>.</p> |
| </dd> |
| <dt class="hdlist1">baseResource</dt> |
| <dd> |
| <p>The path from which Jetty serves static resources. |
| Defaults to <code>src/main/webapp</code>. |
| If this location does not exist (because, for example, your project does not use static content), then the plugin will synthesize a virtual static resource location of <code>target/webapp-synth</code>.</p> |
| </dd> |
| <dt class="hdlist1">resourceBases</dt> |
| <dd> |
| <p>Use instead of <code>baseResource</code> if you have multiple directories from which you want to serve static content. |
| This is an array of directory locations, either as urls or file paths.</p> |
| </dd> |
| <dt class="hdlist1">baseAppFirst</dt> |
| <dd> |
| <p>Defaults to "true". |
| Controls whether any overlaid wars are added before or after the original base resource(s) of the webapp. |
| See the section on <a href="#using-overlaid-wars">overlaid wars</a> for more information.</p> |
| </dd> |
| <dt class="hdlist1">containerIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to <code>.<strong>/jetty-servlet-api-[<sup>/]</strong>\.jar$|.<strong>javax.servlet.jsp.jstl-[</sup>/]</strong>\.jar|.<strong>taglibs-standard-impl-.</strong>\.jar</code>. |
| This is a pattern that is applied to the names of the jars on the container’s classpath (ie the classpath of the plugin, not that of the webapp) that should be scanned for fragments, tlds, annotations etc. |
| This is analogous to the context attribute <a href="#container-include-jar-pattern">org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</a> that is documented <a href="#container-include-jar-pattern">here</a>. |
| You can define extra patterns of jars that will be included in the scan.</p> |
| </dd> |
| <dt class="hdlist1">webInfIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to matching <em>all</em> of the dependency jars for the webapp (ie the equivalent of WEB-INF/lib). |
| You can make this pattern more restrictive to only match certain jars by using this setter. |
| This is analogous to the context attribute <a href="#web-inf-include-jar-pattern">org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</a> that is documented <a href="#web-inf-include-jar-pattern">here</a>.</p> |
| </dd> |
| </dl> |
| </div> |
| </dd> |
| <dt class="hdlist1">contextXml</dt> |
| <dd> |
| <p>The path to a context xml file that is applied to your webapp AFTER the <code>webApp</code> element.</p> |
| </dd> |
| <dt class="hdlist1">classesDirectory</dt> |
| <dd> |
| <p>Location of your compiled classes for the webapp. |
| You should rarely need to set this parameter. |
| Instead, you should set <code><build><outputDirectory></code> in your <code>pom.xml</code>.</p> |
| </dd> |
| <dt class="hdlist1">testClassesDirectory</dt> |
| <dd> |
| <p>Location of the compiled test classes for your webapp. By default this is <code>${project.build.testOutputDirectory}</code>.</p> |
| </dd> |
| <dt class="hdlist1">useTestScope</dt> |
| <dd> |
| <p>If true, the classes from <code>testClassesDirectory</code> and dependencies of scope "test" are placed first on the classpath. |
| By default this is false.</p> |
| </dd> |
| <dt class="hdlist1">scan</dt> |
| <dd> |
| <p>The pause in seconds between sweeps of the webapp to check for changes and automatically hot redeploy if any are detected. |
| <strong>By default this is 0, which disables hot deployment scanning. Redeployment is by hitting <code>Enter</code> key.</strong> |
| A number greater than 0 enables it.</p> |
| </dd> |
| <dt class="hdlist1">scanTargetPatterns</dt> |
| <dd> |
| <p>Optional. |
| List of extra directories with glob-style include/excludes patterns (see <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-">javadoc</a> for <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-">FileSystem.getPathMatcher</a>) to specify other files to periodically scan for changes.</p> |
| </dd> |
| <dt class="hdlist1">scanClassesPattern</dt> |
| <dd> |
| <p>Optional. |
| Include and exclude patterns that can be applied to the classesDirectory for the purposes of scanning, it does <strong>not</strong> affect the classpath. |
| If a file or directory is excluded by the patterns then a change in that file (or subtree in the case of a directory) is ignored and will not cause the webapp to redeploy. |
| Patterns are specified as a relative path using a glob-like syntax as described in the <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-">javadoc</a> for <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-">FileSystem.getPathMatcher</a>.</p> |
| </dd> |
| <dt class="hdlist1">scanTestClassesPattern</dt> |
| <dd> |
| <p>Optional. |
| Include and exclude patterns that can be applied to the testClassesDirectory for the purposes of scanning, it does <strong>not</strong> affect the classpath. |
| If a file or directory is excluded by the patterns then a change in that file (or subtree in the case of a directory) is ignored and will not cause the webapp to redeploy. |
| Patterns are specified as a relative path using a glob-like syntax as described in the <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-">javadoc</a> for <a href="http://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html#getPathMatcher-java.lang.String-">FileSystem.getPathMatcher</a>.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>See <a href="#deployment-modes">Deployment Modes</a> for other configuration parameters available when using the <code>run</code> goal in EMBED, FORK or DISTRO modes.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example of a pom configuration for the plugin with the <code>run</code> goal:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project> |
| ... |
| <plugins> |
| ... |
| <plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <configuration> |
| <webApp> |
| <contextPath>/</contextPath> |
| <descriptor>${project.basedir}/src/over/here/web.xml</descriptor> |
| <jettyEnvXml>${project.basedir}/src/over/here/jetty-env.xml</jettyEnvXml> |
| <baseResource>${project.basedir}/src/staticfiles</baseResource> |
| </webApp> |
| <classesDirectory>${project.basedir}/somewhere/else</classesDirectory> |
| <scanClassesPattern> |
| <excludes> |
| <exclude>**/Foo.class</exclude> |
| </excludes> |
| </scanClassesPattern> |
| <scanTargetPatterns> |
| <scanTargetPattern> |
| <directory>src/other-resources</directory> |
| <includes> |
| <include>**/*.xml</include> |
| <include>**/*.properties</include> |
| </includes> |
| <excludes> |
| <exclude>**/myspecial.xml</exclude> |
| <exclude>**/myspecial.properties</exclude> |
| </excludes> |
| </scanTargetPattern> |
| </scanTargetPatterns> |
| </configuration> |
| </plugin> |
| </plugins> |
| ... |
| </project></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If, for whatever reason, you cannot run on an unassembled webapp, the goal <code>run-war</code> works on assembled webapps.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-run-war-goal">jetty:run-war</h4> |
| <div class="paragraph"> |
| <p>When invoked at the command line this goal first executes a maven build of your project to the package phase.</p> |
| </div> |
| <div class="paragraph"> |
| <p>By default it then deploys the resultant war to jetty, but you can use this goal instead to deploy <em>any</em> war file by simply setting the <code><webApp><war></code> configuration parameter to its location.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you set a non-zero <code>scan</code>, Jetty watches your <code>pom.xml</code> and the WAR file; if either changes, it redeploys the war. |
| With a zero <code>scan</code> interval, redeployment is manual via hitting the <code>Enter</code> key.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The maven build is held up until jetty exits, which is achieved by typing <code>cntrl-c</code> at the command line.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All jetty output is directed to the console.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Configuration</h5> |
| <div class="paragraph"> |
| <p>Configuration parameters are:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">webApp</dt> |
| <dd> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">war</dt> |
| <dd> |
| <p>The location of the built WAR file. This defaults to <code>${project.build.directory}/${project.build.finalName}.war</code>. |
| You can set it to the location of any pre-built war file.</p> |
| </dd> |
| <dt class="hdlist1">contextPath</dt> |
| <dd> |
| <p>The context path for your webapp. By default, this is set to <code>/</code>. |
| If using a custom value for this parameter, you should include the leading <code>/</code>, example <code>/mycontext</code>.</p> |
| </dd> |
| <dt class="hdlist1">defaultsDescriptor</dt> |
| <dd> |
| <p>The path to a <code>webdefault.xml</code> file that will be applied to your webapp before the <code>web.xml</code>. |
| If you don’t supply one, Jetty uses a default file baked into the <code>jetty-webapp.jar</code>.</p> |
| </dd> |
| <dt class="hdlist1">overrideDescriptor</dt> |
| <dd> |
| <p>The path to a <code>web.xml</code> file that Jetty applies after reading your <code>web.xml</code>. |
| You can use this to replace or add configuration.</p> |
| </dd> |
| <dt class="hdlist1">containerIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to <code>.<strong>/jetty-servlet-api-[<sup>/]</strong>\.jar$|.<strong>javax.servlet.jsp.jstl-[</sup>/]</strong>\.jar|.<strong>taglibs-standard-impl-.</strong>\.jar</code>. |
| This is a pattern that is applied to the names of the jars on the container’s classpath (ie the classpath of the plugin, not that of the webapp) that should be scanned for fragments, tlds, annotations etc. |
| This is analogous to the context attribute <a href="#container-include-jar-pattern">org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</a> that is documented <a href="#container-include-jar-pattern">here</a>. |
| You can define extra patterns of jars that will be included in the scan.</p> |
| </dd> |
| <dt class="hdlist1">webInfIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to matching <em>all</em> of the dependency jars for the webapp (ie the equivalent of WEB-INF/lib). |
| You can make this pattern more restrictive to only match certain jars by using this setter. |
| This is analogous to the context attribute <a href="#web-inf-include-jar-pattern">org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</a> that is documented <a href="#web-inf-include-jar-pattern">here</a>.</p> |
| </dd> |
| <dt class="hdlist1">tempDirectory</dt> |
| <dd> |
| <p>The path to a dir that Jetty can use to expand or copy jars and jsp compiles when your webapp is running. |
| The default is <code>${project.build.outputDirectory}/tmp</code>.</p> |
| </dd> |
| <dt class="hdlist1">contextXml</dt> |
| <dd> |
| <p>The path to a context xml file that is applied to your webapp AFTER the <code>webApp</code> element.</p> |
| </dd> |
| </dl> |
| </div> |
| </dd> |
| <dt class="hdlist1">scan</dt> |
| <dd> |
| <p>The pause in seconds between sweeps of the webapp to check for changes and automatically hot redeploy if any are detected. |
| <strong>By default this is 0, which disables hot deployment scanning. Redeployment is by hitting <code>Enter</code> key.</strong> |
| A number greater than 0 enables it.</p> |
| </dd> |
| <dt class="hdlist1">scanTargetPatterns</dt> |
| <dd> |
| <p>Optional. |
| List of directories with ant-style include/excludes patterns to specify other files to periodically scan for changes.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>See <a href="#deployment-modes">Deployment Modes</a> for other configuration parameters available when using the <code>run-war</code> goal in EMBED, FORK or DISTRO modes.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-start-goal">jetty:start</h4> |
| <div class="paragraph"> |
| <p>This is similar to the <code>jetty:run</code> goal, however it is <em>not</em> designed to be run from the command line and does <em>not</em> first execute the build up until the <code>test-compile</code> phase to ensure that all necessary classes and files of the webapp have been generated. |
| It will <em>not</em> scan your project for changes and restart your webapp. |
| It does <em>not</em> pause maven until jetty is stopped.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Instead, it is designed to be used with build phase bindings in your pom. |
| For example to you can have maven start your webapp at the beginning of your tests and stop at the end.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the plugin is invoked as part of a multi-module build, any dependencies that are also in the maven reactor are used from their compiled classes. |
| Prior to jetty-9.4.7 any dependencies needed to be built first.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example of using the <code>pre-integration-test</code> and <code>post-integration-test</code> Maven build phases to trigger the execution and termination of Jetty:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <configuration> |
| <scan>10</scan> |
| <stopKey>foo</stopKey> |
| <stopPort>9999</stopPort> |
| </configuration> |
| <executions> |
| <execution> |
| <id>start-jetty</id> |
| <phase>pre-integration-test</phase> |
| <goals> |
| <goal>start</goal> |
| </goals> |
| <configuration> |
| <scan>0</scan> |
| </configuration> |
| </execution> |
| <execution> |
| <id>stop-jetty</id> |
| <phase>post-integration-test</phase> |
| <goals> |
| <goal>stop</goal> |
| </goals> |
| </execution> |
| </executions> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This goal will generate output from jetty into the <code>target/jetty-start.out</code> file.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Configuration</h5> |
| <div class="paragraph"> |
| <p>These configuration parameters are available:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">webApp</dt> |
| <dd> |
| <p>This is an instance of <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/maven/plugin/MavenWebAppContext.html">org.eclipse.jetty.maven.plugin.MavenWebAppContext</a>, which is an extension to the class <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.hml"><code>org.eclipse.jetty.webapp.WebAppContext</code></a>. |
| You can use any of the setter methods on this object to configure your webapp. |
| Here are a few of the most useful ones:</p> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">contextPath</dt> |
| <dd> |
| <p>The context path for your webapp. By default, this is set to <code>/</code>. |
| If using a custom value for this parameter, you should include the leading <code>/</code>, example <code>/mycontext</code>.</p> |
| </dd> |
| <dt class="hdlist1">descriptor</dt> |
| <dd> |
| <p>The path to the <code>web.xml</code> file for your webapp. |
| The default is <code>src/main/webapp/WEB-INF/web.xml</code>.</p> |
| </dd> |
| <dt class="hdlist1">defaultsDescriptor</dt> |
| <dd> |
| <p>The path to a <code>webdefault.xml</code> file that will be applied to your webapp before the <code>web.xml</code>. |
| If you don’t supply one, Jetty uses a default file baked into the <code>jetty-webapp.jar</code>.</p> |
| </dd> |
| <dt class="hdlist1">overrideDescriptor</dt> |
| <dd> |
| <p>The path to a <code>web.xml</code> file that Jetty applies after reading your <code>web.xml</code>. |
| You can use this to replace or add configuration.</p> |
| </dd> |
| <dt class="hdlist1">jettyEnvXml</dt> |
| <dd> |
| <p>Optional. |
| Location of a <code>jetty-env.xml</code> file, which allows you to make JNDI bindings that satisfy <code>env-entry</code>, <code>resource-env-ref</code>, and <code>resource-ref</code> linkages in the <code>web.xml</code> that are scoped only to the webapp and not shared with other webapps that you might be deploying at the same time (for example, by using a <code>jettyXml</code> file).</p> |
| </dd> |
| <dt class="hdlist1">tempDirectory</dt> |
| <dd> |
| <p>The path to a dir that Jetty can use to expand or copy jars and jsp compiles when your webapp is running. |
| The default is <code>${project.build.outputDirectory}/tmp</code>.</p> |
| </dd> |
| <dt class="hdlist1">baseResource</dt> |
| <dd> |
| <p>The path from which Jetty serves static resources. |
| Defaults to <code>src/main/webapp</code>.</p> |
| </dd> |
| <dt class="hdlist1">resourceBases</dt> |
| <dd> |
| <p>Use instead of <code>baseResource</code> if you have multiple directories from which you want to serve static content. |
| This is an array of directory names.</p> |
| </dd> |
| <dt class="hdlist1">baseAppFirst</dt> |
| <dd> |
| <p>Defaults to "true". |
| Controls whether any overlaid wars are added before or after the original base resource(s) of the webapp. |
| See the section on <a href="#using-overlaid-wars">overlaid wars</a> for more information.</p> |
| </dd> |
| <dt class="hdlist1">containerIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to <code>.<strong>/jetty-servlet-api-[<sup>/]</strong>\.jar$|.<strong>javax.servlet.jsp.jstl-[</sup>/]</strong>\.jar|.<strong>taglibs-standard-impl-.</strong>\.jar</code>. |
| This is a pattern that is applied to the names of the jars on the container’s classpath (ie the classpath of the plugin, not that of the webapp) that should be scanned for fragments, tlds, annotations etc. |
| This is analogous to the context attribute <a href="#container-include-jar-pattern">org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</a> that is documented <a href="#container-include-jar-pattern">here</a>. |
| You can define extra patterns of jars that will be included in the scan.</p> |
| </dd> |
| <dt class="hdlist1">webInfIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to matching <em>all</em> of the dependency jars for the webapp (ie the equivalent of WEB-INF/lib). |
| You can make this pattern more restrictive to only match certain jars by using this setter. |
| This is analogous to the context attribute <a href="#web-inf-include-jar-pattern">org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</a> that is documented <a href="#web-inf-include-jar-pattern">here</a>.</p> |
| </dd> |
| </dl> |
| </div> |
| </dd> |
| <dt class="hdlist1">contextXml</dt> |
| <dd> |
| <p>The path to a context xml file that is applied to your webapp AFTER the <code>webApp</code> element.</p> |
| </dd> |
| <dt class="hdlist1">classesDirectory</dt> |
| <dd> |
| <p>Location of your compiled classes for the webapp. |
| You should rarely need to set this parameter. |
| Instead, you should set <code>build outputDirectory</code> in your <code>pom.xml</code>.</p> |
| </dd> |
| <dt class="hdlist1">testClassesDirectory</dt> |
| <dd> |
| <p>Location of the compiled test classes for your webapp. By default this is <code>${project.build.testOutputDirectory}</code>.</p> |
| </dd> |
| <dt class="hdlist1">useTestScope</dt> |
| <dd> |
| <p>If true, the classes from <code>testClassesDirectory</code> and dependencies of scope "test" are placed first on the classpath. |
| By default this is false.</p> |
| </dd> |
| <dt class="hdlist1">stopPort</dt> |
| <dd> |
| <p>Optional. |
| Port to listen on for stop commands. |
| Useful to use in conjunction with the <a href="#jetty-stop-goal">stop</a> and <a href="#jetty-start-goal">start</a> goals.</p> |
| </dd> |
| <dt class="hdlist1">stopKey</dt> |
| <dd> |
| <p>Optional. |
| Used in conjunction with stopPort for stopping jetty. |
| Useful to use in conjunction with the <a href="#jetty-stop-goal">stop</a> and <a href="#jetty-start-goal">start</a> goals.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>These additional configuration parameters are available when running in <code>FORK</code> or <code>DISTRO</code> mode:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">maxChildStartChecks</dt> |
| <dd> |
| <p>Default is <code>10</code>. |
| This is maximum number of times the parent process checks to see if the forked jetty process has started correctly</p> |
| </dd> |
| <dt class="hdlist1">maxChildStartCheckMs</dt> |
| <dd> |
| <p>Default is <code>200</code>. |
| This is the time in milliseconds between checks on the startup of the forked jetty process.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-start-war-goal">jetty:start-war</h4> |
| <div class="paragraph"> |
| <p>Similarly to the <code>jetty:start</code> goal, <code>jetty:start-war</code> is designed to be bound to build lifecycle phases in your pom.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It will <em>not</em> scan your project for changes and restart your webapp. |
| It does <em>not</em> pause maven until jetty is stopped.</p> |
| </div> |
| <div class="paragraph"> |
| <p>By default, if your pom is for a webapp project, it will deploy the war file for the project to jetty. |
| However, like the <code>jetty:run-war</code> project, you can nominate any war file to deploy by defining its location in the <code><webApp><war></code> parameter.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If the plugin is invoked as part of a multi-module build, any dependencies that are also in the maven reactor are used from their compiled classes. |
| Prior to jetty-9.4.7 any dependencies needed to be built first.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This goal will generate output from jetty into the <code>target/jetty-start-war.out</code> file.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Configuration</h5> |
| <div class="paragraph"> |
| <p>These configuration parameters are available:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">webApp</dt> |
| <dd> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">war</dt> |
| <dd> |
| <p>The location of the built WAR file. This defaults to <code>${project.build.directory}/${project.build.finalName}.war</code>. |
| You can set it to the location of any pre-built war file.</p> |
| </dd> |
| <dt class="hdlist1">contextPath</dt> |
| <dd> |
| <p>The context path for your webapp. By default, this is set to <code>/</code>. |
| If using a custom value for this parameter, you should include the leading <code>/</code>, example <code>/mycontext</code>.</p> |
| </dd> |
| <dt class="hdlist1">defaultsDescriptor</dt> |
| <dd> |
| <p>The path to a <code>webdefault.xml</code> file that will be applied to your webapp before the <code>web.xml</code>. |
| If you don’t supply one, Jetty uses a default file baked into the <code>jetty-webapp.jar</code>.</p> |
| </dd> |
| <dt class="hdlist1">overrideDescriptor</dt> |
| <dd> |
| <p>The path to a <code>web.xml</code> file that Jetty applies after reading your <code>web.xml</code>. |
| You can use this to replace or add configuration.</p> |
| </dd> |
| <dt class="hdlist1">containerIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to <code>.<strong>/jetty-servlet-api-[<sup>/]</strong>\.jar$|.<strong>javax.servlet.jsp.jstl-[</sup>/]</strong>\.jar|.<strong>taglibs-standard-impl-.</strong>\.jar</code>. |
| This is a pattern that is applied to the names of the jars on the container’s classpath (ie the classpath of the plugin, not that of the webapp) that should be scanned for fragments, tlds, annotations etc. |
| This is analogous to the context attribute <a href="#container-include-jar-pattern">org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</a> that is documented <a href="#container-include-jar-pattern">here</a>. |
| You can define extra patterns of jars that will be included in the scan.</p> |
| </dd> |
| <dt class="hdlist1">webInfIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to matching <em>all</em> of the dependency jars for the webapp (ie the equivalent of WEB-INF/lib). |
| You can make this pattern more restrictive to only match certain jars by using this setter. |
| This is analogous to the context attribute <a href="#web-inf-include-jar-pattern">org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</a> that is documented <a href="#web-inf-include-jar-pattern">here</a>.</p> |
| </dd> |
| <dt class="hdlist1">tempDirectory</dt> |
| <dd> |
| <p>The path to a dir that Jetty can use to expand or copy jars and jsp compiles when your webapp is running. |
| The default is <code>${project.build.outputDirectory}/tmp</code>.</p> |
| </dd> |
| <dt class="hdlist1">contextXml</dt> |
| <dd> |
| <p>The path to a context xml file that is applied to your webapp AFTER the <code>webApp</code> element.</p> |
| </dd> |
| </dl> |
| </div> |
| </dd> |
| <dt class="hdlist1">stopPort</dt> |
| <dd> |
| <p>Optional. |
| Port to listen on for stop commands. |
| Useful to use in conjunction with the <a href="#jetty-stop-goal">stop</a>.</p> |
| </dd> |
| <dt class="hdlist1">stopKey</dt> |
| <dd> |
| <p>Optional. |
| Used in conjunction with stopPort for stopping jetty. |
| Useful to use in conjunction with the <a href="#jetty-stop-goal">stop</a>.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>These additional configuration parameters are available when running in FORK or DISTRO mode:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">maxChildStartChecks</dt> |
| <dd> |
| <p>Default is <code>10</code>. |
| This is maximum number of times the parent process checks to see if the forked jetty process has started correctly</p> |
| </dd> |
| <dt class="hdlist1">maxChildStartCheckMs</dt> |
| <dd> |
| <p>Default is <code>200</code>. |
| This is the time in milliseconds between checks on the startup of the forked jetty process.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-stop-goal">jetty:stop</h4> |
| <div class="paragraph"> |
| <p>The stop goal stops a FORK or DISTRO mode running instance of Jetty. |
| To use it, you need to configure the plugin with a special port number and key. |
| That same port number and key will also be used by the other goals that start jetty.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Configuration</h5> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">stopPort</dt> |
| <dd> |
| <p>A port number for Jetty to listen on to receive a stop command to cause it to shutdown.</p> |
| </dd> |
| <dt class="hdlist1">stopKey</dt> |
| <dd> |
| <p>A string value sent to the <code>stopPort</code> to validate the stop command.</p> |
| </dd> |
| <dt class="hdlist1">stopWait</dt> |
| <dd> |
| <p>The maximum time in seconds that the plugin will wait for confirmation that Jetty has stopped. |
| If false or not specified, the plugin does not wait for confirmation but exits after issuing the stop command.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s a configuration example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <configuration> |
| <stopPort>9966</stopPort> |
| <stopKey>foo</stopKey> |
| <stopWait>10</stopWait> |
| </configuration> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Then, while Jetty is running (in another window), type:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">mvn jetty:stop</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>stopPort</code> must be free on the machine you are running on. |
| If this is not the case, you will get an "Address already in use" error message after the "Started ServerConnector …​" message.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-effective-web-xml-goal">jetty:effective-web-xml</h4> |
| <div class="paragraph"> |
| <p>This goal calculates a synthetic <code>web.xml</code> (the "effective web.xml") according to the rules of the Servlet Specification taking into account all sources of discoverable configuration of web components in your application: descriptors (<code>webdefault.xml</code>, <code>web.xml</code>, <code>web-fragment.xml`s, `web-override.xml</code>) and discovered annotations (<code>@WebServlet</code>, <code>@WebFilter</code>, <code>@WebListener</code>). |
| No programmatic declarations of servlets, filters and listeners can be taken into account.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can calculate the effective web.xml for any pre-built war file by setting the <code><webApp><war></code> parameter, or you can calculate it for the unassembled webapp by setting all of the usual <code><webApp></code> parameters as for <code>jetty:run</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Other useful information about your webapp that is produced as part of the analysis is also stored as context parameters in the effective-web.xml. |
| The effective-web.xml can be used in conjunction with the <a href="#quickstart-webapp">Quickstart</a> feature to quickly start your webapp (note that Quickstart is not appropriate for the mvn jetty goals).</p> |
| </div> |
| <div class="paragraph"> |
| <p>The effective web.xml from these combined sources is generated into a file, which by default is <code>target/effective-web.xml</code>, but can be changed by setting the <code>effectiveWebXml</code> configuration parameter.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Configuration</h5> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">effectiveWebXml</dt> |
| <dd> |
| <p>The full path name of a file into which you would like the effective web xml generated.</p> |
| </dd> |
| <dt class="hdlist1">webApp</dt> |
| <dd> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">war</dt> |
| <dd> |
| <p>The location of the built WAR file. This defaults to <code>${project.build.directory}/${project.build.finalName}.war</code>. |
| You can set it to the location of any pre-built war file. |
| Or you can leave it blank and set up the other <code>webApp</code> parameters as per <a href="#jetty-run-goal">jetty:run</a>, as well as the <code>webAppSourceDirectory</code>, <code>classes</code> and <code>testClasses</code> parameters.</p> |
| </dd> |
| <dt class="hdlist1">contextPath</dt> |
| <dd> |
| <p>The context path for your webapp. By default, this is set to <code>/</code>. |
| If using a custom value for this parameter, you should include the leading <code>/</code>, example <code>/mycontext</code>.</p> |
| </dd> |
| <dt class="hdlist1">defaultsDescriptor</dt> |
| <dd> |
| <p>The path to a <code>webdefault.xml</code> file that will be applied to your webapp before the <code>web.xml</code>. |
| If you don’t supply one, Jetty uses a default file baked into the <code>jetty-webapp.jar</code>.</p> |
| </dd> |
| <dt class="hdlist1">overrideDescriptor</dt> |
| <dd> |
| <p>The path to a <code>web.xml</code> file that Jetty applies after reading your <code>web.xml</code>. |
| You can use this to replace or add configuration.</p> |
| </dd> |
| <dt class="hdlist1">containerIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to <code>.<strong>/jetty-servlet-api-[<sup>/]</strong>\.jar$|.<strong>javax.servlet.jsp.jstl-[</sup>/]</strong>\.jar|.<strong>taglibs-standard-impl-.</strong>\.jar</code>. |
| This is a pattern that is applied to the names of the jars on the container’s classpath (ie the classpath of the plugin, not that of the webapp) that should be scanned for fragments, tlds, annotations etc. |
| This is analogous to the context attribute <a href="#container-include-jar-pattern">org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</a> that is documented <a href="#container-include-jar-pattern">here</a>. |
| You can define extra patterns of jars that will be included in the scan.</p> |
| </dd> |
| <dt class="hdlist1">webInfIncludeJarPattern</dt> |
| <dd> |
| <p>Defaults to matching <em>all</em> of the dependency jars for the webapp (ie the equivalent of WEB-INF/lib). |
| You can make this pattern more restrictive to only match certain jars by using this setter. |
| This is analogous to the context attribute <a href="#web-inf-include-jar-pattern">org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</a> that is documented <a href="#web-inf-include-jar-pattern">here</a>.</p> |
| </dd> |
| <dt class="hdlist1">tempDirectory</dt> |
| <dd> |
| <p>The path to a dir that Jetty can use to expand or copy jars and jsp compiles when your webapp is running. |
| The default is <code>${project.build.outputDirectory}/tmp</code>.</p> |
| </dd> |
| <dt class="hdlist1">contextXml</dt> |
| <dd> |
| <p>The path to a context xml file that is applied to your webapp AFTER the <code>webApp</code> element.</p> |
| </dd> |
| </dl> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>You can also generate the origin of each element into the effective web.xml file. |
| The origin is either a descriptor eg web.xml,web-fragment.xml,override-web.xml file, or an annotation eg @WebServlet. |
| Some examples of elements with origin attribute information are:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><listener origin="DefaultsDescriptor(file:///path/to/distro/etc/webdefault.xml):21"> |
| <listener origin="WebDescriptor(file:///path/to/base/webapps/test-spec/WEB-INF/web.xml):22"> |
| <servlet-class origin="FragmentDescriptor(jar:file:///path/to/base/webapps/test-spec/WEB-INF/lib/test-web-fragment.jar!/META-INF/web-fragment.xml):23"> |
| <servlet-class origin="@WebServlet(com.acme.test.TestServlet):24"></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>To generate origin information, use the following configuration parameters on the <code>webApp</code> element:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">originAttribute</dt> |
| <dd> |
| <p>The name of the attribute that will contain the origin. |
| By default it is <code>origin</code>.</p> |
| </dd> |
| <dt class="hdlist1">generateOrigin</dt> |
| <dd> |
| <p>False by default. If true, will force the generation of the originAttribute onto each element.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="using-overlaid-wars">Using Overlaid wars</h4> |
| <div class="paragraph"> |
| <p>If your webapp depends on other war files, the <a href="#jetty-run-goal">jetty:run</a> and <a href="#jetty-start-goal">jetty:start</a> goals are able to merge resources from all of them. |
| It can do so based on the settings of the <a href="http://maven.apache.org/plugins/maven-war-plugin/">maven-war-plugin</a>, or if your project does not use the <a href="http://maven.apache.org/plugins/maven-war-plugin/">maven-war-plugin</a> to handle the overlays, it can fall back to a simple algorithm to determine the ordering of resources.</p> |
| </div> |
| <div class="sect4"> |
| <h5>With maven-war-plugin</h5> |
| <div class="paragraph"> |
| <p>The maven-war-plugin has a rich set of capabilities for merging resources. |
| The <code>jetty:run</code> and <code>jetty:start</code> goals are able to interpret most of them and apply them during execution of your unassembled webapp. |
| This is probably best seen by looking at a concrete example.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Suppose your webapp depends on the following wars:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>com.acme</groupId> |
| <artifactId>X</artifactId> |
| <type>war</type> |
| </dependency> |
| <dependency> |
| <groupId>com.acme</groupId> |
| <artifactId>Y</artifactId> |
| <type>war</type> |
| </dependency></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Containing:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-text" data-lang="text">WebAppX: |
| |
| /foo.jsp |
| /bar.jsp |
| /WEB-INF/web.xml |
| |
| WebAppY: |
| |
| /bar.jsp |
| /baz.jsp |
| /WEB-INF/web.xml |
| /WEB-INF/special.xml</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>They are configured for the <a href="http://maven.apache.org/plugins/maven-war-plugin/overlays.html">maven-war-plugin</a>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-war-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <configuration> |
| <overlays> |
| <overlay> |
| <groupId>com.acme</groupId> |
| <artifactId>X</artifactId> |
| <excludes> |
| <exclude>bar.jsp</exclude> |
| </excludes> |
| </overlay> |
| <overlay> |
| <groupId>com.acme</groupId> |
| <artifactId>Y</artifactId> |
| <excludes> |
| <exclude>baz.jsp</exclude> |
| </excludes> |
| </overlay> |
| <overlay> |
| </overlay> |
| </overlays> |
| </configuration> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Then executing jetty:run would yield the following ordering of resources: <code>com.acme.X.war : com.acme.Y.war: ${project.basedir}/src/main/webapp</code>. |
| Note that the current project’s resources are placed last in the ordering due to the empty <overlay/> element in the maven-war-plugin. |
| You can either use that, or specify the <code><baseAppFirst>false</baseAppFirst></code> parameter to the jetty-maven-plugin.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Moreover, due to the <code>exclusions</code> specified above, a request for the resource ` bar.jsp` would only be satisfied from <code>com.acme.Y.war.</code> |
| Similarly as <code>baz.jsp</code> is excluded, a request for it would result in a 404 error.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Without maven-war-plugin</h5> |
| <div class="paragraph"> |
| <p>The algorithm is fairly simple, is based on the ordering of declaration of the dependent wars, and does not support exclusions. |
| The configuration parameter <code><baseAppFirst></code> (see for example <a href="#jetty-run-goal">jetty:run</a> for more information) can be used to control whether your webapp’s resources are placed first or last on the resource path at runtime.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, suppose our webapp depends on these two wars:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>com.acme</groupId> |
| <artifactId>X</artifactId> |
| <type>war</type> |
| </dependency> |
| <dependency> |
| <groupId>com.acme</groupId> |
| <artifactId>Y</artifactId> |
| <type>war</type> |
| </dependency></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Suppose the webapps contain:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-text" data-lang="text">WebAppX: |
| |
| /foo.jsp |
| /bar.jsp |
| /WEB-INF/web.xml |
| |
| WebAppY: |
| |
| /bar.jsp |
| /baz.jsp |
| /WEB-INF/web.xml |
| /WEB-INF/special.xml</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Then our webapp has available these additional resources:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-text" data-lang="text">/foo.jsp (X) |
| /bar.jsp (X) |
| /baz.jsp (Y) |
| /WEB-INF/web.xml (X) |
| /WEB-INF/special.xml (Y)</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="configuring-security-settings">Configuring Security Settings</h4> |
| <div class="paragraph"> |
| <p>You can configure LoginServices in the plugin. |
| Here’s an example of setting up the HashLoginService for a webapp:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <configuration> |
| <scan>10</scan> |
| <webApp> |
| <contextPath>/test</contextPath> |
| </webApp> |
| <loginServices> |
| <loginService implementation="org.eclipse.jetty.security.HashLoginService"> |
| <name>Test Realm</name> |
| <config>${project.basedir}/src/etc/realm.properties</config> |
| </loginService> |
| </loginServices> |
| </configuration> |
| </plugin></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="using-multiple-webapp-root-directories">Using Multiple Webapp Root Directories</h4> |
| <div class="paragraph"> |
| <p>If you have external resources that you want to incorporate in the execution of a webapp, but which are not assembled into war files, you can’t use the overlaid wars method described above, but you can tell Jetty the directories in which these external resources are located. |
| At runtime, when Jetty receives a request for a resource, it searches all the locations to retrieve the resource. |
| It’s a lot like the overlaid war situation, but without the war.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here is a configuration example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><configuration> |
| <webApp> |
| <contextPath>/${build.finalName}</contextPath> |
| <baseResource implementation="org.eclipse.jetty.util.resource.ResourceCollection"> |
| <resourcesAsCSV>src/main/webapp,/home/johndoe/path/to/my/other/source,/yet/another/folder</resourcesAsCSV> |
| </baseResource> |
| </webApp> |
| </configuration></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="running-more-than-one-webapp">Running More than One Webapp</h4> |
| <div class="sect4"> |
| <h5>With jetty:run</h5> |
| <div class="paragraph"> |
| <p>You can use either a <code>jetty.xml</code> file to configure extra (pre-compiled) webapps that you want to deploy, or you can use the <code><contextHandlers></code> configuration element to do so. |
| If you want to deploy webapp A, and webapps B and C in the same Jetty instance:</p> |
| </div> |
| <div class="paragraph"> |
| <p>Putting the configuration in webapp A’s <code>pom.xml</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <configuration> |
| <scan>10</scan> |
| <webApp> |
| <contextPath>/test</contextPath> |
| </webApp> |
| <contextHandlers> |
| <contextHandler implementation="org.eclipse.jetty.maven.plugin.MavenWebAppContext"> |
| <war>${project.basedir}../../B.war</war> |
| <contextPath>/B</contextPath> |
| </contextHandler> |
| <contextHandler implementation="org.eclipse.jetty.maven.plugin.MavenWebAppContext"> |
| <war>${project.basedir}../../C.war</war> |
| <contextPath>/C</contextPath> |
| </contextHandler> |
| </contextHandlers> |
| </configuration> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock important"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-important" title="Important"></i> |
| </td> |
| <td class="content"> |
| If the <code>ContextHandler</code> you are deploying is a webapp, it is <strong>essential</strong> that you use an <code>org.eclipse.jetty.maven.plugin.MavenWebAppContext</code> instance rather than a standard <code>org.eclipse.jetty.webapp.WebAppContext</code> instance. |
| Only the former will allow the webapp to function correctly in the maven environment. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>Alternatively, add a <code>jetty.xml</code> file to webapp A. |
| Copy the <code>jetty.xml</code> file from the Jetty distribution, and then add WebAppContexts for the other 2 webapps:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Ref refid="Contexts"> |
| <Call name="addHandler"> |
| <Arg> |
| <New class="org.eclipse.jetty.maven.plugin.MavenWebAppContext"> |
| <Set name="contextPath">/B</Set> |
| <Set name="war">../../B.war</Set> |
| </New> |
| </Arg> |
| </Call> |
| <Call> |
| <Arg> |
| <New class="org.eclipse.jetty.maven.plugin.MavenWebAppContext"> |
| <Set name="contextPath">/C</Set> |
| <Set name="war">../../C.war</Set> |
| </New> |
| </Arg> |
| </Call> |
| </Ref></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Then configure the location of this <code>jetty.xml</code> file into webapp A’s jetty plugin:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <configuration> |
| <scan>10</scan> |
| <webApp> |
| <contextPath>/test</contextPath> |
| </webApp> |
| <jettyXml>src/main/etc/jetty.xml</jettyXml> |
| </configuration> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>For either of these solutions, the other webapps must already have been built, and they are not automatically monitored for changes. |
| You can refer either to the packed WAR file of the pre-built webapps or to their expanded equivalents.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="setting-system-properties">Setting System Properties</h4> |
| <div class="paragraph"> |
| <p>You can specify property name/value pairs that Jetty sets as System properties for the execution of the plugin. |
| This feature is useful to tidy up the command line and save a lot of typing.</p> |
| </div> |
| <div class="paragraph"> |
| <p>However, <strong>sometimes it is not possible to use this feature to set System properties</strong> - sometimes the software component using the System property is already initialized by the time that maven runs (in which case you will need to provide the System property on the command line), or by the time that Jetty runs. |
| In the latter case, you can use the <a href="http://www.mojohaus.org/">maven properties plugin</a> to define the system properties instead. Here’s an example that configures the logback logging system as the Jetty logger:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.codehaus.mojo</groupId> |
| <artifactId>properties-maven-plugin</artifactId> |
| <version>1.0-alpha-2</version> |
| <executions> |
| <execution> |
| <goals> |
| <goal>set-system-properties</goal> |
| </goals> |
| <configuration> |
| <properties> |
| <property> |
| <name>logback.configurationFile</name> |
| <value>${project.baseUri}/resources/logback.xml</value> |
| </property> |
| </properties> |
| </configuration> |
| </execution> |
| </executions> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| If a System property is already set (for example, from the command line or by the JVM itself), then by default these configured properties <strong>DO NOT</strong> override them. |
| However, they can override system properties set from a file instead, see <a href="#specifying-properties-in-file">specifying system properties in a file</a>. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="sect4"> |
| <h5 id="specifying-properties-in-pom">Specifying System Properties in the POM</h5> |
| <div class="paragraph"> |
| <p>Here’s an example of how to specify System properties in the POM:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <configuration> |
| <systemProperties> |
| <fooprop>222</fooprop> |
| </systemProperties> |
| <webApp> |
| <contextPath>/test</contextPath> |
| </webApp> |
| </configuration> |
| </plugin></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="specifying-properties-in-file">Specifying System Properties in a File</h5> |
| <div class="paragraph"> |
| <p>You can also specify your System properties in a file. |
| System properties you specify in this way <strong>do not</strong> override System properties that set on the command line, by the JVM, or directly in the POM via <code>systemProperties</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Suppose we have a file called <code>mysys.props</code> which contains the following:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-text" data-lang="text">fooprop=222</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This can be configured on the plugin like so:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-maven-plugin</artifactId> |
| <configuration> |
| <systemPropertiesFile>${project.basedir}/mysys.props</systemPropertiesFile> |
| <webApp> |
| <contextPath>/test</contextPath> |
| </webApp> |
| </configuration> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You can instead specify the file by setting the System property <code>jetty.systemPropertiesFile</code> on the command line.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-maven-scanning">Files Scanned by the Jetty Maven Plugin</h3> |
| <div class="paragraph"> |
| <p>If you set a non zero <code>scanIntervalSeconds</code> <a href="#jetty-maven-plugin">configuration parameter</a>, the <code>jetty-maven-plugin</code> will scan certain files for changes, and redeploy the webapp if necessary. |
| The files that are scanned depend on the goal being executed.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="scanner-matrix">Scanner Matrix</h4> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 66.6667%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Goal</th> |
| <th class="tableblock halign-left valign-top">Files</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#jetty-run-goal">jetty:run</a></p></td> |
| <td class="tableblock halign-left valign-top"><div class="content"><div class="ulist"> |
| <ul> |
| <li> |
| <p>pom.xml</p> |
| </li> |
| <li> |
| <p><dependencies></p> |
| </li> |
| <li> |
| <p><classesDirectory></p> |
| </li> |
| <li> |
| <p><testClassesDirectory></p> |
| </li> |
| <li> |
| <p><webApp><descriptor/></webApp> or src/main/webapp/WEB-INF/web.xml</p> |
| </li> |
| <li> |
| <p><webApp><jettyEnvXml/></webApp> or src/main/webapp/WEB-INF/jetty-web.xml</p> |
| </li> |
| <li> |
| <p><webApp><baseResource>/WEB-INF/jetty-web.xml</p> |
| </li> |
| <li> |
| <p><scanTargets></p> |
| </li> |
| <li> |
| <p><scanTargetPatterns></p> |
| </li> |
| <li> |
| <p>any <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setDefaultsDescriptor%28java.lang.String%29">defaultsDescriptor</a> for the webapp</p> |
| </li> |
| <li> |
| <p>any <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setOverrideDescriptor%28java.lang.String%29">overrideDescriptor</a> for the webapp</p> |
| </li> |
| <li> |
| <p>any dependencies that are wars or zips</p> |
| </li> |
| </ul> |
| </div></div></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#running-assembled-webapp-as-war">jetty:run-war</a></p></td> |
| <td class="tableblock halign-left valign-top"><div class="content"><div class="ulist"> |
| <ul> |
| <li> |
| <p>pom.xml</p> |
| </li> |
| <li> |
| <p><war></p> |
| </li> |
| </ul> |
| </div></div></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-jspc-maven-plugin">Jetty Jspc Maven Plugin</h3> |
| <div class="paragraph"> |
| <p>This plugin will help you pre-compile your jsps and works in conjunction with the Maven war plugin to put them inside an assembled war.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="jspc-config">Configuration</h4> |
| <div class="paragraph"> |
| <p>Here’s the basic setup required to put the jspc plugin into your build:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-jspc-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <executions> |
| <execution> |
| <id>jspc</id> |
| <goals> |
| <goal>jspc</goal> |
| </goals> |
| <configuration> |
| </configuration> |
| </execution> |
| </executions> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The configurable parameters are as follows:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">webXmlFragment</dt> |
| <dd> |
| <p>Default value: <code>$\{project.basedir}/target/webfrag.xml</code></p> |
| <div class="paragraph"> |
| <p>File into which to generate the servlet declarations. |
| Will be merged with an existing <code>web.xml</code>.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">webAppSourceDirectory</dt> |
| <dd> |
| <p>Default value: <code>$\{project.basedir}/src/main/webapp</code></p> |
| <div class="paragraph"> |
| <p>Root of resources directory where jsps, tags etc are located.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">webXml</dt> |
| <dd> |
| <p>Default value: <code>$\{project.basedir}/src/main/webapp/WEB-INF/web.xml</code></p> |
| <div class="paragraph"> |
| <p>The web.xml file to use to merge with the generated fragments.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">includes</dt> |
| <dd> |
| <p>Default value: <code><strong>\/<strong>.jsp, </strong>\/</strong>.jspx</code></p> |
| <div class="paragraph"> |
| <p>The comma separated list of patterns for file extensions to be processed.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">excludes</dt> |
| <dd> |
| <p>Default value: <code><strong>\/.svn\/</strong></code></p> |
| <div class="paragraph"> |
| <p>The comma separated list of patterns for file extensions to be skipped.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">classesDirectory</dt> |
| <dd> |
| <p>Default value: <code>$\{project.build.outputDirectory}</code></p> |
| <div class="paragraph"> |
| <p>Location of classes for the webapp.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">generatedClasses</dt> |
| <dd> |
| <p>Default value: <code>$\{project.build.outputDirectory}</code></p> |
| <div class="paragraph"> |
| <p>Location to put the generated classes for the jsps.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">insertionMarker</dt> |
| <dd> |
| <p>Default value: <em>none</em></p> |
| <div class="paragraph"> |
| <p>A marker string in the src <code>web.xml</code> file which indicates where to merge in the generated web.xml fragment. |
| Note that the marker string will NOT be preserved during the insertion. |
| Can be left blank, in which case the generated fragment is inserted just before the line containing <code></web-app></code>.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">useProvidedScope</dt> |
| <dd> |
| <p>Default value: false</p> |
| <div class="paragraph"> |
| <p>If true, jars of dependencies marked with <scope>provided</scope> will be placed on the compilation classpath.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">mergeFragment</dt> |
| <dd> |
| <p>Default value: true</p> |
| <div class="paragraph"> |
| <p>Whether or not to merge the generated fragment file with the source web.xml. |
| The merged file will go into the same directory as the webXmlFragment.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">keepSources</dt> |
| <dd> |
| <p>Default value: false</p> |
| <div class="paragraph"> |
| <p>If true, the generated .java files are not deleted at the end of processing.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">sourceVersion</dt> |
| <dd> |
| <p>Introduced in Jetty 9.3.6. |
| Java version of jsp source files. |
| Defaults to 1.7.</p> |
| </dd> |
| <dt class="hdlist1">targetVersion</dt> |
| <dd> |
| <p>Introduced in Jetty 9.3.6. |
| Java version of class files generated from jsps. |
| Defaults to 1.7.</p> |
| </dd> |
| <dt class="hdlist1">tldJarNamePatterns</dt> |
| <dd> |
| <p>Default value: <code>.<strong>taglibs[<sup>/]</strong>\.jar|.<strong>jstl-impl[</sup>/]</strong>\.jar$</code></p> |
| <div class="paragraph"> |
| <p>Patterns of jars on the 'system' (ie container) path that contain tlds. |
| Use | to separate each pattern.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1">jspc</dt> |
| <dd> |
| <p>Default value: the <code>org.apache.jasper.JspC</code> instance being configured.</p> |
| <div class="paragraph"> |
| <p>The JspC class actually performs the pre-compilation. |
| All setters on the JspC class are available. |
| You can download the javadoc <a href="https://repo1.maven.org/maven2/org/glassfish/web/javax.servlet.jsp/2.3.2/javax.servlet.jsp-2.3.2-javadoc.jar">here</a>.</p> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Taking all the default settings, here’s how to configure the war plugin to use the generated <code>web.xml</code> that includes all of the jsp servlet declarations:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-war-plugin</artifactId> |
| <configuration> |
| <webXml>${project.basedir}/target/web.xml</webXml> |
| </configuration> |
| </plugin></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jspc-production-precompile">Precompiling only for Production Build</h4> |
| <div class="paragraph"> |
| <p>As compiling jsps is usually done during preparation for a production release and not usually done during development, it is more convenient to put the plugin setup inside a <profile> which which can be deliberately invoked during prep for production.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, the following profile will only be invoked if the flag <code>-Dprod</code> is present on the run line:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><profiles> |
| <profile> |
| <id>prod</id> |
| <activation> |
| <property><name>prod</name></property> |
| </activation> |
| <build> |
| <plugins> |
| <plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-jspc-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <!-- put your configuration in here --> |
| </plugin> |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-war-plugin</artifactId> |
| <!-- put your configuration in here --> |
| </plugin> |
| </plugins> |
| </build> |
| </profile> |
| </profiles></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The following invocation would cause your code to be compiled, the jsps to be compiled, the <servlet> and <servlet-mapping>s inserted in the <code>web.xml</code> and your webapp assembled into a war:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">$ mvn -Dprod package</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jspc-overlay-precompile">Precompiling Jsps with Overlaid Wars</h4> |
| <div class="paragraph"> |
| <p>Precompiling jsps with an overlaid war requires a bit more configuration. |
| This is because you need to separate the steps of unpacking the overlaid war and then repacking the final target war so the jetty-jspc-maven-plugin has the opportunity to access the overlaid resources.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the example we’ll show, we will use an overlaid war. |
| The overlaid war will provide the <code>web.xml</code> file but the jsps will be in <code>src/main/webapp</code> (i.e. part of the project that uses the overlay). |
| We will unpack the overlaid war file, compile the jsps and merge their servlet definitions into the extracted <code>web.xml</code>, then pack everything into a war.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example configuration of the war plugin that separate those phases into an unpack phase, and then a packing phase:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <artifactId>maven-war-plugin</artifactId> |
| <executions> |
| <execution> |
| <id>unpack</id> |
| <goals><goal>exploded</goal></goals> |
| <phase>generate-resources</phase> |
| <configuration> |
| <webappDirectory>target/foo</webappDirectory> |
| <overlays> |
| <overlay /> |
| <overlay> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>test-jetty-webapp</artifactId> |
| </overlay> |
| </overlays> |
| </configuration> |
| </execution> |
| <execution> |
| <id>pack</id> |
| <goals><goal>war</goal></goals> |
| <phase>package</phase> |
| <configuration> |
| <warSourceDirectory>target/foo</warSourceDirectory> |
| <webXml>target/web.xml</webXml> |
| </configuration> |
| </execution> |
| </executions> |
| </plugin></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Now you also need to configure the <code>jetty-jspc-maven-plugin</code> so that it can use the web.xml that was extracted by the war unpacking and merge in the generated definitions of the servlets. |
| This is in <code>target/foo/WEB-INF/web.xml</code>. |
| Using the default settings, the <code>web.xml</code> merged with the jsp servlet definitions will be put into <code>target/web.xml</code>.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><plugin> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-jspc-maven-plugin</artifactId> |
| <version>10.0.0-SNAPSHOT</version> |
| <executions> |
| <execution> |
| <id>jspc</id> |
| <goals> |
| <goal>jspc</goal> |
| </goals> |
| <configuration> |
| <webXml>target/foo/WEB-INF/web.xml</webXml> |
| <includes>**/*.foo</includes> |
| <excludes>**/*.fff</excludes> |
| </configuration> |
| </execution> |
| </executions> |
| </plugin></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="http-client">HTTP Client</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="http-client-intro">Introduction</h3> |
| <div class="paragraph"> |
| <p>The Jetty HTTP client module provides easy-to-use APIs and utility classes to perform HTTP (or HTTPS) requests.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty’s HTTP client is non-blocking and asynchronous. |
| It offers an asynchronous API that never blocks for I/O, making it very efficient in thread utilization and well suited for high performance scenarios such as load testing or parallel computation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>However, when all you need to do is to perform a <code>GET</code> request to a resource, Jetty’s HTTP client offers also a synchronous API; a programming interface |
| where the thread that issued the request blocks until the request/response conversation is complete.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty’s HTTP client supports different <a href="#http-client-transport">transports</a>: HTTP/1.1, FastCGI and HTTP/2. |
| This means that the semantic of a HTTP request (that is, " <code>GET</code> me the resource <code>/index.html</code> ") can be carried over the network in different formats. |
| The most common and default format is HTTP/1.1. |
| That said, Jetty’s HTTP client can carry the same request using the FastCGI format or the new HTTP/2 format.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The FastCGI transport is heavily used in Jetty’s <a href="#fastcgi">FastCGI support</a> that allows Jetty to work as a reverse proxy to PHP (exactly like Apache or Nginx do) and therefore be able to serve - for example - WordPress websites.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The HTTP/2 transport allows Jetty’s HTTP client to perform requests using HTTP/2 to HTTP/2 enabled web sites, see also Jetty’s <a href="#http2">HTTP/2 support</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Out of the box features that you get with the Jetty HTTP client include:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Redirect support - redirect codes such as 302 or 303 are automatically followed.</p> |
| </li> |
| <li> |
| <p>Cookies support - cookies sent by servers are stored and sent back to servers in matching requests.</p> |
| </li> |
| <li> |
| <p>Authentication support - HTTP "Basic" and "Digest" authentications are supported, others are pluggable.</p> |
| </li> |
| <li> |
| <p>Forward proxy support - HTTP proxying and SOCKS4 proxying.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect3"> |
| <h4 id="http-client-init">Starting HttpClient</h4> |
| <div class="paragraph"> |
| <p>The main class is named <code>org.eclipse.jetty.client.HttpClient</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can think of a <code>HttpClient</code> instance as a browser instance. |
| Like a browser it can make requests to different domains, it manages redirects, cookies and authentication, you can configure it with a proxy, and |
| it provides you with the responses to the requests you make.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In order to use <code>HttpClient</code>, you must instantiate it, configure it, and then start it:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// Instantiate HttpClient |
| HttpClient httpClient = new HttpClient(); |
| |
| // Configure HttpClient, for example: |
| httpClient.setFollowRedirects(false); |
| |
| // Start HttpClient |
| httpClient.start();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You may create multiple instances of <code>HttpClient</code>, but typically one instance is enough for an application. |
| There are several reasons for having multiple <code>HttpClient</code> instances including, but not limited to:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>You want to specify different configuration parameters (for example, one instance is configured with a forward proxy while another is not)</p> |
| </li> |
| <li> |
| <p>You want the two instances to behave like two different browsers and hence have different cookies, different authentication credentials…​etc.</p> |
| </li> |
| <li> |
| <p>You want to use different transports</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>When you create a <code>HttpClient</code> instance using the parameterless constructor, you will only be able to perform plain HTTP requests and you will not be able to perform HTTPS requests.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In order to perform HTTPS requests, you should create first a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/util/ssl/SslContextFactory.Client.html"><code>SslContextFactory.Client</code></a>, configure it, and pass it to the <code>HttpClient</code> constructor. |
| When created with a <code>SslContextFactory</code>, the <code>HttpClient</code> will be able to perform both HTTP and HTTPS requests to any domain.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// Instantiate and configure the SslContextFactory |
| SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); |
| |
| // Instantiate HttpClient with the SslContextFactory |
| HttpClient httpClient = new HttpClient(sslContextFactory); |
| |
| // Configure HttpClient, for example: |
| httpClient.setFollowRedirects(false); |
| |
| // Start HttpClient |
| httpClient.start();</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Stopping HttpClient</h4> |
| <div class="paragraph"> |
| <p>It is recommended that when your application stops, you also stop the <code>HttpClient</code> instance (or instances) that you are using.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient.stop();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Stopping <code>HttpClient</code> makes sure that the memory it holds (for example, authentication credentials, cookies, etc.) is released, and that the thread pool and scheduler are properly stopped allowing all threads used by <code>HttpClient</code> to exit.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="http-client-api">API Usage</h3> |
| <div class="sect3"> |
| <h4 id="http-client-blocking">Blocking APIs</h4> |
| <div class="paragraph"> |
| <p>The simple way to perform a HTTP request is the following:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ContentResponse response = httpClient.GET("http://domain.com/path?query");</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The method <code>HttpClient.GET(…​)</code> performs a HTTP <code>GET</code> request to the given URI and returns a <code>ContentResponse</code> when the request/response conversation completes successfully.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>ContentResponse</code> object contains the HTTP response information: status code, headers and possibly content. |
| The content length is limited by default to 2 MiB; for larger content see <a href="#http-client-response-content">Response Content Handling</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you want to customize the request, for example by issuing a <code>HEAD</code> request instead of a <code>GET</code>, and simulating a browser user agent, you can do it in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ContentResponse response = httpClient.newRequest("http://domain.com/path?query") |
| .method(HttpMethod.HEAD) |
| .agent("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:17.0) Gecko/20100101 Firefox/17.0") |
| .send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is a shorthand for:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Request request = httpClient.newRequest("http://domain.com/path?query"); |
| request.method(HttpMethod.HEAD); |
| request.agent("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:17.0) Gecko/20100101 Firefox/17.0"); |
| ContentResponse response = request.send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You first create a request object using <code>httpClient.newRequest(…​)</code>, and then you customize it using the fluent API style (that is, a chained invocation of methods on the request object). |
| When the request object is customized, you call <code>request.send()</code> that produces the <code>ContentResponse</code> when the request/response conversation is complete.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Simple <code>POST</code> requests also have a shortcut method:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ContentResponse response = httpClient.POST("http://domain.com/entity/1") |
| .param("p", "value") |
| .send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>POST</code> parameter values added via the <code>param()</code> method are automatically URL-encoded.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty’s HTTP client automatically follows redirects, so it handles the typical web pattern <a href="http://en.wikipedia.org/wiki/Post/Redirect/Get">POST/Redirect/GET</a>, and the response object contains the content of the response of the <code>GET</code> request. |
| Following redirects is a feature that you can enable/disable on a per-request basis or globally.</p> |
| </div> |
| <div class="paragraph"> |
| <p>File uploads also require one line, and make use of JDK 7′s <code>java.nio.file</code> classes:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ContentResponse response = httpClient.newRequest("http://domain.com/upload") |
| .method(HttpMethod.POST) |
| .file(Paths.get("file_to_upload.txt"), "text/plain") |
| .send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>It is possible to impose a total timeout for the request/response conversation using the <code>Request.timeout(…​)</code> method as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ContentResponse response = httpClient.newRequest("http://domain.com/path?query") |
| .timeout(5, TimeUnit.SECONDS) |
| .send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In the example above, when the 5 seconds expire, the request is aborted and a <code>java.util.concurrent.TimeoutException</code> is thrown.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="http-client-async">Non-Blocking APIs</h4> |
| <div class="paragraph"> |
| <p>So far we have shown how to use Jetty HTTP client in a blocking style - that is, the thread that issues the request blocks until the request/response conversation is complete.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This section will look at Jetty’s HTTP client non-blocking, asynchronous APIs that are perfectly suited for large content downloads, for parallel processing of requests/responses and in cases where performance and efficient thread and resource utilization is a key factor.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The asynchronous APIs rely heavily on listeners that are invoked at various stages of request and response processing. |
| These listeners are implemented by applications and may perform any kind of logic. |
| The implementation invokes these listeners in the same thread that is used to process the request or response. |
| Therefore, if the application code in these listeners takes a long time to execute, the request or response processing is delayed until the listener returns.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you need to execute application code that takes long time inside a listener, you must spawn your own thread and remember to deep copy any data provided by the listener that you will need in your code, because when the listener returns the data it provides may be recycled/cleared/destroyed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Request and response processing are executed by two different threads and therefore may happen concurrently. |
| A typical example of this concurrent processing is an echo server, where a large upload may be concurrent with the large download echoed back. |
| As a side note, remember that responses may be processed and completed <em>before</em> requests; a typical example is a large upload that triggers a quick response - for example an error - by the server: the response may arrive and be completed while the request content is still being uploaded.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The application thread that calls <code>Request.send(Response.CompleteListener)</code> performs the processing of the request until either the request is fully processed or until it would block on I/O, then it returns (and therefore never blocks). |
| If it would block on I/O, the thread asks the I/O system to emit an event when the I/O will be ready to continue, then returns. |
| When such an event is fired, a thread taken from the <code>HttpClient</code> thread pool will resume the processing of the request.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Response are processed from the I/O thread that fires the event that bytes are ready to be read. |
| Response processing continues until either the response is fully processed or until it would block for I/O. |
| If it would block for I/O, the thread asks the I/O system to emit an event when the I/O will be ready to continue, then returns. |
| When such an event is fired, a thread taken from the <code>HttpClient</code> thread pool will resume the processing of the response.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When the request and the response are both fully processed, the thread that finished the last processing (usually the thread that processes the response, but may also be the thread that processes the request - if the request takes more time than the response to be processed) is used to de-queue the next request for the same destination and processes it.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A simple asynchronous <code>GET</code> request that discards the response content can be written in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient.newRequest("http://domain.com/path") |
| .send(new Response.CompleteListener() |
| { |
| @Override |
| public void onComplete(Result result) |
| { |
| // Your logic here |
| } |
| });</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Method <code>Request.send(Response.CompleteListener)</code> returns <code>void</code> and does not block; the <code>Response.CompleteListener</code> provided as a parameter is notified when the request/response conversation is complete, and the <code>Result</code> parameter allows you to access the response object.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can write the same code using JDK 8′s lambda expressions:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient.newRequest("http://domain.com/path") |
| .send(result -> { /* Your logic here */ });</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You can impose a total timeout for the request/response conversation in the same way used by the synchronous API:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient.newRequest("http://domain.com/path") |
| .timeout(3, TimeUnit.SECONDS) |
| .send(result -> { /* Your logic here */ });</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The example above will impose a total timeout of 3 seconds on the request/response conversation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The HTTP client APIs use listeners extensively to provide hooks for all possible request and response events, and with JDK 8′s lambda expressions they are even more fun to use:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient.newRequest("http://domain.com/path") |
| // Add request hooks |
| .onRequestQueued(request -> { ... }) |
| .onRequestBegin(request -> { ... }) |
| ... // More request hooks available |
| |
| // Add response hooks |
| .onResponseBegin(response -> { ... }) |
| .onResponseHeaders(response -> { ... }) |
| .onResponseContent((response, buffer) -> { ... }) |
| ... // More response hooks available |
| |
| .send(result -> { ... });</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This makes Jetty HTTP client suitable for HTTP load testing because, for example, you can accurately time every step of the request/response conversation (thus knowing where the request/response time is really spent).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Have a look at the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/client/api/Request.Listener.html"><code>Request.Listener</code></a> class to know about request events, and to the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/client/api/Response.Listener.html"><code>Response.Listener</code></a> class to know about response events.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="http-client-content">Content Handling</h4> |
| <div class="sect4"> |
| <h5 id="http-client-request-content">Request Content Handling</h5> |
| <div class="paragraph"> |
| <p>Jetty’s HTTP client provides a number of utility classes off the shelf to handle request content.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can provide request content as <code>String</code>, <code>byte[]</code>, <code>ByteBuffer</code>, <code>java.nio.file.Path</code>, <code>InputStream</code>, and provide your own implementation of <code>org.eclipse.jetty.client.api.ContentProvider</code>. |
| Here’s an example that provides the request content using <code>java.nio.file.Paths</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ContentResponse response = httpClient.newRequest("http://domain.com/upload") |
| .method(HttpMethod.POST) |
| .file(Paths.get("file_to_upload.txt"), "text/plain") |
| .send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to using the <code>PathContentProvider</code> utility class:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ContentResponse response = httpClient.newRequest("http://domain.com/upload") |
| .method(HttpMethod.POST) |
| .content(new PathContentProvider(Paths.get("file_to_upload.txt")), "text/plain") |
| .send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Alternatively, you can use <code>FileInputStream</code> via the <code>InputStreamContentProvider</code> utility class:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ContentResponse response = httpClient.newRequest("http://domain.com/upload") |
| .method(HttpMethod.POST) |
| .content(new InputStreamContentProvider(new FileInputStream("file_to_upload.txt")), "text/plain") |
| .send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Since <code>InputStream</code> is blocking, then also the send of the request will block if the input stream blocks, even in case of usage of the asynchronous <code>HttpClient</code> APIs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you have already read the content in memory, you can pass it as a <code>byte[]</code> using the <code>BytesContentProvider</code> utility class:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">byte[] bytes = ...; |
| ContentResponse response = httpClient.newRequest("http://domain.com/upload") |
| .method(HttpMethod.POST) |
| .content(new BytesContentProvider(bytes), "text/plain") |
| .send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If the request content is not immediately available, but your application will be notified of the content to send, you can use <code>DeferredContentProvider</code> in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">DeferredContentProvider content = new DeferredContentProvider(); |
| httpClient.newRequest("http://domain.com/upload") |
| .method(HttpMethod.POST) |
| .content(content) |
| .send(new Response.CompleteListener() |
| { |
| @Override |
| public void onComplete(Result result) |
| { |
| // Your logic here |
| } |
| }); |
| |
| // Content not available yet here |
| |
| ... |
| |
| // An event happens, now content is available |
| byte[] bytes = ...; |
| content.offer(ByteBuffer.wrap(bytes)); |
| |
| ... |
| |
| // All content has arrived |
| content.close();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>While the request content is awaited and consequently uploaded by the client application, the server may be able to respond (at least with the response headers) completely asynchronously. |
| In this case, <code>Response.Listener</code> callbacks will be invoked before the request is fully sent. |
| This allows fine-grained control of the request/response conversation: for example the server may reject contents that are too big, send a response to the client, which in turn may stop the content upload.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Another way to provide request content is by using an <code>OutputStreamContentProvider</code>, |
| which allows applications to write request content when it is available to the <code>OutputStream</code> provided by <code>OutputStreamContentProvider</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">OutputStreamContentProvider content = new OutputStreamContentProvider(); |
| |
| // Use try-with-resources to close the OutputStream when all content is written |
| try (OutputStream output = content.getOutputStream()) |
| { |
| client.newRequest("localhost", 8080) |
| .method(HttpMethod.POST) |
| .content(content) |
| .send(new Response.CompleteListener() |
| { |
| @Override |
| public void onComplete(Result result) |
| { |
| // Your logic here |
| } |
| }); |
| |
| ... |
| |
| // Write content |
| writeContent(output); |
| } |
| // End of try-with-resource, output.close() called automatically to signal end of content</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="http-client-response-content">Response Content Handling</h5> |
| <div class="paragraph"> |
| <p>Jetty HTTP client allows applications to handle response content in different ways.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The first way is to buffer the response content in memory; this is done when using the blocking APIs (see <a href="#http-client-blocking">Blocking APIs</a>) and the content is buffered within a <code>ContentResponse</code> up to 2 MiB.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you want to control the length of the response content (for example limiting to values smaller than the default of 2 MiB), then you can use a <code>org.eclipse.jetty.client.util.FutureResponseListener</code> in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Request request = httpClient.newRequest("http://domain.com/path"); |
| |
| // Limit response content buffer to 512 KiB |
| FutureResponseListener listener = new FutureResponseListener(request, 512 * 1024); |
| |
| request.send(listener); |
| |
| ContentResponse response = listener.get(5, TimeUnit.SECONDS);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If the response content length is exceeded, the response will be aborted, and an exception will be thrown by method <code>get()</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you are using the asynchronous APIs (see <a href="#http-client-async">Non-Blocking APIs</a>), you can use the <code>BufferingResponseListener</code> utility class:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient.newRequest("http://domain.com/path") |
| // Buffer response content up to 8 MiB |
| .send(new BufferingResponseListener(8 * 1024 * 1024) |
| { |
| @Override |
| public void onComplete(Result result) |
| { |
| if (!result.isFailed()) |
| { |
| byte[] responseContent = getContent(); |
| // Your logic here |
| } |
| } |
| });</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The second way is the most efficient (because it avoids content copies) and allows you to specify a <code>Response.ContentListener</code>, or a subclass, to handle the content as soon as it arrives. |
| In the example below, <code>Response.Listener.Adapter</code> is a class that implements both <code>Response.ContentListener</code> and <code>Response.CompleteListener</code> and can be passed to <code>Request.send()</code>. |
| Jetty’s HTTP client will invoke the <code>onContent()</code> method zero or more times (until there is content), and finally invoke the <code>onComplete()</code> method.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient .newRequest("http://domain.com/path") |
| .send(new Response.Listener.Adapter() |
| { |
| @Override |
| public void onContent(Response response, ByteBuffer buffer) |
| { |
| // Your logic here |
| } |
| });</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The third way allows you to wait for the response and then stream the content using the <code>InputStreamResponseListener</code> utility class:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">InputStreamResponseListener listener = new InputStreamResponseListener(); |
| httpClient.newRequest("http://domain.com/path") |
| .send(listener); |
| |
| // Wait for the response headers to arrive |
| Response response = listener.get(5, TimeUnit.SECONDS); |
| |
| // Look at the response |
| if (response.getStatus() == HttpStatus.OK_200) |
| { |
| // Use try-with-resources to close input stream. |
| try (InputStream responseContent = listener.getInputStream()) |
| { |
| // Your logic here |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="http-client-cookie">Cookies Support</h3> |
| <div class="paragraph"> |
| <p>Jetty HTTP client supports cookies out of the box. |
| The <code>HttpClient</code> instance receives cookies from HTTP responses and stores them in a <code>java.net.CookieStore</code>, a class that is part of the JDK. |
| When new requests are made, the cookie store is consulted and if there are matching cookies (that is, cookies that are not expired and that match domain and path of the request) then they are added to the requests.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Applications can programmatically access the cookie store to find the cookies that have been set:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">CookieStore cookieStore = httpClient.getCookieStore(); |
| List<HttpCookie> cookies = cookieStore.get(URI.create("http://domain.com/path"));</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Applications can also programmatically set cookies as if they were returned from a HTTP response:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">CookieStore cookieStore = httpClient.getCookieStore(); |
| HttpCookie cookie = new HttpCookie("foo", "bar"); |
| cookie.setDomain("domain.com"); |
| cookie.setPath("/"); |
| cookie.setMaxAge(TimeUnit.DAYS.toSeconds(1)); |
| cookieStore.add(URI.create("http://domain.com"), cookie);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Cookies may be added only for a particular request:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ContentResponse response = httpClient.newRequest("http://domain.com/path") |
| .cookie(new HttpCookie("foo", "bar")) |
| .send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You can remove cookies that you do not want to be sent in future HTTP requests:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">CookieStore cookieStore = httpClient.getCookieStore(); |
| URI uri = URI.create("http://domain.com"); |
| List<HttpCookie> cookies = cookieStore.get(uri); |
| for (HttpCookie cookie : cookies) |
| cookieStore.remove(uri, cookie);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If you want to totally disable cookie handling, you can install a <code>HttpCookieStore.Empty</code> instance in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient.setCookieStore(new HttpCookieStore.Empty());</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You can enable cookie filtering by installing a cookie store that performs the filtering logic in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient.setCookieStore(new GoogleOnlyCookieStore()); |
| |
| public class GoogleOnlyCookieStore extends HttpCookieStore |
| { |
| @Override |
| public void add(URI uri, HttpCookie cookie) |
| { |
| if (uri.getHost().endsWith("google.com")) |
| super.add(uri, cookie); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The example above will retain only cookies that come from the <code>google.com</code> domain or sub-domains.</p> |
| </div> |
| <div class="sect3"> |
| <h4>Special Characters in Cookies</h4> |
| <div class="paragraph"> |
| <p>Jetty is compliant with <a href="https://tools.ietf.org/html/rfc6265">RFC6265</a>, and as such care must be taken when setting a cookie value that includes special characters such as <code>;</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Previously, Version=1 cookies defined in <a href="https://tools.ietf.org/html/rfc2109">RFC2109</a> (and continued in <a href="https://tools.ietf.org/html/rfc2965">RFC2965</a>) allowed for special/reserved characters to be enclosed within double quotes when declared in a <code>Set-Cookie</code> response header:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Set-Cookie: foo="bar;baz";Version=1;Path="/secur"</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This was added to the HTTP Response header as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Cookie cookie = new Cookie("foo", "bar;baz"); |
| cookie.setPath("/secur"); |
| response.addCookie(cookie);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The introduction of RFC6265 has rendered this approach no longer possible; users are now required to encode cookie values that use these special characters. |
| This can be done utilizing <code>javax.servlet.http.Cookie</code> as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Cookie cookie = new Cookie("foo", URLEncoder.encode("bar;baz", "utf-8"));</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty validates all cookie names and values being added to the <code>HttpServletResponse</code> via the <code>addCookie(Cookie)</code> method. |
| If an illegal value is discovered Jetty will throw an <code>IllegalArgumentException</code> with the details.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="http-client-authentication">Authentication Support</h3> |
| <div class="paragraph"> |
| <p>Jetty’s HTTP client supports the <code>BASIC</code> and <code>DIGEST</code> authentication mechanisms defined by <a href="https://tools.ietf.org/html/rfc7235">RFC 7235</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can configure authentication credentials in the HTTP client instance as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">URI uri = new URI("http://domain.com/secure"); |
| String realm = "MyRealm"; |
| String user = "username"; |
| String pass = "password"; |
| |
| // Add authentication credentials |
| AuthenticationStore auth = httpClient.getAuthenticationStore(); |
| auth.addAuthentication(new BasicAuthentication(uri, realm, user, pass)); |
| |
| ContentResponse response = httpClient |
| .newRequest(uri) |
| .send() |
| .get(5, TimeUnit.SECONDS);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty’s HTTP client tests authentication credentials against the challenge(s) the server issues (see our section here on <a href="#configuring-security-secure-passwords">secure password obfuscation</a>), and if they match it automatically sends the right authentication headers to the server for authentication. |
| If the authentication is successful, it caches the result and reuses it for subsequent requests for the same domain and matching URIs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The HTTP conversation for a successful match is the following:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>Application HttpClient Server |
| | | | |
| |--- GET ---|------------ GET ----------->| |
| | | | |
| | |<-- 401 + WWW-Authenticate --| |
| | | | |
| | |--- GET + Authentication --->| |
| | | | |
| |<-- 200 ---|------------ 200 ------------|</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The application does not receive events related to the response with code 401, they are handled internally by <code>HttpClient</code> which produces a request similar to the original but with the correct <code>Authorization</code> header, and then relays the response with code 200 to the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Successful authentications are cached, but it is possible to clear them in order to force authentication again:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">httpClient.getAuthenticationStore().clearAuthenticationResults();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Authentications may be preempted to avoid the additional roundtrip due to the server challenge in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">AuthenticationStore auth = httpClient.getAuthenticationStore(); |
| URI uri = URI.create("http://domain.com/secure"); |
| auth.addAuthenticationResult(new BasicAuthentication.BasicResult(uri, "username", "password"));</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In this way, requests for the given URI are enriched by <code>HttpClient</code> immediately with the <code>Authorization</code> header, and the server should respond with a 200 and the resource content rather than with the 401 and the challenge.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is also possible to preempt the authentication for a single request only, in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">URI uri = URI.create("http://domain.com/secure"); |
| Authentication.Result authn = new BasicAuthentication.BasicResult(uri, "username", "password") |
| Request request = httpClient.newRequest(uri); |
| authn.apply(request); |
| request.send();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>See also the <a href="#http-client-proxy-authentication">proxy authentication section</a> for further information about how authentication works with HTTP proxies.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="http-client-proxy">Proxy Support</h3> |
| <div class="paragraph"> |
| <p>Jetty’s HTTP client can be configured to use proxies to connect to destinations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Two types of proxies are available out of the box: a HTTP proxy (provided by class <code>org.eclipse.jetty.client.HttpProxy</code>) and a SOCKS 4 proxy (provided by class <code>org.eclipse.jetty.client.Socks4Proxy</code>). |
| Other implementations may be written by subclassing <code>ProxyConfiguration.Proxy</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The following is a typical configuration:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); |
| HttpProxy proxy = new HttpProxy("proxyHost", proxyPort); |
| |
| // Do not proxy requests for localhost:8080 |
| proxy.getExcludedAddresses().add("localhost:8080"); |
| |
| // add the new proxy to the list of proxies already registered |
| proxyConfig.getProxies().add(proxy); |
| |
| ContentResponse response = httpClient.GET(uri);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You specify the proxy host and port, and optionally also the addresses that you do not want to be proxied, and then add the proxy configuration on the <code>ProxyConfiguration</code> instance.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Configured in this way, <code>HttpClient</code> makes requests to the HTTP proxy (for plain-text HTTP requests) or establishes a tunnel via <code>HTTP CONNECT</code> (for encrypted HTTPS requests).</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="http-client-proxy-authentication">Proxy Authentication Support</h4> |
| <div class="paragraph"> |
| <p>Jetty’s HTTP client support proxy authentication in the same way it supports <a href="#http-client-authentication">server authentication</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the example below, the proxy requires Basic authentication, but the server requires Digest authentication, and therefore:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">URI proxyURI = new URI("http://proxy.net:8080"); |
| URI serverURI = new URI("http://domain.com/secure"); |
| |
| AuthenticationStore auth = httpClient.getAuthenticationStore(); |
| |
| // Proxy credentials. |
| auth.addAuthentication(new BasicAuthentication(proxyURI, "ProxyRealm", "proxyUser", "proxyPass")); |
| |
| // Server credentials. |
| auth.addAuthentication(new DigestAuthentication(serverURI, "ServerRealm", "serverUser", "serverPass")); |
| |
| // Proxy configuration. |
| ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration(); |
| HttpProxy proxy = new HttpProxy("proxy.net", 8080); |
| proxyConfig.getProxies().add(proxy); |
| |
| ContentResponse response = httpClient.newRequest(serverURI) |
| .send() |
| .get(5, TimeUnit.SECONDS);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The HTTP conversation for successful authentications on both the proxy and the server is the following:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>Application HttpClient Proxy Server |
| | | | | |
| |--- GET -->|------------- GET ------------->| | |
| | | | | |
| | |<----- 407 + Proxy-Authn -------| | |
| | | | | |
| | |------ GET + Proxy-Authz ------>| | |
| | | | | |
| | | |---------- GET --------->| |
| | | | | |
| | | |<--- 401 + WWW-Authn ----| |
| | | | | |
| | |<------ 401 + WWW-Authn --------| | |
| | | | | |
| | |-- GET + Proxy-Authz + Authz -->| | |
| | | | | |
| | | |------ GET + Authz ----->| |
| | | | | |
| |<-- 200 ---|<------------ 200 --------------|<--------- 200 ----------|</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The application does not receive events related to the responses with code 407 and 401 since they are handled internally by <code>HttpClient</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Similarly to the <a href="#http-client-authentication">authentication section</a>, the proxy authentication result and the server authentication result can be preempted to avoid, respectively, the 407 and 401 roundtrips.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="http-client-transport">Pluggable Transports</h3> |
| <div class="paragraph"> |
| <p>Jetty’s HTTP client can be configured to use different transports to carry the semantic of HTTP requests and responses.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This means that the intention of a client to request resource <code>/index.html</code> using the <code>GET</code> method can be carried over the network in different formats.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A HTTP client transport is the component that is in charge of converting a high-level, semantic, HTTP requests such as "GET resource /index.html" into the specific format understood by the server (for example, HTTP/2), and to convert the server response from the specific format (HTTP/2) into high-level, semantic objects that can be used by applications.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In this way, applications are not aware of the actual protocol being used. |
| This allows them to write their logic against a high-level API that hides the details of the specific protocol being used over the network.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The most common protocol format is HTTP/1.1, a text-based protocol with lines separated by <code>\r\n</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">GET /index.html HTTP/1.1\r\n |
| Host: domain.com\r\n |
| ... |
| \r\n</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>However, the same request can be made using FastCGI, a binary protocol:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">x01 x01 x00 x01 x00 x08 x00 x00 |
| x00 x01 x01 x00 x00 x00 x00 x00 |
| x01 x04 x00 x01 xLL xLL x00 x00 |
| x0C x0B D O C U M E |
| N T _ U R I / i |
| n d e x . h t m |
| l |
| ...</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Similarly, HTTP/2 is a binary protocol that transports the same information in a yet different format.</p> |
| </div> |
| <div class="sect3"> |
| <h4>HTTP/1.1 Transport</h4> |
| <div class="paragraph"> |
| <p>HTTP/1.1 is the default transport.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">// No transport specified, using default. |
| HttpClient client = new HttpClient(); |
| client.start();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>If you want to customize the HTTP/1.1 transport, you can explicitly configure <code>HttpClient</code> in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">int selectors = 1; |
| HttpClientTransportOverHTTP transport = new HttpClientTransportOverHTTP(selectors); |
| |
| HttpClient client = new HttpClient(transport, null); |
| client.start();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The example above allows you to customize the number of NIO selectors that <code>HttpClient</code> will be using.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>HTTP/2 Transport</h4> |
| <div class="paragraph"> |
| <p>The HTTP/2 transport can be configured in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">HTTP2Client h2Client = new HTTP2Client(); |
| h2Client.setSelectors(1); |
| HttpClientTransportOverHTTP2 transport = new HttpClientTransportOverHTTP2(h2Client); |
| |
| HttpClient client = new HttpClient(transport, null); |
| client.start();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p><code>HTTP2Client</code> is the lower-level client that provides an API based on HTTP/2 concepts such as <em>sessions</em>, <em>streams</em> and <em>frames</em> that are specific to HTTP/2.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>HttpClientTransportOverHTTP2</code> uses <code>HTTP2Client</code> to format high-level semantic HTTP requests ("GET resource /index.html") into the HTTP/2 specific format.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>FastCGI Transport</h4> |
| <div class="paragraph"> |
| <p>The FastCGI transport can be configured in this way:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">int selectors = 1; |
| String scriptRoot = "/var/www/wordpress"; |
| HttpClientTransportOverFCGI transport = new HttpClientTransportOverFCGI(selectors, false, scriptRoot); |
| |
| HttpClient client = new HttpClient(transport, null); |
| client.start();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In order to make requests using the FastCGI transport, you need to have a FastCGI server such as <a href="https://en.wikipedia.org/wiki/PHP#PHPFPM">PHP-FPM</a> (see also <a href="http://php.net/manual/en/install.fpm.php" class="bare">http://php.net/manual/en/install.fpm.php</a>).</p> |
| </div> |
| <div class="paragraph"> |
| <p>The FastCGI transport is primarily used by Jetty’s <a href="#fastcgi">FastCGI support</a> to serve PHP pages (WordPress for example).</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="jetty-handlers">Handlers</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="writing-custom-handlers">Writing Custom Handlers</h3> |
| <div class="paragraph"> |
| <p>The Handler is the Jetty component that deals with received requests.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Many users of Jetty never need to write a Jetty Handler, but instead use the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/servlet/package-summary.html">Servlet API.</a> |
| You can reuse the existing Jetty handlers for context, security, sessions and servlets without the need for extension. |
| However, some users might have special requirements or footprint concerns that prohibit the use of the full servlet API. |
| For them implementing a Jetty handler is a straight forward way to provide dynamic web content with a minimum of fuss.</p> |
| </div> |
| <div class="paragraph"> |
| <p>See the section on <a href="#basic-architecture">Jetty Architecture</a> to understand more about Handlers vs. Servlets.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="handler-api">The Handler API</h4> |
| <div class="paragraph"> |
| <p>The <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/Handler.html">Handler</a> interface provides Jetty’s core of content generation or manipulation. |
| Classes that implement this interface are used to coordinate requests, filter requests and generate content.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The core API of the Handler interface is:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) |
| throws IOException, ServletException</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>An implementation of this method can handle a request and pass the request onto another handler (or servlet), or it can modify and/or wrap the request before passing it on. |
| This gives three styles of handler:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Coordinating Handlers - Handlers that route requests to other handlers (<code>HandlerCollection</code>, <code>ContextHandlerCollection</code>)</p> |
| </li> |
| <li> |
| <p>Filtering Handlers - Handlers that augment a request and pass it on to other handlers (<code>HandlerWrapper</code>, <code>ContextHandler</code>, <code>SessionHandler</code>)</p> |
| </li> |
| <li> |
| <p>Generating Handlers - Handlers that produce content (<code>ResourceHandler</code> and <code>ServletHandler</code>)</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect4"> |
| <h5 id="target">The Target</h5> |
| <div class="paragraph"> |
| <p>The target of a handler is an identifier for the resource that should handle the passed request. |
| This is normally the URI that is parsed from an HTTP Request. |
| However, in two key circumstances the target may differ from the URI of the passed request:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>If the request has been dispatched to a named resource, such as a named servlet, the target is the name of that resource.</p> |
| </li> |
| <li> |
| <p>If the request is being made by a call to <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/RequestDispatcher.html"><code>RequestDispatcher</code></a>, the target is the URI of the included resource and is different to the URI of the actual request.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="request-and-response">The Request and Response</h5> |
| <div class="paragraph"> |
| <p>The request and response objects used in the signature of the handle method are |
| <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html"><code>ServletRequest</code></a> and <a href="http://docs.oracle.com/javaee/7/api/javax/servlet/ServletResponse.html"><code>ServletResponse</code></a>. |
| These are the standard APIs and are moderately restricted in what they can do to the request and response. |
| More often than not, access to the Jetty implementations of these classes is required: <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/Request.html"><code>Request</code></a> and <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/Response.html"><code>Response</code></a>. |
| However, as the request and response may be wrapped by handlers, filters and servlets, it is not possible to pass the implementation directly. |
| The following mantra retrieves the core implementation objects from under any wrappers:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Request base_request = request instanceof Request ? (Request)request : HttpConnection.getCurrentConnection().getHttpChannel().getRequest(); |
| Response base_response = response instanceof Response ? (Response)response : HttpConnection.getCurrentConnection().getHttpChannel().getResponse();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Notice that if the handler passes the request on to another handler, it should use the Request/Response objects passed in, and not the base objects. |
| This is to preserve any wrapping done by up stream handlers.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="dispatch">The Dispatch</h5> |
| <div class="paragraph"> |
| <p>The dispatch argument indicates the state of the handling of the call and may be:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>REQUEST == 1</code> - An original request received from a connector.</p> |
| </li> |
| <li> |
| <p><code>FORWARD == 2</code> - A request being forwarded by a RequestDispatcher.</p> |
| </li> |
| <li> |
| <p><code>INCLUDE == 4</code> - A request being included by a RequestDispatcher.</p> |
| </li> |
| <li> |
| <p><code>ERROR == 8</code> - A request being forwarded to a error handler by the container.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>These mostly have significance for servlet and related handlers. |
| For example, the security handler only applies authentication and authorization to REQUEST dispatches.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="handling-requests">Handling Requests</h4> |
| <div class="paragraph"> |
| <p>A Handler may handle a request by:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#generating-response">Generating a Response</a></p> |
| </li> |
| <li> |
| <p><a href="#filtering-request-or-response">Filtering the Request and/or Response</a></p> |
| </li> |
| <li> |
| <p><a href="#passing-request-and-response">Passing the Request and Response to Another Handler</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect4"> |
| <h5 id="generating-response">Generating a Response</h5> |
| <div class="paragraph"> |
| <p>The <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/embedded/OneHandler.html"><code>OneHandler</code></a> embedded example shows how a simple handler can generate a response.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can use the standard servlet response API, which will typically set some status, content headers and then write out the content:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java"> response.setContentType("text/html"); |
| response.setStatus(HttpServletResponse.SC_OK); |
| response.getWriter().println("<h1>Hello OneHandler</h1>");</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>It is also very important that a handler indicate that it has completed handling the request and that the request should not be passed to other handlers:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java"> Request base_request = (request instanceof Request) ? (Request)request:HttpConnection.getCurrentConnection().getHttpChannel().getRequest(); |
| base_request.setHandled(true);</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="filtering-request-or-response">Filtering the Request and/or Response</h5> |
| <div class="paragraph"> |
| <p>Once the base request or response object is obtained, you can modify it. |
| Typically you would make modifications to accomplish:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Breaking the URI into contextPath, servletPath and pathInfo components.</p> |
| </li> |
| <li> |
| <p>Associating a resource base with a request for static content.</p> |
| </li> |
| <li> |
| <p>Associating a session with a request.</p> |
| </li> |
| <li> |
| <p>Associating a security principal with a request.</p> |
| </li> |
| <li> |
| <p>Changing the URI and paths during a request dispatch forward to another resource.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>You can also update the context of the request:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Setting the current threads context classloader.</p> |
| </li> |
| <li> |
| <p>Setting thread locals to identify the current <code>ServletContext</code>.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Typically Jetty passes a modified request to another handler and undoes modifications in a finally block afterwards:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java"> try |
| { |
| base_request.setSession(a_session); |
| next_handler.handle(target,request,response,dispatch); |
| } |
| finally |
| { |
| base_request.setSession(old_session); |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The classes that implement the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/HandlerWrapper.html"><code>HandlerWrapper</code></a> class are typically handler filters of this style.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="passing-request-and-response">Passing the Request and Response to Another Handler</h5> |
| <div class="paragraph"> |
| <p>A handler might simply inspect the request and use the target, request URI or other information to select another handler to pass the request to. |
| These handlers typically implement the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/HandlerContainer.html"><code>HandlerContainer</code></a> interface.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Examples include:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/HandlerCollection.html">Class <code>HandlerCollection</code></a> - |
| A collection of handlers, where each handler is called regardless of the state of the request. |
| This is typically used to pass a request to a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/ContextHandlerCollection.html"><code>ContextHandlerCollection</code>,</a> and then the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/RequestLogHandler.html"><code>RequestLogHandler</code>.</a></p> |
| </li> |
| <li> |
| <p><a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/HandlerList.html"><code>HandlerList</code></a> - A list of handlers that are called in turn until the request state is set as handled.</p> |
| </li> |
| <li> |
| <p><a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/handler/ContextHandlerCollection.html"><code>ContextHandlerCollection</code></a> - A collection of Handlers, of which one is selected by best match for the context path.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="more-about-handlers">More About Handlers</h4> |
| <div class="paragraph"> |
| <p>See the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/">latest Jetty JavaDoc</a> for detailed information on each Jetty handler.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="websocket-intro">WebSocket Introduction</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>WebSocket is a new protocol for bidirectional communications initiated via HTTP/1.1 upgrade and providing basic message framing, layered over TCP. |
| It is based on a low-level framing protocol that delivers messages in either UTF-8 TEXT or BINARY format.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A single message in WebSocket can be of any size (the underlying framing however does have a single frame limit of <a href="http://en.wikipedia.org/wiki/9223372036854775807">63-bits</a>). |
| There can be an unlimited number of messages sent. |
| Messages are sent sequentially, the base protocol does not support interleaved messages.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A WebSocket connection goes through some basic state changes:</p> |
| </div> |
| <table class="tableblock frame-all grid-all" style="width: 50%;"> |
| <caption class="title">Table 1. WebSocket connection states</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">State</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CONNECTING</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A HTTP Upgrade to WebSocket is in progress</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">OPEN</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The HTTP Upgrade succeeded and the socket is now open and ready to read / write</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CLOSING</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A WebSocket Close Handshake has been started</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CLOSED</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">WebSocket is now closed, no more read/write possible</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>When a WebSocket is closed, a <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/websocket/api/StatusCode.html">status code</a> and short reason string is provided.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="ws-intro-provides">What Jetty provides</h3> |
| <div class="paragraph"> |
| <p>Jetty provides an implementation of the following standards and specs.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><a href="http://tools.ietf.org/html/rfc6455">RFC-6455</a></dt> |
| <dd> |
| <p>The WebSocket Protocol</p> |
| <div class="paragraph"> |
| <p>We support the version 13 of the released and final spec.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty tests its WebSocket protocol implementation using the <a href="http://autobahn.ws/testsuite">autobahn testsuite</a>.</p> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock important"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-important" title="Important"></i> |
| </td> |
| <td class="content"> |
| The early drafts of WebSocket were supported in Jetty 7 and Jetty 8, but this support has been removed in Jetty 9. |
| This means that Jetty 9 will not support the old browsers that implemented the early drafts of WebSocket. (such as Safari 5.0 or Opera 12) |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock tip"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-tip" title="Tip"></i> |
| </td> |
| <td class="content"> |
| Want to know if the browser you are targeting supports WebSocket? |
| Use <a href="http://caniuse.com/websockets">caniuse.com/websockets</a> to find out. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><a href="http://www.jcp.org/en/jsr/detail?id=356">JSR-356</a></dt> |
| <dd> |
| <p>The Java WebSocket API (<code>javax.websocket</code>)</p> |
| <div class="paragraph"> |
| <p>This is the official Java API for working with WebSockets.</p> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Unstable standards and specs:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1"><a href="https://datatracker.ietf.org/doc/draft-ietf-hybi-websocket-perframe-compression/">perframe-compression</a></dt> |
| <dd> |
| <p>Per Frame Compression Extension.</p> |
| <div class="paragraph"> |
| <p>An early extension draft from the Google/Chromium team that would provide WebSocket frame compression. |
| perframe-compression using deflate algorithm is present on many versions of Chrome/Chromium.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty’s support for perframe-compression is based on the draft-04 spec. |
| This standard is being replaced with permessage-compression.</p> |
| </div> |
| </dd> |
| <dt class="hdlist1"><a href="https://datatracker.ietf.org/doc/draft-tyoshino-hybi-permessage-compression/">permessage-compression</a></dt> |
| <dd> |
| <p>Per Frame Compression Extension.</p> |
| <div class="paragraph"> |
| <p>This is the replacement for perframe-compression, switching the compression to being based on the entire message, not the individual frames.</p> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="ws-intro-api">WebSocket APIs</h3> |
| <div class="paragraph"> |
| <p>APIs and libraries to implement your WebSockets using Jetty.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Jetty WebSocket API</dt> |
| <dd> |
| <p>The basic common API for creating and working with WebSockets using Jetty.</p> |
| </dd> |
| <dt class="hdlist1">Jetty WebSocket Server API</dt> |
| <dd> |
| <p>Write WebSocket Server Endpoints for Jetty.</p> |
| </dd> |
| <dt class="hdlist1">Jetty WebSocket Client API</dt> |
| <dd> |
| <p>Connect to WebSocket servers with Jetty.</p> |
| </dd> |
| <dt class="hdlist1">Java WebSocket Client API</dt> |
| <dd> |
| <p>The new standard Java WebSocket Client API (<code>javax.websocket</code>) [JSR-356]</p> |
| </dd> |
| <dt class="hdlist1">Java WebSocket Server API</dt> |
| <dd> |
| <p>The new standard Java WebSocket Server API (<code>javax.websocket.server</code>) [JSR-356]</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3>Enabling WebSocket</h3> |
| <div class="paragraph"> |
| <p>To enable Websocket, you need to enable the <code>websocket</code> <a href="#enabling-modules">module</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Once this module is enabled for your Jetty base, it will apply to all webapps deployed to that base. If you want to be more selective about which webapps use Websocket, then you can:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Disable Websocket for a particular webapp</dt> |
| <dd> |
| <p>You can disable jsr-356 for a particular webapp by setting the <a href="#context_attributes">context attribute</a> <code>org.eclipse.jetty.websocket.javax</code> to <code>false</code>. |
| This will mean that websockets are not available to your webapp, however deployment time scanning for websocket-related classes such as endpoints will still occur. |
| This can be a significant impost if your webapp contains a lot of classes and/or jar files. |
| To completely disable websockets and avoid all setup costs associated with it for a particular webapp, use instead the context attribute <code>org.eclipse.jetty.containerInitializerExclusionPattern</code>, described next, which allows you to exclude the websocket ServletContainerInitializer that causes the scanning.</p> |
| </dd> |
| <dt class="hdlist1">Completely disable Websocket for a particular webapp</dt> |
| <dd> |
| <p>Set the <code>org.eclipse.jetty.containerInitializerExclusionPattern</code> <a href="#context_attributes">context attribute</a> to include <code>org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServletContainerInitializer</code>. |
| Here’s an example of doing this in code, although you can do the <a href="#intro-jetty-configuration-webapps">same in xml</a>:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">WebAppContext context = new WebAppContext(); |
| context.setAttribute("org.eclipse.jetty.containerInitializerExclusionPattern", |
| "org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServletContainerInitializer|com.acme.*");</code></pre> |
| </div> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="websocket-jetty">Jetty Websocket API</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>These pages are works in progress that have not been moved to their respective sections yet.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Unresolved directive in server/websockets/jetty/chapter.adoc - include::websocket-jetty-api.adoc[] |
| Unresolved directive in server/websockets/jetty/chapter.adoc - include::websocket-jetty-api-events.adoc[] |
| Unresolved directive in server/websockets/jetty/chapter.adoc - include::websocket-jetty-api-session.adoc[] |
| Unresolved directive in server/websockets/jetty/chapter.adoc - include::websocket-jetty-api-send-message.adoc[] |
| Unresolved directive in server/websockets/jetty/chapter.adoc - include::websocket-jetty-api-annotations.adoc[] |
| Unresolved directive in server/websockets/jetty/chapter.adoc - include::websocket-jetty-api-listener.adoc[] |
| Unresolved directive in server/websockets/jetty/chapter.adoc - include::websocket-jetty-api-adapter.adoc[] |
| Unresolved directive in server/websockets/jetty/chapter.adoc - include::websocket-jetty-server-api.adoc[] |
| Unresolved directive in server/websockets/jetty/chapter.adoc - include::websocket-jetty-client-api.adoc[]</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="ant-and-jetty">Ant and Jetty</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>This chapter explains how to use Jetty with Ant and the Jetty Ant tasks.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-ant">Ant Jetty Plugin</h3> |
| <div class="paragraph"> |
| <p>The Ant Jetty plugin is a part of Jetty 9 under the <code>jetty-ant</code> module. |
| This plugin makes it possible to start a Jetty web server directly from the Ant build script, and to embed the Jetty web server inside your build process. |
| Its purpose is to provide almost the same functionality as the Jetty plugin for Maven: dynamic application reloading, working directly on web application sources, and tightly integrating with the build system.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><dependency> |
| <groupId>org.eclipse.jetty</groupId> |
| <artifactId>jetty-ant</artifactId> |
| </dependency></code></pre> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-ant-preparation">Preparing Your Project</h4> |
| <div class="paragraph"> |
| <p>To set up your project for Ant to run Jetty, you need a Jetty distribution and the jetty-ant Jar:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p><a href="https://www.eclipse.org/jetty/download.html">Download</a> a Jetty distribution and unpack it in the local filesystem.</p> |
| </li> |
| <li> |
| <p><a href="https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-ant/">Get</a> the jetty-ant Jar.</p> |
| </li> |
| <li> |
| <p>Make a directory in your project called <code>jetty-lib/</code>.</p> |
| </li> |
| <li> |
| <p>Copy all of the Jars in your Jetty distribution’s <code>lib</code> directory, and all its subdirectories, into your new <code>jetty-lib</code> dir. |
| When copying the Jars, <em>don’t</em> preserve the Jetty distribution’s lib dir hierarchy – all the jars should be directly inside your ` jetty-lib` dir.</p> |
| </li> |
| <li> |
| <p>Also copy the jetty-ant Jar you downloaded earlier into the <code>jetty-lib</code> dir.</p> |
| </li> |
| <li> |
| <p>Make a directory in your project called <code>jetty-temp</code>.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>Now you’re ready to edit or create your Ant <code>build.xml</code> file.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Preparing the <code>build.xml</code> file</h4> |
| <div class="paragraph"> |
| <p>Begin with an empty <code>build.xml</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| </project></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Add a <code><taskdef></code> that imports all available Jetty tasks:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Now you are ready to add a new target for running Jetty:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run /> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is the minimal configuration you need. You can now start Jetty on the default port of 8080.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Starting Jetty via Ant</h4> |
| <div class="paragraph"> |
| <p>At the command line enter:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> ant jetty.run</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Configuring the Jetty Container</h4> |
| <div class="paragraph"> |
| <p>A number of configuration options can help you set up the Jetty environment so that your web application has all the resources it needs:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">ports and connectors</dt> |
| <dd> |
| <p>To configure the port that Jetty starts on you need to define a connector. |
| First you need to configure a <code><typedef></code> for the Connector class and then define the connector in the Jetty tags:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="connector" classname="org.eclipse.jetty.ant.types.Connector" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <connectors> |
| <connector port="8090"/> |
| </connectors> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock tip"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-tip" title="Tip"></i> |
| </td> |
| <td class="content"> |
| You can set the port to 0, which starts the Jetty server connector on an arbitrary available port. |
| You can then access these values from system properties <code>jetty.ant.server.port</code> and <code>jetty.ant.server.host</code>. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| </dd> |
| <dt class="hdlist1">login services</dt> |
| <dd> |
| <p>If your web application requires authentication and authorization services, you can configure these on the Jetty container. |
| Here’s an example of how to set up an <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/security/HashLoginService.html">org.eclipse.jetty.security.HashLoginService</a>:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="hashLoginService" classname="org.eclipse.jetty.security.HashLoginService" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <loginServices> |
| <hashLoginService name="Test Realm" config="${basedir}/realm.properties"/> |
| </loginServices> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">request log</dt> |
| <dd> |
| <p>The <code>requestLog</code> option allows you to specify a request logger for the Jetty instance. |
| You can either use the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/NCSARequestLog.html">org.eclipse.jetty.server.NCSARequestLog</a> class, or supply the name of your custom class:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run requestLog="com.acme.MyFancyRequestLog"> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">temporary directory</dt> |
| <dd> |
| <p>You can configure a directory as a temporary file store for uses such as expanding files and compiling JSPs by supplying the <code>tempDirectory</code> option:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run tempDirectory="${basedir}/jetty-temp"> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">other context handlers</dt> |
| <dd> |
| <p>You may need to configure some other context handlers to run at the same time as your web application. |
| You can specify these other context handlers using the <code><contextHandlers></code> element. |
| You need to supply a <code><typedef></code> for it before you can use it:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" |
| resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="contextHandlers" classname="org.eclipse.jetty.ant.types.ContextHandlers" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <contextHandlers> |
| <contextHandler resourceBase="${basedir}/stuff" contextPath="/stuff"/> |
| </contextHandlers> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">system properties</dt> |
| <dd> |
| <p>As a convenience, you can configure system properties by using the <code><systemProperties></code> element. |
| Be aware that, depending on the purpose of the system property, setting it from within the Ant execution may mean that it is evaluated too late, as the JVM evaluates some system properties on entry.</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <systemProperties> |
| <systemProperty name="foo" value="bar"/> |
| </systemProperties> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">jetty XML file</dt> |
| <dd> |
| <p>If you have a lot of configuration to apply to the Jetty container, it can be more convenient to put it into a standard Jetty XML configuration file and have the Ant plugin apply it before starting Jetty:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run jettyXml="${basedir}/jetty.xml"> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">scanning for changes</dt> |
| <dd> |
| <p>The most useful mode in which to run the Ant plugin is for it to continue to execute Jetty and automatically restart your web application if any part of it changes (for example, your IDE |
| recompiles the classes of the web application). |
| The <code>scanIntervalSeconds</code> option controls how frequently the <code><jetty.run></code> task scans your web application/WAR file for changes. |
| The default value of <code>0</code> disables scanning. Here’s an example where Jetty checks for changes every five seconds:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run scanIntervalSeconds="5"> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">stopping</dt> |
| <dd> |
| <p>In normal mode (<code>daemon="false"</code>), the <code><jetty.run></code> task runs until you <code>cntrl-c</code> it. It may be useful to script both the stop AND the start of Jetty. |
| For such a case, we provide the <code><jetty.stop></code> task. |
| + |
| To use it, you need to provide a port and an identifying string to both the ` <jetty.run>` and the <code><jetty.stop></code> tasks, where <code><jetty.run></code> listens on the given port for a stop message containing the given string, and cleanly stops Jetty when it is received. |
| The <code><jetty.stop></code> task sends this stop message. |
| You can also optionally provide a <code>stopWait</code> value (in seconds), which is the length of time the <code><jetty.stop></code> task waits for confirmation that the stop succeeded:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run stopPort="9999" stopKey="9999"> |
| </jetty.run> |
| </target> |
| |
| <target name="jetty.stop"> |
| <jetty.stop stopPort="9999" stopKey="9999" stopWait="10"/> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>To stop jetty via Ant, enter:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">> ant jetty.stop</code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">execution without pausing ant</dt> |
| <dd> |
| <p>Usually, the <code><jetty.run></code> task runs until you <code>cntrl-c</code> it, pausing the execution of Ant as it does so. In some cases, it may be useful to let Ant continue executing. |
| For example, to run your unit tests you may need other tasks to execute while Jetty is running. |
| For this case, we provide the <code>daemon</code> option. |
| This defaults to <code>false</code>. For <code>true</code>, Ant continues to execute after starting Jetty. |
| If Ant exits, so does Jetty. Understand that this option does <em>not</em> fork a new process for Jetty.</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run daemon="true"> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Deploying a Web Application</h4> |
| <div class="paragraph"> |
| <p>Add a <code><typedef></code> for the <code>org.eclipse.jetty.ant.AntWebAppContext</code> class with name <em>webApp</em>, then add a <code><webApp></code> element to <code><jetty.run></code> to describe your web application. |
| The following example deploys a web application that is expanded in the local directory <code>foo/</code> to context path ` / `:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="webApp" classname="org.eclipse.jetty.ant.AntWebAppContext" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <webApp war="${basedir}/foo" contextPath="/"/> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">deploying a WAR file</dt> |
| <dd> |
| <p>It is not necessary to expand the web application into a directory. |
| It is fine to deploy it as a WAR file:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="webApp" classname="org.eclipse.jetty.ant.AntWebAppContext" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <webApp war="${basedir}/foo.war" contextPath="/"/> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">deploying more than one web application</dt> |
| <dd> |
| <p>You can also deploy more than one web application:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="webApp" classname="org.eclipse.jetty.ant.AntWebAppContext" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <webApp war="${basedir}/foo.war" contextPath="/"/> |
| <webApp war="${basedir}/other contextPath="/other"/> |
| <webApp war="${basedir}/bar.war" contextPath="/bar"/> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| <div class="sect4"> |
| <h5>Configuring the Web Application</h5> |
| <div class="paragraph"> |
| <p>As the <code>org.eclipse.jetty.ant.AntWebAppContext</code> class is an extension of |
| the |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html"><code>org.eclipse.jetty.webapp.WebAppContext</code></a> |
| class, you can configure it by adding attributes of the same name |
| (without the <code>set</code> or <code>add</code> prefix) as the setter methods.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example that specifies the location of the <code>web.xml</code> file (equivalent to method <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setDescriptor%28java.lang.String%29"><code>AntWebAppContext.setDescriptor()</code></a>) and the web application’s temporary directory (equivalent to method <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setTempDirectory%28java.io.File%29"><code>AntWebAppContext.setTempDirectory()</code></a>):</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="webApp" classname="org.eclipse.jetty.ant.AntWebAppContext" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <webApp descriptor="${basedir}/web.xml" tempDirectory="${basedir}/my-temp" war="${basedir}/foo" contextPath="/"/> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Other extra configuration options for the AntWebAppContext include:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">extra classes and Jars</dt> |
| <dd> |
| <p>If your web application’s classes and Jars do not reside inside <code>WEB-INF</code> of the resource base directory, you can use the <classes> and <jar> elements to tell Ant where to find them. Here’s an example:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="webApp" classname="org.eclipse.jetty.ant.AntWebAppContext" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <webApp descriptor="${basedir}/web.xml" tempDirectory="${basedir}/my-temp" war="${basedir}/foo" contextPath="/"> |
| <classes dir="${basedir}/classes"> |
| <include name="**/*.class"/> |
| <include name="**/*.properties"/> |
| </classes> |
| <lib dir="${basedir}/jars"> |
| <include name="**/*.jar"/> |
| <exclude name="**/*.dll"/> |
| </lib> |
| </webApp> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">context attributes</dt> |
| <dd> |
| <p>Jetty allows you to set up ServletContext attributes on your web application. |
| You configure them in a context XML file that is applied to your WebAppContext instance prior to starting it. |
| For convenience, the Ant plugin permits you to configure these directly in the build file. |
| Here’s an example:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="webApp" classname="org.eclipse.jetty.ant.AntWebAppContext" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <webApp war="${basedir}/foo" contextPath="/"> |
| <attributes> |
| <attribute name="my.param" value="123"/> |
| </attributes> |
| </webApp> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1"><code>jetty-env.xml</code> file</dt> |
| <dd> |
| <p>If you are using features such as <a href="#configuring_jndi">JNDI</a> with your web application, you may need to configure a <a href="#using_jndi"><code>WEB-INF/jetty-env.xml</code></a> file to define resources. If the structure of your web application project is such that the source of <code>jetty-env.xml</code> file resides somewhere other than <code>WEB-INF</code>, you can use the <code>jettyEnvXml</code> attribute to tell Ant where to find it:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="webApp" classname="org.eclipse.jetty.ant.AntWebAppContext" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <webApp war="${basedir}/foo" contextPath="/" jettyEnvXml="${basedir}/jetty-env.xml"> |
| <attributes> |
| </webApp> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">context XML file</dt> |
| <dd> |
| <p>You may prefer or even require to do some advanced configuration of your web application outside of the Ant build file. |
| In this case, you can use a standard context XML configuration file which the Ant plugin applies to your web application before it is deployed. |
| Be aware that the settings from the context XML file <em>override</em> those of the attributes and nested elements you defined in the build file.</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml">project name="Jetty-Ant integration test" basedir="."> |
| |
| <path id="jetty.plugin.classpath"> |
| <fileset dir="jetty-lib" includes="*.jar"/> |
| </path> |
| |
| <taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" /> |
| |
| <typedef name="webApp" classname="org.eclipse.jetty.ant.AntWebAppContext" |
| classpathref="jetty.plugin.classpath" loaderref="jetty.loader" /> |
| |
| <target name="jetty.run"> |
| <jetty.run> |
| <webApp war="${basedir}/foo" contextPath="/" contextXml="${basedir}/jetty-env.xml"> |
| <attributes> |
| </webApp> |
| </jetty.run> |
| </target> |
| |
| </project></code></pre> |
| </div> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="frameworks">Frameworks</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="framework-jetty-spring">Spring Setup</h3> |
| <div class="paragraph"> |
| <p>You can assemble and configure Jetty in code or with almost any IoC style framework including Spring. |
| If all you want to do is setup a Jetty server in your stock Spring usage, simply look at the xml snippet below as an example. |
| If you want to replace the jetty-xml being used to start the normal Jetty distribution with spring, you may do so however currently it will not leverage the rest of the module system.</p> |
| </div> |
| <div class="sect3"> |
| <h4>Jetty-Spring Module</h4> |
| <div class="paragraph"> |
| <p>The skeleton of a jetty spring module can be enabled from the jetty-distribution via the <a href="#startup-modules">module mechanism</a>. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">$ java -jar start.jar --add-to-start=spring</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This (or the alternative <a href="#start-jar">--add-to-start</a>=spring command) creates a <code>${jetty.home}/lib/spring</code> directory and populates it with the jetty-spring integration jar. |
| It does NOT supply the spring jars and their dependencies. |
| You will need to download these and place them into jetty’s classpath - you can use the <code>${jetty.home}/lib/spring</code> directory created by spring.mod for this purpose.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Using Spring to Configure Jetty</h4> |
| <div class="paragraph"> |
| <p>Configuring Jetty via Spring is simply a matter of calling the API as Spring beans. |
| The following is an example mimicking the default jetty startup configuration.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> |
| |
| <!-- =============================================================== --> |
| <!-- Configure the Jetty Server with Spring --> |
| <!-- This file is the similar to jetty.xml, but written in spring --> |
| <!-- XmlBeanFactory format. --> |
| <!-- =============================================================== --> |
| |
| <beans> |
| <bean id="contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/> |
| <bean id="server" name="Main" class="org.eclipse.jetty.server.Server" init-method="start" destroy-method="stop"> |
| <constructor-arg> |
| <bean id="threadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool"> |
| <property name="minThreads" value="10"/> |
| <property name="maxThreads" value="50"/> |
| </bean> |
| </constructor-arg> |
| <property name="connectors"> |
| <list> |
| <bean id="connector" class="org.eclipse.jetty.server.ServerConnector"> |
| <constructor-arg ref="server"/> |
| <property name="port" value="8080"/> |
| </bean> |
| </list> |
| </property> |
| <property name="handler"> |
| <bean id="handlers" class="org.eclipse.jetty.server.handler.HandlerCollection"> |
| <property name="handlers"> |
| <list> |
| <ref bean="contexts"/> |
| <bean id="defaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/> |
| </list> |
| </property> |
| </bean> |
| </property> |
| <property name="beans"> |
| <list> |
| <bean id="deploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager"> |
| <property name="contexts" ref="contexts"/> |
| <property name="appProviders"> |
| <list> |
| <bean id="webAppProvider" class="org.eclipse.jetty.deploy.providers.WebAppProvider"> |
| <property name="monitoredDirName" value="webapps"/> |
| <property name="scanInterval" value="1"/> |
| <property name="extractWars" value="true"/> |
| </bean> |
| </list> |
| </property> |
| </bean> |
| </list> |
| </property> |
| </bean> |
| </beans></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="framework-jetty-osgi">OSGI</h3> |
| <div class="sect3"> |
| <h4>Introduction</h4> |
| <div class="paragraph"> |
| <p>The Jetty OSGi infrastructure provides a Jetty container inside an OSGi container. |
| Traditional JavaEE webapps can be deployed, in addition to Jetty <code>ContextHandlers</code>, along with OSGi web bundles. |
| In addition, the infrastructure also supports the OSGi <code>HttpService</code> interface.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>General Setup</h4> |
| <div class="paragraph"> |
| <p>All of the Jetty jars contain manifest entries appropriate to ensure that they can be deployed into an OSGi container as bundles. |
| You will need to install some jetty jars into your OSGi container. |
| You can always find the Jetty jars either in the Maven Central repository, or you can <a href="https://www.eclipse.org/jetty/download.html">download</a> a distribution of Jetty. |
| Here’s the absolute minimal set of Jetty jars:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 2. Minimal Bundles</caption> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Jar</th> |
| <th class="tableblock halign-left valign-top">Bundle Symbolic Name</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-util</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.util</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-http</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.http</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-io</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.io</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-security</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.security</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-server</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.server</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-servlet</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.servlet</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-webapp</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.webapp</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-deploy</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.deploy</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-xml</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.xml</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-servlet-api</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.servlet-api</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>You <strong>must also install the Apache Aries SPI Fly bundles</strong> as many parts of Jetty - for example ALPN, websocket, annotations - use the <code>ServiceLoader</code> mechanism, which requires an OSGi Service Loader Mediator like SPI Fly:</p> |
| </div> |
| <table id="spifly" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 3. SPI Fly Bundles</caption> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Jar</th> |
| <th class="tableblock halign-left valign-top">Bundle Symbolic Name</th> |
| <th class="tableblock halign-left valign-top">Location</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle-1.2.jar</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.apache.aries.spifly.dynamic.bundle</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://repo1.maven.org/maven2/org/apache/aries/spifly/org.apache.aries.spifly.dynamic.bundle/">Maven central</a></p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| We strongly recommend that you also deploy the <a href="#osgi-annotations">annotation-related</a> jars also, as the Servlet Specification increasingly relies on annotations for functionality. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>You will also need the <strong>OSGi Event Management service</strong> and the <strong>OSGi Configuration Management service</strong>. |
| If your OSGi container does not automatically make these available, you will need to add them in a way appropriate to your container.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>The Jetty OSGi Container</h4> |
| <div class="sect4"> |
| <h5>The jetty-osgi-boot jar</h5> |
| <div class="paragraph"> |
| <p>Now that you have the basic set of Jetty jars installed, you can install the <a href="https://repo1.maven.org/maven2/org/eclipse/jetty/osgi/jetty-osgi-boot/">jetty-osgi-boot.jar</a> bundle, downloadable from the maven central repo <a href="https://repo1.maven.org/maven2/org/eclipse/jetty/osgi/jetty-osgi-boot/">here.</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>This bundle will instantiate and make available the Jetty OSGi container when it is started. |
| If this bundle is not auto-started upon installation into your OSGi container, you should start it manually using a command appropriate for your container.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="customize-jetty-container">Customizing the Jetty Container</h5> |
| <div class="paragraph"> |
| <p>Before going ahead with the install, you may want to customize the Jetty container. |
| In general this is done by a combination of System properties and the usual Jetty xml configuration files. |
| The way you define the System properties will depend on which OSGi container you are using, so ensure that you are familiar with how to set them for your environment. |
| In the following examples, we will assume that the OSGi container allows us to set System properties as simple <code>name=value</code> pairs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The available System properties are:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">jetty.http.port</dt> |
| <dd> |
| <p>If not specified, this defaults to the usual jetty port of 8080.</p> |
| </dd> |
| <dt class="hdlist1">jetty.home</dt> |
| <dd> |
| <p>Either this property <em>or</em> the <strong>jetty.home.bundle</strong> <em>must</em> be specified. |
| This property should point to a file system location that has an <code>etc/</code> directory containing xml files to configure the Jetty container on startup. |
| For example:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">jetty.home=/opt/custom/jetty</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Where <code>/opt/custom/jetty</code> contains:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">etc/jetty.xml |
| etc/jetty-selector.xml |
| etc/jetty-deployer.xml |
| etc/jetty-special.xml</code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">jetty.home.bundle</dt> |
| <dd> |
| <p>Either this property <em>or</em> the <strong>jetty.home</strong> property must be specified. |
| This property should specify the symbolic name of a bundle which contains a directory called <code>jettyhome/</code>. |
| The <code>jettyhome/</code> directory should have a subdirectory called <code>etc/</code> that contains the xml files to be applied to Jetty on startup. |
| The jetty-osgi-boot.jar contains a <code>jettyhome/</code> directory with a default set of xml configuration files. |
| Here’s how you would specify it:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">jetty.home.bundle=org.eclipse.jetty.osgi.boot</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s a partial listing of that jar that shows you the names of the xml files contained within it:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">META-INF/MANIFEST.MF |
| jettyhome/etc/jetty.xml |
| jettyhome/etc/jetty-deployer.xml |
| jettyhome/etc/jetty-http.xml</code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">jetty.etc.config.urls</dt> |
| <dd> |
| <p>This specifies the paths of the xml files that are to be used. |
| If not specified, they default to:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">etc/jetty.xml,etc/jetty-http.xml,etc/jetty-deployer.xml</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Note that the paths can either be relative or absolute, or a mixture. |
| If the path is relative, it is resolved against either <strong>jetty.home</strong> or <strong>jetty.home.bundle</strong>, whichever was specified. |
| You can use this ability to mix and match jetty configuration files to add functionality, such as adding in a https connector. |
| Here’s an example of adding a HTTPS connector, using the relevant files from the jetty-distribution:</p> |
| </div> |
| <div class="literalblock"> |
| <div class="content"> |
| <pre>etc/jetty.xml, etc/jetty-http.xml, /opt/jetty/etc/jetty-ssl.xml, /opt/jetty/etc/jetty-https.xml, etc/jetty-deployer.xml</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Note that regardless of whether you set the <strong>jetty.home</strong> or <strong>jetty.home.bundle</strong> property, when Jetty executes the configuration files, it will set an appropriate value for <strong>jetty.home</strong> so that references in xml files to <code><property name="jetty.home"></code> will work. |
| Be careful, however, if you are mixing and matching relative and absolute configuration file paths: the value of <strong>jetty.home</strong> is determined from the resolved location of the <em>relative</em> files only.</p> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>The Jetty Container as an OSGi Service</h5> |
| <div class="paragraph"> |
| <p>You can now go ahead and deploy the jetty-osgi-boot.jar into your OSGi container. |
| A Jetty server instance will be created, the xml config files applied to it, and then published as an OSGi service. |
| Normally, you will not need to interact with this service instance, however you can retrieve a reference to it using the usual OSGi API:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">org.osgi.framework.BundleContext bc; |
| org.osgi.framework.ServiceReference ref = bc.getServiceReference("org.eclipse.jetty.server.Server");</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The Server service has a couple of properties associated with it that you can retrieve using the <code>org.osgi.framework.ServiceReference.getProperty(String)</code> method:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">managedServerName</dt> |
| <dd> |
| <p>The Jetty Server instance created by the jetty-osgi-boot.jar will be called "defaultJettyServer"</p> |
| </dd> |
| <dt class="hdlist1">jetty.etc.config.urls</dt> |
| <dd> |
| <p>The list of xml files resolved from either <strong>jetty.home</strong> or <strong>jetty.home.bundle</strong>/jettyhome</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Adding More Jetty Servers</h5> |
| <div class="paragraph"> |
| <p>As we have seen in the previous section, the jetty-osgi-boot code will create an <code>org.eclipse.jetty.server.Server</code> instance, apply the xml configuration files specified by <strong>jetty.etc.config.urls</strong> System property to it, and then register it as an OSGi Service. |
| The name associated with this default instance is <code>defaultJettyServer</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can create other Server instances, register them as OSGi Services, and the jetty-osgi-boot code will notice them, and configure them so that they can deploy <code>ContextHandlers</code> and webapp bundles. |
| When you deploy webapps or <code>ContextHandlers</code> as bundles or Services (see sections below) you can target them to be deployed to a particular server instance via |
| the Server’s name.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example of how to create a new Server instance and register it with OSGi so that the jetty-osgi-boot code will find it and configure it so it can be a deployment target:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">public class Activator implements BundleActivator |
| { |
| |
| public void start(BundleContext context) throws Exception |
| { |
| |
| Server server = new Server(); |
| //do any setup on Server in here |
| String serverName = "fooServer"; |
| Dictionary serverProps = new Hashtable(); |
| //define the unique name of the server instance |
| serverProps.put("managedServerName", serverName); |
| serverProps.put("jetty.http.port", "9999"); |
| //let Jetty apply some configuration files to the Server instance |
| serverProps.put("jetty.etc.config.urls", "file:/opt/jetty/etc/jetty.xml,file:/opt/jetty/etc/jetty-selector.xml,file:/opt/jetty/etc/jetty-deployer.xml"); |
| //register as an OSGi Service for Jetty to find |
| context.registerService(Server.class.getName(), server, serverProps); |
| |
| } |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Now that we have created a new Server called "fooServer", we can deploy webapps and <code>ContextHandlers</code> as Bundles or Services to it (see below for more information on this). Here’s an example of deploying a webapp as a Service and targeting it to the "fooServer" Server we created above:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">public class Activator implements BundleActivator |
| { |
| |
| public void start(BundleContext context) throws Exception |
| { |
| |
| //Create a webapp context as a Service and target it at the "fooServer" Server instance |
| WebAppContext webapp = new WebAppContext(); |
| Dictionary props = new Hashtable(); |
| props.put("war","."); |
| props.put("contextPath","/acme"); |
| props.put("managedServerName", "fooServer"); |
| context.registerService(ContextHandler.class.getName(),webapp,props); |
| } |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Deploying Bundles as Webapps</h4> |
| <div class="paragraph"> |
| <p>The Jetty OSGi container listens for the installation of bundles, and will automatically attempt to deploy any that appear to be webapps.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Any of the following criteria are sufficient for Jetty to deploy the bundle as a webapp:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Bundle contains a WEB-INF/web.xml file</dt> |
| <dd> |
| <p>If the bundle contains a web descriptor, then it is automatically deployed. |
| This is an easy way to deploy classic JavaEE webapps.</p> |
| </dd> |
| <dt class="hdlist1">Bundle MANIFEST contains Jetty-WarFolderPath (for releases prior tojetty-9.3) or Jetty-WarResourcePath</dt> |
| <dd> |
| <p>This is the location within the bundle of the webapp resources. |
| Typically this would be used if the bundle is not a pure webapp, but rather the webapp is a component of the bundle. |
| Here’s an example of a bundle where the resources of the webapp are not located at the root of the bundle, but rather inside the subdirectory <code>web/</code> :</p> |
| <div class="paragraph"> |
| <p><code>MANIFEST</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Bundle-Name: Web |
| Jetty-WarResourcePath: web |
| Import-Package: javax.servlet;version="3.1", |
| javax.servlet.resources;version="3.1" |
| Bundle-SymbolicName: com.acme.sample.web</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Bundle contents:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">META-INF/MANIFEST.MF |
| web/index.html |
| web/foo.html |
| web/WEB-INF/web.xml |
| com/acme/sample/web/MyStuff.class |
| com/acme/sample/web/MyOtherStuff.class</code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">Bundle MANIFEST contains Web-ContextPath</dt> |
| <dd> |
| <p>This header can be used in conjunction with either of the two preceding headers to control the context path to which the webapp is deployed, or alone to identify that the bundle’s contents should be published as a webapp. |
| This header is part of the RFC-66 specification for using webapps with OSGi. |
| Here’s an example based on the previous one where we use the <code>Web-ContextPath</code> header to set its deployment context path to be "/sample" :</p> |
| <div class="paragraph"> |
| <p><code>MANIFEST</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Bundle-Name: Web |
| Jetty-WarResourcePath: web |
| Web-ContextPath: /sample |
| Import-Package: javax.servlet;version="3.1", |
| javax.servlet.resources;version="3.1" |
| Bundle-SymbolicName: com.acme.sample.web</code></pre> |
| </div> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>You can also define extra headers in your bundle MANIFEST that help |
| customize the web app to be deployed:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Jetty-defaultWebXmlFilePath</dt> |
| <dd> |
| <p>The location of a <code>webdefault.xml</code> file to apply to the webapp. |
| The location can be either absolute (either absolute path or file: url), or relative (in which case it is interpreted as relative to the bundle root). |
| Defaults to the <code>webdefault.xml</code> file built into the Jetty OSGi container.</p> |
| </dd> |
| <dt class="hdlist1">Jetty-WebXmlFilePath</dt> |
| <dd> |
| <p>The location of the <code>web.xml</code> file. |
| The location can be either absolute (either absolute path or file: url), or relative (in which case it is interpreted as relative to the bundle root). |
| Defaults to <code>WEB-INF/web.xml</code></p> |
| </dd> |
| <dt class="hdlist1">Jetty-extraClassPath</dt> |
| <dd> |
| <p>A classpath of additional items to add to the webapp’s classloader.</p> |
| </dd> |
| <dt class="hdlist1">Jetty-bundleInstall</dt> |
| <dd> |
| <p>The path to the base folder that overrides the computed bundle installation - mostly useful for those OSGi frameworks that unpack bundles by default.</p> |
| </dd> |
| <dt class="hdlist1">Require-TldBundle</dt> |
| <dd> |
| <p>A comma separated list of bundle symbolic names of bundles containing TLDs that this webapp depends upon.</p> |
| </dd> |
| <dt class="hdlist1">managedServerName</dt> |
| <dd> |
| <p>The name of the Server instance to which to deploy this webapp bundle. |
| If not specified, defaults to the default Server instance called "defaultJettyServer".</p> |
| </dd> |
| <dt class="hdlist1">Jetty-WarFragmentResourcePath</dt> |
| <dd> |
| <p>The path within a fragment hosted by the web-bundle that contains static resources for the webapp. |
| The path is appended to the base resource for the webapp (see Jetty-WarResourcePath).</p> |
| </dd> |
| <dt class="hdlist1">Jetty-WarPrependFragmentResourcePath</dt> |
| <dd> |
| <p>The path within a fragment hosted by the web-bundle that contains static resources for the webapp. |
| The path is prepended to the base resource for the webapp (see Jetty-WarResourcePath).</p> |
| </dd> |
| <dt class="hdlist1">Jetty-ContextFilePath</dt> |
| <dd> |
| <p>A comma separated list of paths within the webapp bundle to Jetty context files that will be applied to the webapp. |
| Alternatively you may include a single Jetty context file called <code>jetty-webapp-context.xml</code> in the webapp bundle’s META-INF directory and it will be automatically applied to the webapp.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="sect4"> |
| <h5>Determining the Context Path for a Webapp Bundle</h5> |
| <div class="paragraph"> |
| <p>As we have seen in the previous section, if the bundle <code>MANIFEST</code> contains the RFC-66 header <strong>Web-ContextPath</strong>, Jetty will use that as the context path. |
| If the <code>MANIFEST</code> does not contain that header, then Jetty will concoct a context path based on the last element of the bundle’s location (by calling <code>Bundle.getLocation()</code>) after stripping off any file extensions.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, suppose we have a bundle whose location is:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">file://some/where/over/the/rainbow/oz.war</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The corresponding synthesized context path would be:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">/oz</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Extra Properties Available for Webapp Bundles</h5> |
| <div class="paragraph"> |
| <p>You can further customize your webapp by including a Jetty context xml file that is applied to the webapp. |
| This xml file must be placed in <code>META-INF</code> of the bundle, and must be called <code>jetty-webapp-context.xml</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example of a webapp bundle listing containing such a file:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">META-INF/MANIFEST.MF |
| META-INF/jetty-webapp-context.xml |
| web/index.html |
| web/foo.html |
| web/WEB-INF/web.xml |
| com/acme/sample/web/MyStuff.class |
| com/acme/sample/web/MyOtherStuff.class</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example of the contents of a <code>META-INF/jetty-webapp-context.xml</code> file:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0" encoding="UTF-8"?> |
| |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| |
| <Configure class="org.eclipse.jetty.webapp.WebAppContext"> |
| <Set name="defaultsDescriptor"><Property name="bundle.root"/>META-INF/webdefault.xml</Set> |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>As you can see, it is a normal context xml file used to set up a webapp. |
| There are, however, some additional useful properties that can be referenced</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Server</dt> |
| <dd> |
| <p>This is a reference to the Jetty <code>org.eclipse.jetty.server.Server</code> instance to which the webapp being configured in the context xml file will be deployed.</p> |
| </dd> |
| <dt class="hdlist1">bundle.root</dt> |
| <dd> |
| <p>This is a reference to the <code>org.eclipse.jetty.util.resource.Resource</code> that represents the location of the Bundle. |
| Note that this could be either a directory in the file system if the OSGi container automatically unpacks bundles, or it may be a jar:file: url if the bundle remains packed.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Deploying Bundles as Jetty ContextHandlers</h4> |
| <div class="paragraph"> |
| <p>In addition to deploying webapps, the Jetty OSGi container listens for the installation of bundles that are not heavyweight webapps, but rather use the flexible Jetty-specific concept of <code>ContextHandlers</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The following is the criteria used to decide if a bundle can be deployed as a <code>ContextHandler</code>:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Bundle MANIFEST contains Jetty-ContextFilePath</dt> |
| <dd> |
| <p>A comma separated list of names of context files - each one of which represents a ContextHandler that should be deployed by Jetty. |
| The context files can be inside the bundle, external to the bundle somewhere on the file system, or external to the bundle in the <strong>jetty.home</strong> directory.</p> |
| <div class="paragraph"> |
| <p>A context file that is inside the bundle:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Jetty-ContextFilePath: ./a/b/c/d/foo.xml</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A context file that is on the file system:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Jetty-ContextFilePath: /opt/app/contexts/foo.xml</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A context file that is relative to jetty.home:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Jetty-ContextFilePath: contexts/foo.xml</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>A number of different context files:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Jetty-ContextFilePath: ./a/b/c/d/foo.xml,/opt/app/contexts/foo.xml,contexts/foo.xml</code></pre> |
| </div> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Other <code>MANIFEST</code> properties that can be used to configure the deployment of the <code>ContextHandler</code>:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">managedServerName</dt> |
| <dd> |
| <p>The name of the Server instance to which to deploy this webapp bundle. |
| If not specified, defaults to the default Server instance called "defaultJettyServer".</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="sect4"> |
| <h5>Determining the Context Path for a ContextHandler Bundle</h5> |
| <div class="paragraph"> |
| <p>Usually, the context path for the ContextHandler will be set by the context xml file. |
| However, you can override any path set in the context xml file by using the <strong>Web-ContextPath</strong> header in the <code>MANIFEST</code>.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Extra Properties Available for Context Xml Files</h5> |
| <div class="paragraph"> |
| <p>Before the Jetty OSGi container applies a context xml file found in a <strong>Jetty-ContextFilePath</strong> <code>MANIFEST</code> header, it sets a few useful propertiesthat can be referred to within the xml file:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Server</dt> |
| <dd> |
| <p>This is a reference to the Jetty <code>org.eclipse.jetty.server.Server</code> instance to which the <code>ContextHandler</code> being configured in the context xml file will be deployed.</p> |
| </dd> |
| <dt class="hdlist1">bundle.root</dt> |
| <dd> |
| <p>This is a reference to the <code>org.eclipse.jetty.util.resource.Resource</code> that represents the location of the Bundle (obtained by calling <code>Bundle.getLocation()</code>). |
| Note that this could be either a directory in the file system if the OSGi container automatically unpacks bundles, or it may be a jar:file: url if the bundle remains packed.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example of a context xml file that makes use of these properties:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| |
| <Configure class="org.eclipse.jetty.server.handler.ContextHandler"> |
| |
| <!-- Get root for static content, could be on file system or this bundle --> |
| <Call id="res" class="org.eclipse.jetty.util.resource.Resource" name="newResource"> |
| <Arg><Property name="bundle.root"/></Arg> |
| </Call> |
| |
| <Ref refid="res"> |
| <Call id="base" name="addPath"> |
| <Arg>/static/</Arg> |
| </Call> |
| </Ref> |
| |
| <Set name="contextPath">/unset</Set> |
| |
| <!-- Set up the base resource for static files relative to inside bundle --> |
| <Set name="baseResource"> |
| <Ref refid="base"/> |
| </Set> |
| |
| <Set name="handler"> |
| <New class="org.eclipse.jetty.server.handler.ResourceHandler"> |
| <Set name="welcomeFiles"> |
| <Array type="String"> |
| <Item>index.html</Item> |
| </Array> |
| </Set> |
| <Set name="cacheControl">max-age=3600,public</Set> |
| </New> |
| </Set> |
| |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="services-as-webapps">Deploying Services as Webapps</h4> |
| <div class="paragraph"> |
| <p>In addition to listening for bundles whose format or <code>MANIFEST</code> entries define a webapp or <code>ContextHandler</code> for to be deployed, the Jetty OSGi container also listens for the registration of OSGi services that are instances of <code>org.eclipse.jetty.webapp.WebAppContext</code>. |
| So you may programmatically create a <code>WebAppContext</code>, register it as a service, and have Jetty pick it up and deploy it.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example of doing that with a simple bundle that serves static content, and an <code>org.osgi.framework.BundleActivator</code> that instantiates the <code>WebAppContext</code>:</p> |
| </div> |
| <div class="paragraph"> |
| <p>The bundle contents:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">META-INF/MANIFEST.MF |
| index.html |
| com/acme/osgi/Activator.class</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>MANIFEST.MF</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Bundle-Classpath: . |
| Bundle-Name: Jetty OSGi Test WebApp |
| DynamicImport-Package: org.eclipse.jetty.*;version="[9.0,10.0)" |
| Bundle-Activator: com.acme.osgi.Activator |
| Import-Package: org.eclipse.jetty.server.handler;version="[9.0,10)", |
| org.eclipse.jetty.webapp;version="[9.0,10)", |
| org.osgi.framework;version= "[1.5,2)", |
| org.osgi.service.cm;version="1.2.0", |
| org.osgi.service.packag eadmin;version="[1.2,2)", |
| org.osgi.service.startlevel;version="1.0.0", |
| org.osgi.service.url;version="1.0.0", |
| org.osgi.util.tracker;version= "1.3.0", |
| org.xml.sax,org.xml.sax.helpers |
| Bundle-SymbolicName: com.acme.testwebapp</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The Activator code:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">public void start(BundleContext context) throws Exception |
| { |
| WebAppContext webapp = new WebAppContext(); |
| Dictionary props = new Hashtable(); |
| props.put("Jetty-WarResourcePath","."); |
| props.put("contextPath","/acme"); |
| context.registerService(WebAppContext.class.getName(),webapp,props); |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The above setup is sufficient for Jetty to recognize and deploy the <code>WebAppContext</code> at /acme.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As the example shows, you can use OSGi Service properties in order to communicate extra configuration information to Jetty:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Jetty-WarFolderPath (for releases prior to 9.3) or Jetty-WarResourcePath</dt> |
| <dd> |
| <p>The location within the bundle of the root of the static resources for the webapp</p> |
| </dd> |
| <dt class="hdlist1">Web-ContextPath</dt> |
| <dd> |
| <p>The context path at which to deploy the webapp.</p> |
| </dd> |
| <dt class="hdlist1">Jetty-defaultWebXmlFilePath</dt> |
| <dd> |
| <p>The location within the bundle of a <code>webdefault.xml</code> file to apply to the webapp. |
| Defaults to that of the Jetty OSGi container.</p> |
| </dd> |
| <dt class="hdlist1">Jetty-WebXmlFilePath</dt> |
| <dd> |
| <p>The location within the bundle of the <code>web.xml</code> file. |
| Defaults to <code>WEB-INF/web.xml</code></p> |
| </dd> |
| <dt class="hdlist1">Jetty-extraClassPath</dt> |
| <dd> |
| <p>A classpath of additional items to add to the webapp’s classloader.</p> |
| </dd> |
| <dt class="hdlist1">Jetty-bundleInstall</dt> |
| <dd> |
| <p>The path to the base folder that overrides the computed bundle installation - mostly useful for those OSGi frameworks that unpack bundles by default.</p> |
| </dd> |
| <dt class="hdlist1">Require-TldBundle</dt> |
| <dd> |
| <p>A comma separated list of bundle symbolic names of bundles containing TLDs that this webapp depends upon.</p> |
| </dd> |
| <dt class="hdlist1">managedServerName</dt> |
| <dd> |
| <p>The name of the Server instance to which to deploy this webapp. |
| If not specified, defaults to the default Server instance called "defaultJettyServer".</p> |
| </dd> |
| <dt class="hdlist1">Jetty-WarFragmentResourcePath</dt> |
| <dd> |
| <p>The path within a fragment hosted by the web-bundle that contains static resources for the webapp. |
| The path is appended to the base resource for the webapp (see Jetty-WarResourcePath).</p> |
| </dd> |
| <dt class="hdlist1">Jetty-WarPrependFragmentResourcePath</dt> |
| <dd> |
| <p>The path within a fragment hosted by the web-bundle that contains static resources for the webapp. |
| The path is prepended to the base resource for the webapp (see Jetty-WarResourcePath).</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Deploying Services as ContextHandlers</h4> |
| <div class="paragraph"> |
| <p>Similarly to WebApp`Contexts, the Jetty OSGi container can detect the registration of an OSGi Service that represents a <code>ContextHandler</code> and ensure that it is deployed. |
| The <code>ContextHandler</code> can either be fully configured before it is registered as an OSGi service - in which case the Jetty OSGi container will merely deploy it - or the <code>ContextHandler</code> can be partially configured, with the Jetty OSGi container completing the configuration via a context xml file and properties associated with the Service.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example of doing that with a simple bundle that serves static content with an <code>org.osgi.framework.BundleActivator</code> that instantiates a <code>ContextHandler</code> and registers it as an OSGi Service, passing in properties that define a context xml file and context path for Jetty to apply upon deployment:</p> |
| </div> |
| <div class="paragraph"> |
| <p>The bundle contents:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">META-INF/MANIFEST.MF |
| static/index.html |
| acme.xml |
| com/acme/osgi/Activator.class |
| com/acme/osgi/Activator$1.class</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>MANIFEST</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Bundle-Classpath: . |
| Bundle-Name: Jetty OSGi Test Context |
| DynamicImport-Package: org.eclipse.jetty.*;version="[9.0,10.0)" |
| Bundle-Activator: com.acme.osgi.Activator |
| Import-Package: javax.servlet;version="2.6.0", |
| javax.servlet.resources;version="2.6.0", |
| org.eclipse.jetty.server.handler;version="[9.0,10)", |
| org.osgi.framework;version="[1.5,2)", |
| org.osgi.service.cm;version="1.2.0", |
| org.osgi.service.packageadmin;version="[1.2,2)", |
| org.osgi.service.startlevel;version="1.0.0.o", |
| org.osgi.service.url;version="1.0.0", |
| org.osgi.util.tracker;version="1.3.0", |
| org.xml.sax,org.xml.sax.helpers |
| Bundle-SymbolicName: com.acme.testcontext</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The Activator code:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">public void start(final BundleContext context) throws Exception |
| { |
| ContextHandler ch = new ContextHandler(); |
| ch.addEventListener(new ServletContextListener () { |
| |
| @Override |
| public void contextInitialized(ServletContextEvent sce) |
| { |
| System.err.println("Context is initialized"); |
| } |
| |
| @Override |
| public void contextDestroyed(ServletContextEvent sce) |
| { |
| System.err.println("Context is destroyed!"); |
| } |
| |
| }); |
| Dictionary props = new Hashtable(); |
| props.put("Web-ContextPath","/acme"); |
| props.put("Jetty-ContextFilePath", "acme.xml"); |
| context.registerService(ContextHandler.class.getName(),ch,props); |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The contents of the <code>acme.xml</code> context file:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| |
| <Configure class="org.eclipse.jetty.server.handler.ContextHandler"> |
| |
| <!-- Get root for static content, could be on file system or this bundle --> |
| <Call id="res" class="org.eclipse.jetty.util.resource.Resource" name="newResource"> |
| <Arg><Property name="bundle.root"/></Arg> |
| </Call> |
| |
| <Ref refid="res"> |
| <Call id="base" name="addPath"> |
| <Arg>/static/</Arg> |
| </Call> |
| </Ref> |
| |
| <Set name="contextPath">/unset</Set> |
| |
| <!-- Set up the base resource for static files relative to inside bundle --> |
| <Set name="baseResource"> |
| <Ref refid="base"/> |
| </Set> |
| |
| <Set name="handler"> |
| <New class="org.eclipse.jetty.server.handler.ResourceHandler"> |
| <Set name="welcomeFiles"> |
| <Array type="String"> |
| <Item>index.html</Item> |
| </Array> |
| </Set> |
| <Set name="cacheControl">max-age=3600,public</Set> |
| </New> |
| </Set> |
| |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You may also use the following OSGi Service properties:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">managedServerName</dt> |
| <dd> |
| <p>The name of the Server instance to which to deploy this webapp. |
| If not specified, defaults to the default Server instance called "defaultJettyServer".</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="sect4"> |
| <h5>Extra Properties Available for Context Xml Files</h5> |
| <div class="paragraph"> |
| <p>Before the Jetty OSGi container applies a context xml file found in a <code>Jetty-ContextFilePath</code> property, it sets a few useful properties that can be referred to within the xml file:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Server</dt> |
| <dd> |
| <p>This is a reference to the Jetty <code>org.eclipse.jetty.server.Server</code> instance to which the <code>ContextHandler</code> being configured in the context xml file will be deployed.</p> |
| </dd> |
| <dt class="hdlist1">bundle.root</dt> |
| <dd> |
| <p>This is a reference to the <code>org.eclipse.jetty.util.resource.Resource</code> that represents the location of the Bundle publishing the <code>ContextHandler</code> as a Service (obtained by calling <code>Bundle.getLocation()</code>). |
| Note that this could be either a directory in the file system if the OSGi container automatically unpacks bundles, or it may be a jar:file: url if the bundle remains packed.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>In the example above, you can see both of these properties being used in the context xml file.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Support for the OSGi Service Platform Enterprise Specification</h4> |
| <div class="paragraph"> |
| <p>The Jetty OSGi container implements several aspects of the Enterprise Specification v4.2 for the <code>WebAppContexts</code> and <code>ContextHandlers</code> that it deploys from either bundles or OSGi services as outlined in foregoing sections.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Context Attributes</h5> |
| <div class="paragraph"> |
| <p>For each <code>WebAppContext</code> or <code>ContextHandler</code>, the following context attribute is set, as required by section <em>128.6.1 Bundle Context</em> page 427:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">osgi-bundleContext</dt> |
| <dd> |
| <p>The value of this attribute is the <code>BundleContext</code> representing the Bundle associated with the <code>WebAppContext</code> or <code>ContextHandler</code>.</p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Service Attributes</h5> |
| <div class="paragraph"> |
| <p>As required by the specification section <em>128.3.4 Publishing the Servlet Context</em> page 421, each <code>WebAppContext</code> and <code>ContextHandler</code> deployed by the Jetty OSGi container is also published as an OSGi service (unless it has been already - see sections 1.6 and 1.7). |
| The following properties are associated with these services:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">osgi.web.symbolicname</dt> |
| <dd> |
| <p>The symbolic name of the Bundle associated with the <code>WebAppContext</code> or <code>ContextHandler</code></p> |
| </dd> |
| <dt class="hdlist1">osgi.web.version</dt> |
| <dd> |
| <p>The Bundle-Version header from the Bundle associated with the <code>WebAppContext</code> or <code>ContextHandler</code></p> |
| </dd> |
| <dt class="hdlist1">osgi.web.contextpath</dt> |
| <dd> |
| <p>The context path of the <code>WebAppContext</code> or <code>ContextHandler</code></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>OSGi Events</h5> |
| <div class="paragraph"> |
| <p>As required by the specification section <em>128.5 Events</em> pg 426, the |
| following OSGi Event Admin events will be posted:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">org/osgi/service/web/DEPLOYING</dt> |
| <dd> |
| <p>The Jetty OSGi container is about to deploy a <code>WebAppContext</code> or <code>ContextHandler</code></p> |
| </dd> |
| <dt class="hdlist1">org/osgi/service/web/DEPLOYED</dt> |
| <dd> |
| <p>The Jetty OSGi container has finished deploying a <code>WebAppContext</code> or <code>ContextHandler</code> and it is in service</p> |
| </dd> |
| <dt class="hdlist1">org/osgi/service/web/UNDEPLOYING</dt> |
| <dd> |
| <p>The Jetty OSGi container is about to undeploy a <code>WebAppContext</code> or <code>ContextHandler</code></p> |
| </dd> |
| <dt class="hdlist1">org/osgi/service/web/UNDEPLOYED</dt> |
| <dd> |
| <p>The Jetty OSGi container has finished undeploying a <code>WebAppContext</code> or <code>ContextHandler</code> and it is no longer in service</p> |
| </dd> |
| <dt class="hdlist1">org/osgi/service/web/FAILED</dt> |
| <dd> |
| <p>The Jetty OSGi container failed to deploy a <code>WebAppContext</code> or <code>ContextHandler</code></p> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Using JSPs</h4> |
| <div class="sect4"> |
| <h5>Setup</h5> |
| <div class="paragraph"> |
| <p>In order to use JSPs with your webapps and bundles you will need to install the JSP and JSTL jars and their dependencies into your OSGi container. |
| Some you will find in the Jetty distribution, whereas others you will need to download from <a href="https://repo1.maven.org/maven2/org/eclipse/jetty/orbit/">Maven central</a>. |
| Here is the list of recommended jars (NOTE the version numbers may change in future):</p> |
| </div> |
| <table id="osgi-jsp" class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 4. Jars Required for JSP</caption> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Jar</th> |
| <th class="tableblock halign-left valign-top">Bundle Symbolic Name</th> |
| <th class="tableblock halign-left valign-top">Location</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The <a href="#osgi-annotations">annotation jars</a></p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.mortbay.jasper:apache-el</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.mortbay.jasper.apache-el</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Distribution lib/apache-jsp</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.mortbay.jasper:apache-jsp</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.mortbay.jasper.apache-jsp</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Distribution lib/apache-jsp</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty:apache-jsp</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.apache-jsp</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Distribution lib/apache-jsp</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jdt.core-3.8.2.v20130121.jar</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jdt.core.compiler.batch</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Distribution lib/apache-jsp</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.osgi:jetty-osgi-boot-jsp</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.osgi.boot.jsp</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://repo1.maven.org/maven2/org/eclipse/jetty/osgi/jetty-osgi-boot-jsp">Maven central</a></p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="olist NOTE"> |
| <ol class="NOTE"> |
| <li> |
| <p>As of Jetty 9.2.3 the jetty-osgi-boot-jsp bundle changed to using Apache Jasper as the JSP implementation. |
| Prior to this the Glassfish Jasper implementation was used, which had a different set of dependencies - pay careful attention to the jars listed both at the top of this page and in this section, as deployment of other jars can cause incomplete or incorrect package resolution in the OSGi container.</p> |
| </li> |
| <li> |
| <p>The order of deployment is important. |
| Deploy these bundles in the order shown or you may experience strange failures in the compilation of jsps. |
| This can be hard to diagnose but is almost always caused by the <code>ServletContainerInitializer</code> in the <code>org.eclipse.jetty.apache-jsp</code> bundle for the jsp container not being invoked due to incorrect startup of the annotation jars.</p> |
| </li> |
| </ol> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>For the JSTL library, we recommend the use of the implementation from Glassfish, as it has fewer dependencies:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 5. Jars Required for Glassfish JSTL</caption> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Jar</th> |
| <th class="tableblock halign-left valign-top">Bundle Symbolic Name</th> |
| <th class="tableblock halign-left valign-top">The <a href="#osgi-jsp">jsp jars</a></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.orbit:javax.servlet.jsp.jstl-1.2.0.v201105211821.jar</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">javax.servlet.jsp.jstl</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>However, if you wish, you may use the JSTL implementation from Apache instead, although you will need to source some dependency jars with suitable OSGi manifests:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 6. Jars Required for Apache JSTL</caption> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Jar</th> |
| <th class="tableblock halign-left valign-top">Bundle Symbolic Name</th> |
| <th class="tableblock halign-left valign-top">Location</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The <a href="#osgi-jsp">jsp jars</a></p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.apache.taglibs:taglibs-standard-spec:jar:1.2.1</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.apache.taglibs.taglibs-standard-spec</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Distribution lib/apache-jstl</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.apache.taglibs:taglibs-standard-spec:jar:1.2.1</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.apache.taglibs.standard-impl</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Distribution lib/apache-jstl</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.apache.xalan 2.7.1</p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Try |
| <a href="http://download.eclipse.org/tools/orbit/downloads/drops/R20140525021250/repository/plugins/org.apache.xalan_2.7.1.v201005080400.jar">Eclipse |
| Orbit</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.apache.xml.serializer 2.7.1</p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Try |
| <a href="http://download.eclipse.org/tools/orbit/downloads/drops/R20140525021250/repository/plugins/org.apache.xml.serializer_2.7.1.v201005080400.jar">Eclipse |
| Orbit</a></p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| <div class="sect4"> |
| <h5>The jetty-osgi-boot-jsp jar</h5> |
| <div class="paragraph"> |
| <p>To be able to use JSPs you will need to also install the <a href="https://repo1.maven.org/maven2/org/eclipse/jetty/osgi/jetty-osgi-boot-jsp/">jetty-osgi-boot-jsp.jar</a> into your OSGi container. |
| This jar can be obtained from maven central <a href="https://repo1.maven.org/maven2/org/eclipse/jetty/osgi/jetty-osgi-boot-jsp/">here</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This bundle acts as a fragment extension to the jetty-osgi-boot.jar and adds in support for using JSP.</p> |
| </div> |
| <div class="sect5"> |
| <h6>Using TagLibs</h6> |
| <div class="paragraph"> |
| <p>The Jetty JSP OSGi container will make available the JSTL tag library to all webapps. |
| If you only use this tag library, then your webapp will work without any further modification.</p> |
| </div> |
| <div class="paragraph"> |
| <p>However, if you make use of other taglibs, you will need to ensure that they are installed into the OSGi container, and also define some System properties and/or <code>MANIFEST</code> headers in your webapp. |
| This is necessary because the classloading regime used by the OSGi container is very different than that used by JSP containers, and the <code>MANIFEST</code> of a normal webapp does not contain enough information for the OSGi environment to allow a JSP container to find and resolve TLDs referenced in the webapp’s .jsp files.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Firstly, lets look at an example of a web bundle’s modified <code>MANIFEST</code> file so you get an idea of what is required. |
| This example is a web bundle that uses the Spring servlet framework:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Bundle-SymbolicName: com.acme.sample |
| Bundle-Name: WebSample |
| Web-ContextPath: taglibs |
| Import-Bundle: org.springframework.web.servlet |
| Require-TldBundle: org.springframework.web.servlet |
| Bundle-Version: 1.0.0 |
| Import-Package: org.eclipse.virgo.web.dm;version="[3.0.0,4.0.0)",org.s |
| pringframework.context.config;version="[2.5.6,4.0.0)",org.springframe |
| work.stereotype;version="[2.5.6,4.0.0)",org.springframework.web.bind. |
| annotation;version="[2.5.6,4.0.0)",org.springframework.web.context;ve |
| rsion="[2.5.6,4.0.0)",org.springframework.web.servlet;version="[2.5.6 |
| ,4.0.0)",org.springframework.web.servlet.view;version="[2.5.6,4.0.0)"</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <strong>Require-TldBundle</strong> header tells the Jetty OSGi container that this bundle contains TLDs that need to be passed over to the JSP container for processing. |
| The <strong>Import-Bundle</strong> header ensures that the implementation classes for these TLDs will be available to the webapp on the OSGi classpath.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The format of the <strong>Require-TldBundle</strong> header is a comma separated list of one or more symbolic names of bundles containing TLDs.</p> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Container Path Taglibs</h6> |
| <div class="paragraph"> |
| <p>Some TLD jars are required to be found on the Jetty OSGi container’s classpath, rather than considered part of the web bundle’s classpath. |
| For example, this is true of JSTL and Java Server Faces. |
| The Jetty OSGi container takes care of JSTL for you, but you can control which other jars are considered as part of the container’s classpath by using the System property <strong>org.eclipse.jetty.osgi.tldbundles</strong>:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">org.eclipse.jetty.osgi.tldbundles</dt> |
| <dd> |
| <p>System property defined on the OSGi environment that is a comma separated list of symbolic names of bundles containing taglibs that will be treated as if they are on the container’s classpath for web bundles. |
| For example:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">org.eclipse.jetty.osgi.tldbundles=com.acme.special.tags,com.foo.web,org.bar.web.framework</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You will still need to define the <strong>Import-Bundle</strong> header in the <code>MANIFEST</code> file for the web bundle to ensure that the TLD bundles are on the OSGi classpath.</p> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Alternatively or additionally, you can define a pattern as a context attribute that will match symbolic bundle names in the OSGi environment containing TLDs that should be considered as discovered from the container’s classpath.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">org.eclipse.jetty.server.webapp.containerIncludeBundlePattern</dt> |
| <dd> |
| <p>This pattern must be specified as a context attribute of the <code>WebAppContext</code> representing the web bundle. |
| Unless you are deploying your own <code>WebAppContext</code> (see <a href="#services-as-webapps">Deploying Services as Webapps</a>), you won’t have a reference to the <code>WebAppContext</code> to do this. |
| In that case, it can be specified on the <code>org.eclipse.jetty.deploy.DeploymentManager</code>, where it will be applied to <em>every</em> webapp deployed by the Jetty OSGi container. |
| The <code>jetty-osgi-boot.jar</code> contains the default <code>jettyhome/etc/jetty-deploy.xml</code> file where the <code>DeploymentManager</code> is defined. |
| To set the pattern, you will need to provide your own etc files - see the section on <a href="#customize-jetty-container">customizing the jetty container</a> for how to do this. Here’s how the <code>jetty-deploy.xml</code> file would look if we defined a pattern that matched all bundle symbolic names ending in "tag" and "web":</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0"?> |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| <Configure id="Server" class="org.eclipse.jetty.server.Server"> |
| <Call name="addBean"> |
| <Arg> |
| <New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager"> |
| <Set name="contexts"> |
| <Ref refid="Contexts" /> |
| </Set> |
| <Call name="setContextAttribute"> |
| <Arg>org.eclipse.jetty.server.webapp.ContainerIncludeBundlePattern</Arg> |
| <Arg>.*\.tag$|.*\.web$</Arg> |
| </Call> |
| </New> |
| </Arg> |
| </Call> |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Again, you will still need to define suitable <strong>Import-Bundle</strong> headers in your web bundle <code>MANIFEST</code> to ensure that bundles matching the pattern are available on the OSGi class path.</p> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="osgi-annotations">Using Annotations/ServletContainerInitializers</h4> |
| <div class="paragraph"> |
| <p>Annotations are very much part of the Servlet 3.0 and 3.1 specifications. |
| In order to use them with Jetty in OSGi, you will need to deploy some extra jars into your OSGi container:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 7. Jars Required for Annotations</caption> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Jar</th> |
| <th class="tableblock halign-left valign-top">Bundle Symbolic Name</th> |
| <th class="tableblock halign-left valign-top">Location</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The <a href="#spifly">spifly jars</a></p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.ow2.asm:asm-7.0.jar</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.objectweb.asm</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://repo1.maven.org/maven2/org/ow2/asm/asm">Maven central</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.ow2.asm:asm-commons-7.0.jar</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.objectweb.asm.commons</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://repo1.maven.org/maven2/org/ow2/asm/asm-commons">Maven central</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.ow2.asm:asm-tree-7.0.jar</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.objectweb.asm.tree</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://repo1.maven.org/maven2/org/ow2/asm/asm-tree">Maven central</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">javax.annotation:javax.annotation-api-1.2.jar</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">javax.annotation-api</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://repo1.maven.org/maven2/javax/annotation/javax.annotation-api/">Maven |
| central</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jta api version 1.1.1 (eg |
| org.apache.geronimo.specs:geronimo-jta_1.1_spec-1.1.1.jar)<sup>*</sup></p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maven |
| central</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">javax mail api version 1.4.1 (eg |
| org.eclipse.jetty.orbit:javax.mail.glassfish-1.4.1.v201005082020.jar)<sup>*</sup></p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Maven central</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-jndi</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.jndi</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Distribution lib/</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-plus</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.plus</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Distribution lib/</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-annotations</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.annotations</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Distribution lib/</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock important"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-important" title="Important"></i> |
| </td> |
| <td class="content"> |
| If you wish to use JSPs you will need to deploy these annotation-related jars. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| You may be able to deploy later versions or other providers of these specifications, however these particular versions are known to have correct manifests and have been tested and known to work with OSGi. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>Even if your webapp itself does not not use annotations, you may need to deploy these jars because your webapp depends on a Jetty module or a 3rd party library that uses a <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html">javax.servlet.ServletContainerInitializer</a>. |
| This interface requires annotation support. |
| It is implemented by providers of code that extend the capabilities of the container. |
| An example of this is the Jetty JSR356 Websocket implementation, although it is being used increasingly commonly in popular libraries like <a href="http://projects.spring.io/spring-framework/">Spring</a>, <a href="https://jersey.java.net/">Jersey</a> and JSP containers.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To find <code>ServletContainerInitializers</code> on the classpath, Jetty uses the Java <a href="http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html"><code>ServiceLoader</code></a> |
| mechanism. |
| For this to function in OSGi, you will need an OSGi R5 compatible container, and have support for the <a href="http://blog.osgi.org/2013/02/javautilserviceloader-in-osgi.html">Service Loader Mediator</a>. |
| Jetty has been tested with the <a href="http://aries.apache.org/modules/spi-fly.html">Aries SpiFly</a> module, which is the reference implementation of the Service Loader Mediator, and is listed in the jars above.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>OSGi Containers</h4> |
| <div class="sect4"> |
| <h5>Felix</h5> |
| <div class="paragraph"> |
| <p>The Jetty OSGi integration has been successfully tested against <a href="http://felix.apache.org/">Felix</a> 5.0.0.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You will require the following extra Felix services, available as separately downloadable jars:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="http://felix.apache.org/documentation/subprojects/apache-felix-config-admin.html">Felix Configuration Admin Service</a></p> |
| </li> |
| <li> |
| <p><a href="http://felix.apache.org/documentation/subprojects/apache-felix-event-admin.html">Felix Event Admin Service</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Unfortunately, as of Felix 4.x there is a difficultly with the resolution of the <code>javax.transaction</code> package. |
| A <a href="http://mail-archives.apache.org/mod_mbox/felix-users/201211.mbox/%3CCAPr=90M+5vYjPqAvyTU+gYHr64y_FosBYELeUYcU_rFEJF3Cxw@mail.gmail.com%3E">description of the problem</a> and hint to solving it is described [<a href="http://mail-archives.apache.org/mod_mbox/felix-users/201211.mbox/%3CCAPr=90M+5vYjPqAvyTU+gYHr64y_FosBYELeUYcU_rFEJF3Cxw@mail.gmail.com%3E">here</a>].</p> |
| </div> |
| <div class="paragraph"> |
| <p>The simplest solution for this is to extract the <code>default.properties</code> file from the <code>felix.jar</code>, change the declaration of the <code>javax.sql</code> and <code>javax.transaction</code> packages and set the changed lines as the value of the <code>org.osgi.framework.system.packages</code> property in the <code>conf/config.properties</code> file.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>default.properties</code> file defines the default <code>org.osgi.framework.system.packages</code> property like this:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-properties" data-lang="properties"># Default packages exported by system bundle. |
| org.osgi.framework.system.packages=org.osgi.framework; version=1.7.0, \ |
| org.osgi.framework.hooks.bundle; version=1.1.0, \ |
| org.osgi.framework.hooks.resolver; version=1.0.0, \ |
| org.osgi.framework.hooks.service; version=1.1.0, \ |
| org.osgi.framework.hooks.weaving; version=1.0.0, \ |
| org.osgi.framework.launch; version=1.1.0, \ |
| org.osgi.framework.namespace; version=1.0.0, \ |
| org.osgi.framework.startlevel; version=1.0.0, \ |
| org.osgi.framework.wiring; version=1.1.0, \ |
| org.osgi.resource; version=1.0.0, \ |
| org.osgi.service.packageadmin; version=1.2.0, \ |
| org.osgi.service.startlevel; version=1.1.0, \ |
| org.osgi.service.url; version=1.0.0, \ |
| org.osgi.util.tracker; version=1.5.1 \ |
| ${jre-${java.specification.version}}</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The last line must be substituted for one of the definitions further down in the file that is suitable for the jvm you are using.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You will take these lines and copy them into the <code>conf/config.properties</code> file, after having replaced the line <code>$\{jre-$\{java.specification.version}}</code> with all of the lines relevant to your version of the jvm.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, for a 1.7 jvm, you will find this property definition:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-properties" data-lang="properties">jre-1.7=, \ |
| javax.accessibility;uses:="javax.swing.text";version="0.0.0.1_007_JavaSE", \ |
| javax.activation;version="0.0.0.1_007_JavaSE", \ |
| javax.activity;version="0.0.0.1_007_JavaSE", \ |
| javax.annotation.processing;uses:="javax.tools,javax.lang.model,javax.lang.model.element,javax.lang.model.util";version="0.0.0.1_007_JavaSE", \ |
| javax.annotation;version="0.0.0.1_007_JavaSE", \ |
| javax.crypto.interfaces;uses:="javax.crypto.spec,javax.crypto";version="0.0.0.1_007_JavaSE", \ |
| javax.crypto.spec;uses:="javax.crypto";version="0.0.0.1_007_JavaSE", \ |
| javax.crypto;uses:="javax.crypto.spec";version="0.0.0.1_007_JavaSE", \ |
| javax.imageio.event;uses:="javax.imageio";version="0.0.0.1_007_JavaSE", \ |
| javax.imageio.metadata;uses:="org.w3c.dom,javax.imageio";version="0.0.0.1_007_JavaSE", \ |
| javax.imageio.plugins.bmp;uses:="javax.imageio";version="0.0.0.1_007_JavaSE", \ |
| javax.imageio.plugins.jpeg;uses:="javax.imageio";version="0.0.0.1_007_JavaSE", \ |
| javax.imageio.spi;uses:="javax.imageio.stream,javax.imageio,javax.imageio.metadata";version="0.0.0.1_007_JavaSE", \ |
| javax.imageio.stream;uses:="javax.imageio";version="0.0.0.1_007_JavaSE", \ |
| javax.imageio;uses:="javax.imageio.metadata,javax.imageio.stream,javax.imageio.spi,javax.imageio.event";version="0.0.0.1_007_JavaSE", \ |
| javax.jws.soap;version="0.0.0.1_007_JavaSE", \ |
| javax.jws;version="0.0.0.1_007_JavaSE", \ |
| javax.lang.model.element;uses:="javax.lang.model.type,javax.lang.model";version="0.0.0.1_007_JavaSE", \ |
| javax.lang.model.type;uses:="javax.lang.model.element,javax.lang.model";version="0.0.0.1_007_JavaSE", \ |
| javax.lang.model.util;uses:="javax.lang.model,javax.lang.model.element,javax.annotation.processing,javax.lang.model.type";version="0.0.0.1_007_JavaSE", \ |
| javax.lang.model;version="0.0.0.1_007_JavaSE", \ |
| javax.management.loading;uses:="javax.management";version="0.0.0.1_007_JavaSE", \ |
| javax.management.modelmbean;uses:="javax.management,javax.management.loading";version="0.0.0.1_007_JavaSE", \ |
| javax.management.monitor;uses:="javax.management";version="0.0.0.1_007_JavaSE", \ |
| javax.management.openmbean;uses:="javax.management";version="0.0.0.1_007_JavaSE", \ |
| javax.management.relation;uses:="javax.management";version="0.0.0.1_007_JavaSE", \ |
| javax.management.remote.rmi;uses:="javax.management.remote,javax.security.auth,javax.management,javax.management.loading,javax.naming,javax.rmi.ssl,org.omg.CORBA,org.omg.CORBA_2_3.portable,org.omg.CORBA.portable,javax.rmi.CORBA,javax.rmi";version="0.0.0.1_007_JavaSE", \ |
| javax.management.remote;uses:="javax.security.auth,javax.management";version="0.0.0.1_007_JavaSE", \ |
| javax.management.timer;uses:="javax.management";version="0.0.0.1_007_JavaSE", \ |
| javax.management;uses:="javax.management.loading,javax.management.openmbean";version="0.0.0.1_007_JavaSE", \ |
| javax.naming.directory;uses:="javax.naming";version="0.0.0.1_007_JavaSE", \ |
| javax.naming.event;uses:="javax.naming,javax.naming.directory";version="0.0.0.1_007_JavaSE", \ |
| javax.naming.ldap;uses:="javax.naming,javax.naming.directory,javax.net.ssl,javax.naming.event";version="0.0.0.1_007_JavaSE", \ |
| javax.naming.spi;uses:="javax.naming,javax.naming.directory";version="0.0.0.1_007_JavaSE", \ |
| javax.naming;uses:="javax.naming.spi";version="0.0.0.1_007_JavaSE", \ |
| javax.net.ssl;uses:="javax.security.cert,javax.security.auth.x500,javax.net";version="0.0.0.1_007_JavaSE", \ |
| javax.net;version="0.0.0.1_007_JavaSE", \ |
| javax.print.attribute.standard;uses:="javax.print.attribute";version="0.0.0.1_007_JavaSE", \ |
| javax.print.attribute;version="0.0.0.1_007_JavaSE", \ |
| javax.print.event;uses:="javax.print,javax.print.attribute";version="0.0.0.1_007_JavaSE", \ |
| javax.print;uses:="javax.print.attribute,javax.print.event,javax.print.attribute.standard";version="0.0.0.1_007_JavaSE", \ |
| javax.rmi.CORBA;uses:="org.omg.CORBA,org.omg.CORBA_2_3.portable,org.omg.CORBA.portable,org.omg.SendingContext";version="0.0.0.1_007_JavaSE", \ |
| javax.rmi.ssl;uses:="javax.net,javax.net.ssl";version="0.0.0.1_007_JavaSE", \ |
| javax.rmi;uses:="org.omg.CORBA,javax.rmi.CORBA";version="0.0.0.1_007_JavaSE", \ |
| javax.script;version="0.0.0.1_007_JavaSE", \ |
| javax.security.auth.callback;version="0.0.0.1_007_JavaSE", \ |
| javax.security.auth.kerberos;uses:="javax.security.auth,javax.crypto";version="0.0.0.1_007_JavaSE", \ |
| javax.security.auth.login;uses:="javax.security.auth,javax.security.auth.callback";version="0.0.0.1_007_JavaSE", \ |
| javax.security.auth.spi;uses:="javax.security.auth.callback,javax.security.auth.login,javax.security.auth";version="0.0.0.1_007_JavaSE", \ |
| javax.security.auth.x500;uses:="javax.security.auth";version="0.0.0.1_007_JavaSE", \ |
| javax.security.auth;version="0.0.0.1_007_JavaSE", \ |
| javax.security.cert;version="0.0.0.1_007_JavaSE", \ |
| javax.security.sasl;uses:="javax.security.auth.callback";version="0.0.0.1_007_JavaSE", \ |
| javax.sound.midi.spi;uses:="javax.sound.midi";version="0.0.0.1_007_JavaSE", \ |
| javax.sound.midi;uses:="javax.sound.midi.spi";version="0.0.0.1_007_JavaSE", \ |
| javax.sound.sampled.spi;uses:="javax.sound.sampled";version="0.0.0.1_007_JavaSE", \ |
| javax.sound.sampled;uses:="javax.sound.sampled.spi";version="0.0.0.1_007_JavaSE", \ |
| javax.sql.rowset.serial;uses:="javax.sql.rowset";version="0.0.0.1_007_JavaSE", \ |
| javax.sql.rowset.spi;uses:="javax.sql,javax.naming,javax.sql.rowset";version="0.0.0.1_007_JavaSE", \ |
| javax.sql.rowset;uses:="javax.sql,javax.sql.rowset.serial,javax.sql.rowset.spi";version="0.0.0.1_007_JavaSE", \ |
| javax.sql;uses:="javax.transaction.xa";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.border;uses:="javax.swing";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.colorchooser;uses:="javax.swing,javax.swing.border,javax.swing.event,javax.swing.text";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.event;uses:="javax.swing,javax.swing.text,javax.swing.table,javax.swing.tree,javax.swing.undo";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.filechooser;uses:="javax.swing";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.plaf.basic;uses:="javax.swing.border,javax.swing,javax.swing.plaf,javax.swing.text,javax.swing.event,javax.swing.colorchooser,javax.accessibility,javax.swing.filechooser,javax.swing.text.html,javax.sound.sampled,javax.swing.table,javax.swing.plaf.synth,javax.swing.tree";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.plaf.metal;uses:="javax.swing.plaf,javax.swing,javax.swing.border,javax.swing.text,javax.swing.plaf.basic,javax.swing.filechooser,javax.swing.event,javax.swing.tree";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.plaf.multi;uses:="javax.accessibility,javax.swing,javax.swing.plaf,javax.swing.filechooser,javax.swing.text,javax.swing.tree";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.plaf.nimbus;uses:="javax.swing,javax.swing.plaf,javax.swing.border,javax.swing.plaf.synth";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.plaf.synth;uses:="javax.swing,javax.swing.plaf,javax.swing.text,javax.swing.border,javax.swing.plaf.basic,javax.swing.colorchooser,javax.swing.event,javax.xml.parsers,org.xml.sax,org.xml.sax.helpers,javax.swing.table,javax.swing.tree";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.plaf;uses:="javax.swing,javax.swing.border,javax.accessibility,javax.swing.filechooser,javax.swing.text,javax.swing.tree";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.table;uses:="javax.swing.event,javax.swing.plaf,javax.swing.border,javax.swing,javax.accessibility";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.text.html.parser;uses:="javax.swing.text,javax.swing.text.html";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.text.html;uses:="javax.swing.event,javax.swing.text,javax.accessibility,javax.swing,javax.swing.plaf,javax.swing.border,javax.swing.undo";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.text.rtf;uses:="javax.swing.text";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.text;uses:="javax.swing.event,javax.swing.tree,javax.swing.undo,javax.swing,javax.swing.plaf,javax.swing.plaf.basic,javax.print,javax.print.attribute,javax.accessibility,javax.swing.text.html";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.tree;uses:="javax.swing.event,javax.swing,javax.swing.border,javax.swing.plaf,javax.swing.plaf.basic";version="0.0.0.1_007_JavaSE", \ |
| javax.swing.undo;uses:="javax.swing,javax.swing.event";version="0.0.0.1_007_JavaSE", \ |
| javax.swing;uses:="javax.swing.event,javax.accessibility,javax.swing.text,javax.swing.plaf,javax.swing.border,javax.swing.tree,javax.swing.table,javax.swing.colorchooser,javax.swing.plaf.basic,javax.swing.text.html,javax.swing.filechooser,javax.print,javax.print.attribute,javax.swing.plaf.metal";version="0.0.0.1_007_JavaSE", \ |
| javax.tools;uses:="javax.lang.model.element,javax.annotation.processing,javax.lang.model";version="0.0.0.1_007_JavaSE", \ |
| javax.transaction.xa;version="0.0.0.1_007_JavaSE", \ |
| javax.transaction;version="0.0.0.1_007_JavaSE", \ |
| javax.xml.bind.annotation.adapters;uses:="javax.xml.bind";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.bind.annotation;uses:="javax.xml.transform,javax.xml.bind,javax.xml.parsers,javax.xml.transform.dom,org.w3c.dom";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.bind.attachment;uses:="javax.activation";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.bind.helpers;uses:="javax.xml.bind.annotation.adapters,javax.xml.transform.dom,org.w3c.dom,org.xml.sax,javax.xml.bind.attachment,javax.xml.stream,javax.xml.transform,javax.xml.transform.stream,javax.xml.validation,javax.xml.transform.sax,javax.xml.bind,javax.xml.parsers";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.bind.util;uses:="javax.xml.transform.sax,javax.xml.bind,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.bind;uses:="javax.xml.validation,javax.xml.namespace,javax.xml.datatype,javax.xml.transform,javax.xml.bind.annotation,javax.xml.transform.stream,org.w3c.dom,javax.xml.bind.attachment,javax.xml.stream,javax.xml.bind.annotation.adapters,org.xml.sax";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.crypto.dom;uses:="javax.xml.crypto,org.w3c.dom";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.crypto.dsig.dom;uses:="javax.xml.crypto.dsig,javax.xml.crypto,org.w3c.dom,javax.xml.crypto.dom";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.crypto.dsig.keyinfo;uses:="javax.xml.crypto";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.crypto.dsig.spec;uses:="javax.xml.crypto";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.crypto.dsig;uses:="javax.xml.crypto,javax.xml.crypto.dsig.spec,javax.xml.crypto.dsig.keyinfo";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.crypto;uses:="javax.xml.crypto.dsig.keyinfo";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.datatype;uses:="javax.xml.namespace";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.namespace;version="0.0.0.1_007_JavaSE", \ |
| javax.xml.parsers;uses:="javax.xml.validation,org.w3c.dom,org.xml.sax,org.xml.sax.helpers";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.soap;uses:="javax.activation,javax.xml.namespace,org.w3c.dom,javax.xml.transform.dom,javax.xml.transform";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.stream.events;uses:="javax.xml.namespace,javax.xml.stream";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.stream.util;uses:="javax.xml.stream,javax.xml.stream.events,javax.xml.namespace";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.stream;uses:="javax.xml.stream.events,javax.xml.namespace,javax.xml.stream.util,javax.xml.transform";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.transform.dom;uses:="javax.xml.transform,org.w3c.dom";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.transform.sax;uses:="org.xml.sax.ext,javax.xml.transform,org.xml.sax,javax.xml.transform.stream";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.transform.stax;uses:="javax.xml.stream,javax.xml.transform,javax.xml.stream.events";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.transform.stream;uses:="javax.xml.transform";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.transform;version="0.0.0.1_007_JavaSE", \ |
| javax.xml.validation;uses:="org.w3c.dom.ls,javax.xml.transform,javax.xml.transform.stream,org.xml.sax,org.w3c.dom";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.ws.handler.soap;uses:="javax.xml.ws.handler,javax.xml.namespace,javax.xml.soap,javax.xml.bind";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.ws.handler;uses:="javax.xml.ws,javax.xml.namespace";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.ws.http;uses:="javax.xml.ws";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.ws.soap;uses:="javax.xml.ws.spi,javax.xml.ws,javax.xml.soap";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.ws.spi.http;version="0.0.0.1_007_JavaSE", \ |
| javax.xml.ws.spi;uses:="javax.xml.ws,javax.xml.ws.wsaddressing,javax.xml.transform,org.w3c.dom,javax.xml.namespace,javax.xml.ws.handler,javax.xml.bind";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.ws.wsaddressing;uses:="javax.xml.bind.annotation,javax.xml.namespace,org.w3c.dom,javax.xml.transform,javax.xml.bind,javax.xml.ws,javax.xml.ws.spi";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.ws;uses:="javax.xml.ws.handler,javax.xml.ws.spi,javax.xml.ws.spi.http,javax.xml.transform,org.w3c.dom,javax.xml.bind.annotation,javax.xml.transform.stream,javax.xml.bind,javax.xml.namespace";version="0.0.0.1_007_JavaSE", \ |
| javax.xml.xpath;uses:="org.xml.sax,javax.xml.namespace";version="0.0.0.1_007_JavaSE", \ |
| javax.xml;version="0.0.0.1_007_JavaSE", \ |
| org.ietf.jgss;version="0.0.0.1_007_JavaSE", \ |
| org.omg.CORBA.DynAnyPackage;uses:="org.omg.CORBA";version="0.0.0.1_007_JavaSE", \ |
| org.omg.CORBA.ORBPackage;uses:="org.omg.CORBA";version="0.0.0.1_007_JavaSE", \ |
| org.omg.CORBA.TypeCodePackage;uses:="org.omg.CORBA";version="0.0.0.1_007_JavaSE", \ |
| org.omg.CORBA.portable;uses:="org.omg.CORBA,org.omg.CORBA_2_3.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.CORBA;uses:="org.omg.CORBA.portable,org.omg.CORBA.DynAnyPackage,org.omg.CORBA.ORBPackage,org.omg.CORBA_2_3.portable,org.omg.CORBA.TypeCodePackage";version="0.0.0.1_007_JavaSE", \ |
| org.omg.CORBA_2_3.portable;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.CORBA_2_3;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.CosNaming.NamingContextExtPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.CosNaming.NamingContextPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.CosNaming";version="0.0.0.1_007_JavaSE", \ |
| org.omg.CosNaming;uses:="org.omg.CORBA.portable,org.omg.CORBA,org.omg.PortableServer,org.omg.CosNaming.NamingContextPackage,org.omg.CosNaming.NamingContextExtPackage";version="0.0.0.1_007_JavaSE", \ |
| org.omg.Dynamic;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.DynamicAny.DynAnyFactoryPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.DynamicAny.DynAnyPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.DynamicAny;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.DynamicAny.DynAnyFactoryPackage,org.omg.DynamicAny.DynAnyPackage";version="0.0.0.1_007_JavaSE", \ |
| org.omg.IOP.CodecFactoryPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.IOP.CodecPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.IOP;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.IOP.CodecFactoryPackage,org.omg.IOP.CodecPackage";version="0.0.0.1_007_JavaSE", \ |
| org.omg.Messaging;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.PortableInterceptor.ORBInitInfoPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.PortableInterceptor;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.IOP,org.omg.PortableInterceptor.ORBInitInfoPackage,org.omg.CORBA_2_3.portable,org.omg.Dynamic";version="0.0.0.1_007_JavaSE", \ |
| org.omg.PortableServer.CurrentPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.PortableServer.POAManagerPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.PortableServer.POAPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.PortableServer.ServantLocatorPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.PortableServer.portable;uses:="org.omg.CORBA,org.omg.PortableServer";version="0.0.0.1_007_JavaSE", \ |
| org.omg.PortableServer;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.PortableServer.CurrentPackage,org.omg.PortableServer.POAManagerPackage,org.omg.PortableServer.POAPackage,org.omg.PortableServer.portable,org.omg.CORBA_2_3,org.omg.PortableServer.ServantLocatorPackage";version="0.0.0.1_007_JavaSE", \ |
| org.omg.SendingContext;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", \ |
| org.omg.stub.java.rmi;uses:="javax.rmi.CORBA";version="0.0.0.1_007_JavaSE", \ |
| org.w3c.dom.bootstrap;uses:="org.w3c.dom";version="0.0.0.1_007_JavaSE", \ |
| org.w3c.dom.events;uses:="org.w3c.dom,org.w3c.dom.views";version="0.0.0.1_007_JavaSE", \ |
| org.w3c.dom.ls;uses:="org.w3c.dom,org.w3c.dom.events,org.w3c.dom.traversal";version="0.0.0.1_007_JavaSE", \ |
| org.w3c.dom;version="0.0.0.1_007_JavaSE", \ |
| org.xml.sax.ext;uses:="org.xml.sax,org.xml.sax.helpers";version="0.0.0.1_007_JavaSE", \ |
| org.xml.sax.helpers;uses:="org.xml.sax";version="0.0.0.1_007_JavaSE", \ |
| org.xml.sax;version="0.0.0.1_007_JavaSE"</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Remove the definition for the <code>javax.transaction</code> packages, and remove the <code>uses:=</code> clause for the <code>javax.sql</code> packages (but leaving the <code>version</code> clause). Concatenate all the lines together. |
| You’ll wind up with something like this in your <code>conf/config.properties</code> file:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-properties" data-lang="properties">org.osgi.framework.system.packages=org.osgi.framework;version=1.7.0, org.osgi.framework.hooks.bundle;version=1.1.0, org.osgi.framework.hooks.resolver;version=1.0.0, org.osgi.framework.hooks.service;version=1.1.0, org.osgi.framework.hooks.weaving;version=1.0.0, org.osgi.framework.launch;version=1.1.0, org.osgi.framework.namespace;version=1.0.0, org.osgi.framework.startlevel;version=1.0.0, org.osgi.framework.wiring;version=1.1.0, org.osgi.resource;version=1.0.0, org.osgi.service.packageadmin; version=1.2.0, org.osgi.service.startlevel; version=1.1.0, org.osgi.service.url;version=1.0.0, org.osgi.util.tracker;version=1.5.1 javax.accessibility;uses:="javax.swing.text";version="0.0.0.1_007_JavaSE", javax.activation;version="0.0.0.1_007_JavaSE", javax.activity;version="0.0.0.1_007_JavaSE", javax.annotation.processing;uses:="javax.tools,javax.lang.model,javax.lang.model.element,javax.lang.model.util";version="0.0.0.1_007_JavaSE", javax.annotation;version="0.0.0.1_007_JavaSE", javax.crypto.interfaces;uses:="javax.crypto.spec,javax.crypto";version="0.0.0.1_007_JavaSE", javax.crypto.spec;uses:="javax.crypto";version="0.0.0.1_007_JavaSE", javax.crypto;uses:="javax.crypto.spec";version="0.0.0.1_007_JavaSE", javax.imageio.event;uses:="javax.imageio";version="0.0.0.1_007_JavaSE", javax.imageio.metadata;uses:="org.w3c.dom,javax.imageio";version="0.0.0.1_007_JavaSE", javax.imageio.plugins.bmp;uses:="javax.imageio";version="0.0.0.1_007_JavaSE", javax.imageio.plugins.jpeg;uses:="javax.imageio";version="0.0.0.1_007_JavaSE", javax.imageio.spi;uses:="javax.imageio.stream,javax.imageio,javax.imageio.metadata";version="0.0.0.1_007_JavaSE", javax.imageio.stream;uses:="javax.imageio";version="0.0.0.1_007_JavaSE", javax.imageio;uses:="javax.imageio.metadata,javax.imageio.stream,javax.imageio.spi,javax.imageio.event";version="0.0.0.1_007_JavaSE", javax.jws.soap;version="0.0.0.1_007_JavaSE", javax.jws;version="0.0.0.1_007_JavaSE", javax.lang.model.element;uses:="javax.lang.model.type,javax.lang.model";version="0.0.0.1_007_JavaSE", javax.lang.model.type;uses:="javax.lang.model.element,javax.lang.model";version="0.0.0.1_007_JavaSE", javax.lang.model.util;uses:="javax.lang.model,javax.lang.model.element,javax.annotation.processing,javax.lang.model.type";version="0.0.0.1_007_JavaSE", javax.lang.model;version="0.0.0.1_007_JavaSE", javax.management.loading;uses:="javax.management";version="0.0.0.1_007_JavaSE", javax.management.modelmbean;uses:="javax.management,javax.management.loading";version="0.0.0.1_007_JavaSE", javax.management.monitor;uses:="javax.management";version="0.0.0.1_007_JavaSE", javax.management.openmbean;uses:="javax.management";version="0.0.0.1_007_JavaSE", javax.management.relation;uses:="javax.management";version="0.0.0.1_007_JavaSE", javax.management.remote.rmi;uses:="javax.management.remote,javax.security.auth,javax.management,javax.management.loading,javax.naming,javax.rmi.ssl,org.omg.CORBA,org.omg.CORBA_2_3.portable,org.omg.CORBA.portable,javax.rmi.CORBA,javax.rmi";version="0.0.0.1_007_JavaSE", javax.management.remote;uses:="javax.security.auth,javax.management";version="0.0.0.1_007_JavaSE", javax.management.timer;uses:="javax.management";version="0.0.0.1_007_JavaSE", javax.management;uses:="javax.management.loading,javax.management.openmbean";version="0.0.0.1_007_JavaSE", javax.naming.directory;uses:="javax.naming";version="0.0.0.1_007_JavaSE", javax.naming.event;uses:="javax.naming,javax.naming.directory";version="0.0.0.1_007_JavaSE", javax.naming.ldap;uses:="javax.naming,javax.naming.directory,javax.net.ssl,javax.naming.event";version="0.0.0.1_007_JavaSE", javax.naming.spi;uses:="javax.naming,javax.naming.directory";version="0.0.0.1_007_JavaSE", javax.naming;uses:="javax.naming.spi";version="0.0.0.1_007_JavaSE", javax.net.ssl;uses:="javax.security.cert,javax.security.auth.x500,javax.net";version="0.0.0.1_007_JavaSE", javax.net;version="0.0.0.1_007_JavaSE", javax.print.attribute.standard;uses:="javax.print.attribute";version="0.0.0.1_007_JavaSE", javax.print.attribute;version="0.0.0.1_007_JavaSE", javax.print.event;uses:="javax.print,javax.print.attribute";version="0.0.0.1_007_JavaSE", javax.print;uses:="javax.print.attribute,javax.print.event,javax.print.attribute.standard";version="0.0.0.1_007_JavaSE", javax.rmi.CORBA;uses:="org.omg.CORBA,org.omg.CORBA_2_3.portable,org.omg.CORBA.portable,org.omg.SendingContext";version="0.0.0.1_007_JavaSE", javax.rmi.ssl;uses:="javax.net,javax.net.ssl";version="0.0.0.1_007_JavaSE", javax.rmi;uses:="org.omg.CORBA,javax.rmi.CORBA";version="0.0.0.1_007_JavaSE", javax.script;version="0.0.0.1_007_JavaSE", javax.security.auth.callback;version="0.0.0.1_007_JavaSE", javax.security.auth.kerberos;uses:="javax.security.auth,javax.crypto";version="0.0.0.1_007_JavaSE", javax.security.auth.login;uses:="javax.security.auth,javax.security.auth.callback";version="0.0.0.1_007_JavaSE", javax.security.auth.spi;uses:="javax.security.auth.callback,javax.security.auth.login,javax.security.auth";version="0.0.0.1_007_JavaSE", javax.security.auth.x500;uses:="javax.security.auth";version="0.0.0.1_007_JavaSE", javax.security.auth;version="0.0.0.1_007_JavaSE", javax.security.cert;version="0.0.0.1_007_JavaSE", javax.security.sasl;uses:="javax.security.auth.callback";version="0.0.0.1_007_JavaSE", javax.sound.midi.spi;uses:="javax.sound.midi";version="0.0.0.1_007_JavaSE", javax.sound.midi;uses:="javax.sound.midi.spi";version="0.0.0.1_007_JavaSE", javax.sound.sampled.spi;uses:="javax.sound.sampled";version="0.0.0.1_007_JavaSE", javax.sound.sampled;uses:="javax.sound.sampled.spi";version="0.0.0.1_007_JavaSE", javax.sql.rowset.serial;version="0.0.0.1_007_JavaSE", javax.sql.rowset.spi;version="0.0.0.1_007_JavaSE", javax.sql.rowset;version="0.0.0.1_007_JavaSE", javax.sql;version="0.0.0.1_007_JavaSE", javax.swing.border;uses:="javax.swing";version="0.0.0.1_007_JavaSE", javax.swing.colorchooser;uses:="javax.swing,javax.swing.border,javax.swing.event,javax.swing.text";version="0.0.0.1_007_JavaSE", javax.swing.event;uses:="javax.swing,javax.swing.text,javax.swing.table,javax.swing.tree,javax.swing.undo";version="0.0.0.1_007_JavaSE", javax.swing.filechooser;uses:="javax.swing";version="0.0.0.1_007_JavaSE", javax.swing.plaf.basic;uses:="javax.swing.border,javax.swing,javax.swing.plaf,javax.swing.text,javax.swing.event,javax.swing.colorchooser,javax.accessibility,javax.swing.filechooser,javax.swing.text.html,javax.sound.sampled,javax.swing.table,javax.swing.plaf.synth,javax.swing.tree";version="0.0.0.1_007_JavaSE", javax.swing.plaf.metal;uses:="javax.swing.plaf,javax.swing,javax.swing.border,javax.swing.text,javax.swing.plaf.basic,javax.swing.filechooser,javax.swing.event,javax.swing.tree";version="0.0.0.1_007_JavaSE", javax.swing.plaf.multi;uses:="javax.accessibility,javax.swing,javax.swing.plaf,javax.swing.filechooser,javax.swing.text,javax.swing.tree";version="0.0.0.1_007_JavaSE", javax.swing.plaf.nimbus;uses:="javax.swing,javax.swing.plaf,javax.swing.border,javax.swing.plaf.synth";version="0.0.0.1_007_JavaSE", javax.swing.plaf.synth;uses:="javax.swing,javax.swing.plaf,javax.swing.text,javax.swing.border,javax.swing.plaf.basic,javax.swing.colorchooser,javax.swing.event,javax.xml.parsers,org.xml.sax,org.xml.sax.helpers,javax.swing.table,javax.swing.tree";version="0.0.0.1_007_JavaSE", javax.swing.plaf;uses:="javax.swing,javax.swing.border,javax.accessibility,javax.swing.filechooser,javax.swing.text,javax.swing.tree";version="0.0.0.1_007_JavaSE", javax.swing.table;uses:="javax.swing.event,javax.swing.plaf,javax.swing.border,javax.swing,javax.accessibility";version="0.0.0.1_007_JavaSE", javax.swing.text.html.parser;uses:="javax.swing.text,javax.swing.text.html";version="0.0.0.1_007_JavaSE", javax.swing.text.html;uses:="javax.swing.event,javax.swing.text,javax.accessibility,javax.swing,javax.swing.plaf,javax.swing.border,javax.swing.undo";version="0.0.0.1_007_JavaSE", javax.swing.text.rtf;uses:="javax.swing.text";version="0.0.0.1_007_JavaSE", javax.swing.text;uses:="javax.swing.event,javax.swing.tree,javax.swing.undo,javax.swing,javax.swing.plaf,javax.swing.plaf.basic,javax.print,javax.print.attribute,javax.accessibility,javax.swing.text.html";version="0.0.0.1_007_JavaSE", javax.swing.tree;uses:="javax.swing.event,javax.swing,javax.swing.border,javax.swing.plaf,javax.swing.plaf.basic";version="0.0.0.1_007_JavaSE", javax.swing.undo;uses:="javax.swing,javax.swing.event";version="0.0.0.1_007_JavaSE", javax.swing;uses:="javax.swing.event,javax.accessibility,javax.swing.text,javax.swing.plaf,javax.swing.border,javax.swing.tree,javax.swing.table,javax.swing.colorchooser,javax.swing.plaf.basic,javax.swing.text.html,javax.swing.filechooser,javax.print,javax.print.attribute,javax.swing.plaf.metal";version="0.0.0.1_007_JavaSE", javax.tools;uses:="javax.lang.model.element,javax.annotation.processing,javax.lang.model";version="0.0.0.1_007_JavaSE", javax.xml.bind.annotation.adapters;uses:="javax.xml.bind";version="0.0.0.1_007_JavaSE", javax.xml.bind.annotation;uses:="javax.xml.transform,javax.xml.bind,javax.xml.parsers,javax.xml.transform.dom,org.w3c.dom";version="0.0.0.1_007_JavaSE", javax.xml.bind.attachment;uses:="javax.activation";version="0.0.0.1_007_JavaSE", javax.xml.bind.helpers;uses:="javax.xml.bind.annotation.adapters,javax.xml.transform.dom,org.w3c.dom,org.xml.sax,javax.xml.bind.attachment,javax.xml.stream,javax.xml.transform,javax.xml.transform.stream,javax.xml.validation,javax.xml.transform.sax,javax.xml.bind,javax.xml.parsers";version="0.0.0.1_007_JavaSE", javax.xml.bind.util;uses:="javax.xml.transform.sax,javax.xml.bind,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers";version="0.0.0.1_007_JavaSE", javax.xml.bind;uses:="javax.xml.validation,javax.xml.namespace,javax.xml.datatype,javax.xml.transform,javax.xml.bind.annotation,javax.xml.transform.stream,org.w3c.dom,javax.xml.bind.attachment,javax.xml.stream,javax.xml.bind.annotation.adapters,org.xml.sax";version="0.0.0.1_007_JavaSE", javax.xml.crypto.dom;uses:="javax.xml.crypto,org.w3c.dom";version="0.0.0.1_007_JavaSE", javax.xml.crypto.dsig.dom;uses:="javax.xml.crypto.dsig,javax.xml.crypto,org.w3c.dom,javax.xml.crypto.dom";version="0.0.0.1_007_JavaSE", javax.xml.crypto.dsig.keyinfo;uses:="javax.xml.crypto";version="0.0.0.1_007_JavaSE", javax.xml.crypto.dsig.spec;uses:="javax.xml.crypto";version="0.0.0.1_007_JavaSE", javax.xml.crypto.dsig;uses:="javax.xml.crypto,javax.xml.crypto.dsig.spec,javax.xml.crypto.dsig.keyinfo";version="0.0.0.1_007_JavaSE", javax.xml.crypto;uses:="javax.xml.crypto.dsig.keyinfo";version="0.0.0.1_007_JavaSE", javax.xml.datatype;uses:="javax.xml.namespace";version="0.0.0.1_007_JavaSE", javax.xml.namespace;version="0.0.0.1_007_JavaSE", javax.xml.parsers;uses:="javax.xml.validation,org.w3c.dom,org.xml.sax,org.xml.sax.helpers";version="0.0.0.1_007_JavaSE", javax.xml.soap;uses:="javax.activation,javax.xml.namespace,org.w3c.dom,javax.xml.transform.dom,javax.xml.transform";version="0.0.0.1_007_JavaSE", javax.xml.stream.events;uses:="javax.xml.namespace,javax.xml.stream";version="0.0.0.1_007_JavaSE", javax.xml.stream.util;uses:="javax.xml.stream,javax.xml.stream.events,javax.xml.namespace";version="0.0.0.1_007_JavaSE", javax.xml.stream;uses:="javax.xml.stream.events,javax.xml.namespace,javax.xml.stream.util,javax.xml.transform";version="0.0.0.1_007_JavaSE", javax.xml.transform.dom;uses:="javax.xml.transform,org.w3c.dom";version="0.0.0.1_007_JavaSE", javax.xml.transform.sax;uses:="org.xml.sax.ext,javax.xml.transform,org.xml.sax,javax.xml.transform.stream";version="0.0.0.1_007_JavaSE", javax.xml.transform.stax;uses:="javax.xml.stream,javax.xml.transform,javax.xml.stream.events";version="0.0.0.1_007_JavaSE", javax.xml.transform.stream;uses:="javax.xml.transform";version="0.0.0.1_007_JavaSE", javax.xml.transform;version="0.0.0.1_007_JavaSE", javax.xml.validation;uses:="org.w3c.dom.ls,javax.xml.transform,javax.xml.transform.stream,org.xml.sax,org.w3c.dom";version="0.0.0.1_007_JavaSE", javax.xml.ws.handler.soap;uses:="javax.xml.ws.handler,javax.xml.namespace,javax.xml.soap,javax.xml.bind";version="0.0.0.1_007_JavaSE", javax.xml.ws.handler;uses:="javax.xml.ws,javax.xml.namespace";version="0.0.0.1_007_JavaSE", javax.xml.ws.http;uses:="javax.xml.ws";version="0.0.0.1_007_JavaSE", javax.xml.ws.soap;uses:="javax.xml.ws.spi,javax.xml.ws,javax.xml.soap";version="0.0.0.1_007_JavaSE", javax.xml.ws.spi.http;version="0.0.0.1_007_JavaSE", javax.xml.ws.spi;uses:="javax.xml.ws,javax.xml.ws.wsaddressing,javax.xml.transform,org.w3c.dom,javax.xml.namespace,javax.xml.ws.handler,javax.xml.bind";version="0.0.0.1_007_JavaSE", javax.xml.ws.wsaddressing;uses:="javax.xml.bind.annotation,javax.xml.namespace,org.w3c.dom,javax.xml.transform,javax.xml.bind,javax.xml.ws,javax.xml.ws.spi";version="0.0.0.1_007_JavaSE", javax.xml.ws;uses:="javax.xml.ws.handler,javax.xml.ws.spi,javax.xml.ws.spi.http,javax.xml.transform,org.w3c.dom,javax.xml.bind.annotation,javax.xml.transform.stream,javax.xml.bind,javax.xml.namespace";version="0.0.0.1_007_JavaSE", javax.xml.xpath;uses:="org.xml.sax,javax.xml.namespace";version="0.0.0.1_007_JavaSE", javax.xml;version="0.0.0.1_007_JavaSE", org.ietf.jgss;version="0.0.0.1_007_JavaSE", org.omg.CORBA.DynAnyPackage;uses:="org.omg.CORBA";version="0.0.0.1_007_JavaSE", org.omg.CORBA.ORBPackage;uses:="org.omg.CORBA";version="0.0.0.1_007_JavaSE", org.omg.CORBA.TypeCodePackage;uses:="org.omg.CORBA";version="0.0.0.1_007_JavaSE", org.omg.CORBA.portable;uses:="org.omg.CORBA,org.omg.CORBA_2_3.portable";version="0.0.0.1_007_JavaSE", org.omg.CORBA;uses:="org.omg.CORBA.portable,org.omg.CORBA.DynAnyPackage,org.omg.CORBA.ORBPackage,org.omg.CORBA_2_3.portable,org.omg.CORBA.TypeCodePackage";version="0.0.0.1_007_JavaSE", org.omg.CORBA_2_3.portable;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.CORBA_2_3;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.CosNaming.NamingContextExtPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.CosNaming.NamingContextPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.CosNaming";version="0.0.0.1_007_JavaSE", org.omg.CosNaming;uses:="org.omg.CORBA.portable,org.omg.CORBA,org.omg.PortableServer,org.omg.CosNaming.NamingContextPackage,org.omg.CosNaming.NamingContextExtPackage";version="0.0.0.1_007_JavaSE", org.omg.Dynamic;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.DynamicAny.DynAnyFactoryPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.DynamicAny.DynAnyPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.DynamicAny;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.DynamicAny.DynAnyFactoryPackage,org.omg.DynamicAny.DynAnyPackage";version="0.0.0.1_007_JavaSE", org.omg.IOP.CodecFactoryPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.IOP.CodecPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.IOP;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.IOP.CodecFactoryPackage,org.omg.IOP.CodecPackage";version="0.0.0.1_007_JavaSE", org.omg.Messaging;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.PortableInterceptor.ORBInitInfoPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.PortableInterceptor;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.IOP,org.omg.PortableInterceptor.ORBInitInfoPackage,org.omg.CORBA_2_3.portable,org.omg.Dynamic";version="0.0.0.1_007_JavaSE", org.omg.PortableServer.CurrentPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.PortableServer.POAManagerPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.PortableServer.POAPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.PortableServer.ServantLocatorPackage;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.PortableServer.portable;uses:="org.omg.CORBA,org.omg.PortableServer";version="0.0.0.1_007_JavaSE", org.omg.PortableServer;uses:="org.omg.CORBA,org.omg.CORBA.portable,org.omg.PortableServer.CurrentPackage,org.omg.PortableServer.POAManagerPackage,org.omg.PortableServer.POAPackage,org.omg.PortableServer.portable,org.omg.CORBA_2_3,org.omg.PortableServer.ServantLocatorPackage";version="0.0.0.1_007_JavaSE", org.omg.SendingContext;uses:="org.omg.CORBA,org.omg.CORBA.portable";version="0.0.0.1_007_JavaSE", org.omg.stub.java.rmi;uses:="javax.rmi.CORBA";version="0.0.0.1_007_JavaSE", org.w3c.dom.bootstrap;uses:="org.w3c.dom";version="0.0.0.1_007_JavaSE", org.w3c.dom.events;uses:="org.w3c.dom,org.w3c.dom.views";version="0.0.0.1_007_JavaSE", org.w3c.dom.ls;uses:="org.w3c.dom,org.w3c.dom.events,org.w3c.dom.traversal";version="0.0.0.1_007_JavaSE", org.w3c.dom;version="0.0.0.1_007_JavaSE", org.xml.sax.ext;uses:="org.xml.sax,org.xml.sax.helpers";version="0.0.0.1_007_JavaSE", org.xml.sax.helpers;uses:="org.xml.sax";version="0.0.0.1_007_JavaSE", org.xml.sax;version="0.0.0.1_007_JavaSE"</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You should now be able to start Felix, and deploy all the jars listed on this page. |
| You should see output similar to this on the console, using the <code>felix:lb</code> command:</p> |
| </div> |
| <div class="literalblock"> |
| <div class="content"> |
| <pre> ID|State |Level|Name |
| 0|Active | 0|System Bundle (4.4.1) |
| 1|Active | 1|ASM (7.0) |
| 2|Active | 1|ASM commons classes (7.0) |
| 3|Active | 1|ASM Tree class visitor (7.0) |
| 4|Active | 1|geronimo-jta_1.1_spec (1.1.1) |
| 5|Active | 1|javax.annotation API (1.2.0) |
| 6|Active | 1|javax.mail bundle from Glassfish (1.4.1.v201005082020) |
| 7|Active | 1|Java Server Pages Standard Tag Library API Bundle (1.2.0.v201105211821) |
| 8|Active | 1|JavaServer Pages (TM) TagLib Implementation (1.2.2) |
| 9|Active | 1|Jetty :: Servlet Annotations ({VERSION}) |
| 10|Active | 1|Jetty :: Deployers ({VERSION}) |
| 11|Active | 1|Jetty :: Http Utility ({VERSION}) |
| 12|Active | 1|Jetty :: IO Utility ({VERSION}) |
| 13|Active | 1|Jetty :: JNDI Naming ({VERSION}) |
| 14|Active | 1|Jetty :: OSGi :: Boot ({VERSION}) |
| 15|Resolved | 1|Jetty-OSGi-Jasper Integration ({VERSION}) |
| 16|Active | 1|Jetty Servlet API and Schemas for OSGi (3.1.0) |
| 17|Active | 1|Jetty :: Plus ({VERSION}) |
| 18|Active | 1|Jetty :: Security ({VERSION}) |
| 19|Active | 1|Jetty :: Server Core ({VERSION}) |
| 20|Active | 1|Jetty :: Servlet Handling ({VERSION}) |
| 21|Active | 1|Jetty :: Utility Servlets and Filters ({VERSION}) |
| 22|Active | 1|Jetty :: Utilities ({VERSION}) |
| 23|Active | 1|Jetty :: Webapp Application Support ({VERSION}) |
| 24|Active | 1|Jetty :: XML utilities ({VERSION}) |
| 25|Active | 1|Apache Aries SPI Fly Dynamic Weaving Bundle (1.2) |
| 27|Active | 1|Apache Felix Bundle Repository (2.0.2) |
| 28|Active | 1|Apache Felix Configuration Admin Service (1.8.0) |
| 29|Active | 1|Apache Felix EventAdmin (1.3.2) |
| 30|Active | 1|Apache Felix Gogo Command (0.14.0) |
| 31|Active | 1|Apache Felix Gogo Runtime (0.12.1) |
| 32|Active | 1|Apache Felix Gogo Shell (0.10.0) |
| 33|Active | 1|Apache Felix Log Service (1.0.1) |
| 34|Active | 1|Jetty :: Apache JSP ({VERSION}) |
| 35|Active | 1|Eclipse Compiler for Java(TM) (3.8.2.v20130121-145325) |
| 36|Active | 1|Mortbay EL API and Implementation (8.5.33.1) |
| 37|Active | 1|Mortbay Jasper (8.5.33.1)</pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Eclipse</h5> |
| <div class="paragraph"> |
| <p>The Jetty OSGi integration has been successfully tested against <a href="https://www.eclipse.org/equinox/">Equinox</a> Mars RC1.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Ensure that these services are present:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="https://www.eclipse.org/equinox/bundles/">Configuration Admin</a></p> |
| </li> |
| <li> |
| <p><a href="https://www.eclipse.org/equinox/bundles/">Event Admin</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect5"> |
| <h6>Eclipse Update Site</h6> |
| <div class="paragraph"> |
| <p>There is a list of Eclipse P2 sites for the jetty releases maintained at <a href="http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/" class="bare">http://download.eclipse.org/jetty/updates/jetty-bundles-9.x/</a></p> |
| </div> |
| <div class="paragraph"> |
| <p>Each P2 repo has one big feature group that defines most of the Jetty jars. |
| <strong>Beware: No 3rd party dependency jars are included, so you will need to have installed the dependencies listed previously in this document.</strong></p> |
| </div> |
| <div class="paragraph"> |
| <p>In addition, as the feature group includes websocket, you will need to download and have installed the <code>javax.websocket-api</code> jar:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 8. Extra Jars Required for Websocket</caption> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Jar</th> |
| <th class="tableblock halign-left valign-top">Bundle Symbolic Name</th> |
| <th class="tableblock halign-left valign-top">Location</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">javax.websocket-api</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">javax.websocket-api</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://repo1.maven.org/maven2/javax/websocket/websocket-api">Maven |
| central</a></p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="framework-weld">Weld</h3> |
| <div class="paragraph"> |
| <p><a href="http://seamframework.org/Weld">Weld</a> can be used to add support for CDI (Contexts and Dependency Injection) to Servlets, Listeners and Filters. |
| It is easily configured with Jetty 9.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="weld-setup-distro">Weld Setup</h4> |
| <div class="paragraph"> |
| <p>The easiest way to configure weld is within the jetty distribution itself:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>Enable the startup <a href="#startup-modules">module</a> called "cdi".</p> |
| </li> |
| <li> |
| <p>Ensure your <code>WEB-INF/web.xml</code> contains the following:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"> <listener> |
| <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> |
| </listener> |
| |
| <resource-env-ref> |
| <description>Object factory for the CDI Bean Manager</description> |
| <resource-env-ref-name>BeanManager</resource-env-ref-name> |
| <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type> |
| </resource-env-ref></code></pre> |
| </div> |
| </div> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>That should be it so when you start up your jetty distribution with the webapp you should see output similar to the following (providing your logging is the default configuration):</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">2015-06-18 12:13:54.924:INFO::main: Logging initialized @485ms |
| 2015-06-18 12:13:55.231:INFO:oejs.Server:main: jetty-9.3.1-SNAPSHOT |
| 2015-06-18 12:13:55.264:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///tmp/cdi-demo/webapps/] at interval 1 |
| 2015-06-18 12:13:55.607:WARN:oeja.AnnotationConfiguration:main: ServletContainerInitializers: detected. Class hierarchy: empty |
| Jun 18, 2015 12:13:55 PM org.jboss.weld.environment.servlet.EnhancedListener onStartup |
| INFO: WELD-ENV-001008: Initialize Weld using ServletContainerInitializer |
| Jun 18, 2015 12:13:55 PM org.jboss.weld.bootstrap.WeldStartup <clinit> |
| INFO: WELD-000900: 2.2.9 (Final) |
| Jun 18, 2015 12:13:55 PM org.jboss.weld.environment.servlet.deployment.WebAppBeanArchiveScanner scan |
| WARN: WELD-ENV-001004: Found both WEB-INF/beans.xml and WEB-INF/classes/META-INF/beans.xml. It's not portable to use both locations at the same time. Weld is going to use file:/tmp/jetty-0.0.0.0-8080-cdi-webapp.war-_cdi-webapp-any-8161614308407422636.dir/webapp/WEB-INF/beans.xml. |
| Jun 18, 2015 12:13:55 PM org.jboss.weld.bootstrap.WeldStartup startContainer |
| INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously. |
| Jun 18, 2015 12:13:55 PM org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit> |
| WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate not found, interception based on it is not enabled |
| Jun 18, 2015 12:13:55 PM org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit> |
| WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate not found, interception based on it is not enabled |
| Jun 18, 2015 12:13:56 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException |
| Jun 18, 2015 12:13:56 PM org.jboss.weld.environment.servlet.WeldServletLifecycle findContainer |
| INFO: WELD-ENV-001002: Container detection skipped - custom container class loaded: org.jboss.weld.environment.jetty.JettyContainer. |
| Jun 18, 2015 12:13:56 PM org.jboss.weld.environment.jetty.JettyContainer initialize |
| INFO: WELD-ENV-001200: Jetty 7.2+ detected, CDI injection will be available in Servlets and Filters. Injection into Listeners should work on Jetty 9.1.1 and newer. |
| Jun 18, 2015 12:13:56 PM org.jboss.weld.environment.servlet.Listener contextInitialized |
| INFO: WELD-ENV-001006: org.jboss.weld.environment.servlet.EnhancedListener used for ServletContext notifications |
| Jun 18, 2015 12:13:56 PM org.jboss.weld.environment.servlet.EnhancedListener contextInitialized |
| INFO: WELD-ENV-001009: org.jboss.weld.environment.servlet.Listener used for ServletRequest and HttpSession notifications |
| 2015-06-18 12:13:56.535:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@6574b225{/cdi-webapp,file:///tmp/jetty-0.0.0.0-8080-cdi-webapp.war-_cdi-webapp-any-8161614308407422636.dir/webapp/,AVAILABLE}{/cdi-webapp.war} |
| 2015-06-18 12:13:56.554:INFO:oejs.ServerConnector:main: Started ServerConnector@7112f81c{HTTP/1.1,[http/1.1]}{0.0.0.0:8080} |
| 2015-06-18 12:13:56.587:INFO:oejus.SslContextFactory:main: x509={jetty.eclipse.org=jetty} wild={} alias=null for SslContextFactory@3214ee6(file:///tmp/cdi-demo/etc/keystore,file:///tmp/cdi-demo/etc/keystore) |
| 2015-06-18 12:13:56.821:INFO:oejs.ServerConnector:main: Started ServerConnector@69176a9b{SSL,[ssl, http/1.1]}{0.0.0.0:8443} |
| 2015-06-18 12:13:56.822:INFO:oejs.Server:main: Started @2383ms</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>For use with the jetty-maven-plugin, the best idea is to make the org.jboss.weld.servlet:weld-servlet artifact a <em>plugin</em> dependency (<em>not</em> a webapp dependency), then follow step 2 above.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="framework-metro">Metro</h3> |
| <div class="paragraph"> |
| <p><a href="https://metro.java.net/">Metro</a> is the reference implementation for <a href="http://jcp.org/en/jsr/detail?id=109">web services</a>. |
| You can easily use Metro with Jetty to integrate web services with your web applications.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="metro-setup-distro">Metro Setup</h4> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p><a href="https://metro.java.net/latest/download.html">Download</a> the Metro distribution and unpack it to your disk. |
| We’ll refer to the unpacked location as <code>$metro.home</code>.</p> |
| </li> |
| <li> |
| <p>Create the directory <code>$jetty.home/lib/metro</code></p> |
| </li> |
| <li> |
| <p>Copy the jars from $metro.home/lib to <code>$jetty.home/lib/metro</code></p> |
| </li> |
| <li> |
| <p>Edit the start.ini file and add an OPTION line for metro near the end.</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">OPTIONS=metro</code></pre> |
| </div> |
| </div> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>That’s all the setup you need to do to integrate Jetty and Metro.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Now read the <a href="https://metro.java.net/discover/">Metro documentation</a> on <a href="https://metro.java.net/getting-started/">how to create web services</a>. |
| The Metro distribution you downloaded should also contain several example web applications in the $metro.home/samples directory that you can build and deploy to Jetty (simply by copying the war file produced by the build).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here’s an example of the log output from Jetty when one of the sample Metro wars (from <code>$metro.home/samples/async</code>) is deployed to Jetty:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">[2093] java -jar start.jar |
| |
| 2013-07-26 15:47:53.480:INFO:oejs.Server:main: jetty-9.0.4.v20130625 |
| 2013-07-26 15:47:53.549:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:/home/user/jetty-distribution-10.0.0-SNAPSHOT/webapps/] at interval 1 |
| Jul 26, 2013 3:47:53 PM com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextInitialized |
| INFO: WSSERVLET12: JAX-WS context listener initializing |
| Jul 26, 2013 3:47:56 PM com.sun.xml.ws.server.MonitorBase createRoot |
| INFO: Metro monitoring rootname successfully set to: com.sun.metro:pp=/,type=WSEndpoint,name=/metro-async-AddNumbersService-AddNumbersImplPort |
| Jul 26, 2013 3:47:56 PM com.sun.xml.ws.transport.http.servlet.WSServletDelegate <init> |
| INFO: WSSERVLET14: JAX-WS servlet initializing |
| 2013-07-26 15:47:56.800:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@75707c77{/metro-async,file:/tmp/jetty-0.0.0.0-8080-metro-async.war-_metro-async-any-/webapp/,AVAILABLE}{/metro-async.war} |
| 2013-07-26 15:47:56.853:INFO:oejs.ServerConnector:main: Started ServerConnector@47dce809{HTTP/1.1}{0.0.0.0:8080}</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="architecture">Architecture</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>General items related to the architecture of jetty and how it deals with certain design decisions.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="basic-architecture">Jetty Architecture</h3> |
| <div class="sect3"> |
| <h4>View from 20,000 feet</h4> |
| <div class="paragraph"> |
| <p>The Jetty <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/Server.html">Server</a> is the plumbing between |
| a collection of `Connector`s that accept connections and a collection of `Handler`s that |
| service requests from the connections and produce responses, with threads from a thread pool doing the work.</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/jetty-high-level-architecture.png" alt="image" width="576"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>While the Jetty request/responses are derived from the Servlet API, the full features of the Servlet API |
| are only available if you configure the appropriate handlers. |
| For example, the session API on the request is inactive unless the request has been passed to a <code>SessionHandler</code>. |
| The concept of a Servlet itself is implemented by a <code>ServletHandler</code>. |
| If Servlets are not required, there is very little overhead in the use of the servlet request/response APIs. |
| Thus you can build a Jetty server using only connectors and handlers, without using Servlets.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The job of configuring Jetty is building a tree of connectors and handlers and providing their individual configurations. |
| As Jetty components are simply Plain Old Java Objects (POJOs), you can accomplish this assembly |
| and configuration of components by a variety of techniques:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>In code, see the examples in the Jetty Source XRef.</p> |
| </li> |
| <li> |
| <p>Using Jetty XML, a dependency injection style in XML format.</p> |
| </li> |
| <li> |
| <p>With your dependency injection framework of choice, Spring or XBean.</p> |
| </li> |
| <li> |
| <p>Using Jetty WebApp and Context Deployers.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Patterns</h4> |
| <div class="paragraph"> |
| <p>The implementation of Jetty follows some fairly standard patterns. |
| Most abstract concepts such as <code>Connector`s and `Handler`s are captured by interfaces. |
| Generic handling for those interfaces is then provided in an abstract implementation |
| such as `AbstractConnector</code> and <code>AbstractHandler</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/basic-architecture-patterns.png" alt="image" width="576"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>The JSR77 inspired life cycle of most Jetty components is represented by the <code>LifeCycle</code> |
| interface and the <code>AbstractLifeCycle</code> implementation used as the base of many Jetty components.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Connectors</h4> |
| <div class="paragraph"> |
| <p>A <code>Connector</code> is the component that accepts TCP connections. |
| For each accepted TCP connection, the <code>Connector</code> asks a <code>ConnectionFactory</code> to create |
| a <code>Connection</code> object that handles the network traffic on that TCP connection, parsing |
| and generating bytes for a specific protocol.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A <code>ServerConnector</code> can therefore be configured with one or more <code>ConnectionFactory</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The simplest case is a single <code>ConnectionFactory</code> such as <code>HttpConnectionFactory</code>, that |
| creates <code>HttpConnection</code> objects that parse and generate bytes for the HTTP/1.1 protocol.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A more complex case can be a <code>ServerConnector</code> configured with three factories: |
| <code>ProxyConnectionFactory</code>, <code>SslConnectionFactory</code> and <code>HttpConnectionFactory</code>. |
| Such connector will be able to handle PROXY protocol bytes coming from a load balancer |
| such as HAProxy (with the <code>ProxyConnectionFactory</code>), then handle TLS bytes (with |
| <code>SslConnectionFactory</code>) and therefore decrypting/encrypting the bytes from/to a remote |
| client, and finally handling HTTP/1.1 bytes (with <code>HttpConnectionFactory</code>). |
| Each <code>ConnectionFactory</code> is asked to create a <code>Connection</code> object for each TCP connection; |
| the <code>Connection</code> objects will be chained together to handle the bytes, each for its |
| own protocol. |
| Therefore the <code>ProxyConnection</code> will handle the PROXY protocol bytes, <code>SslConnection</code> |
| will handle the encryption/decryption of the bytes, and <code>HttpConnection</code> will handle |
| the HTTP/1.1 bytes producing a request and response object that will be processed by |
| applications.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Advanced usages of Jetty will allow users to write their own <code>ConnectionFactory</code> to |
| handle custom protocols that are not implemented directly by the Jetty project, |
| therefore using Jetty as a generic network server.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Handlers</h4> |
| <div class="paragraph"> |
| <p>A <code>Handler</code> is the component that deals with HTTP requests and responses. |
| The core API of a handler is the handle method:</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/basic-architecture-handlers.png" alt="image" width="576"></span></p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Parameters:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>target</code> – the target of the request, either a URI or a name.</p> |
| </li> |
| <li> |
| <p><code>baseRequest</code> – the original unwrapped request object.</p> |
| </li> |
| <li> |
| <p><code>request</code> – the request object, either as the <code>baseRequest</code> object or a wrapper of <code>baseRequest</code>. |
| You can use the HttpConnection.getCurrentConnection() method to access the Request object if required.</p> |
| </li> |
| <li> |
| <p>response – the response object, either unwrapped as <code>Response</code> or a wrapper of that response. |
| You can use the HttpConnection.getCurrentConnection() method to access the <code>Response</code> object if required.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>An implementation of this method can handle the request, pass the request onto another handler (or servlet) |
| or it might modify and/or wrap the request and then pass it on. |
| This gives three styles of Handler:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Coordinating handlers – handlers that route requests to other handlers (<code>HandlerCollection</code>, <code>ContextHandlerCollection</code>)</p> |
| </li> |
| <li> |
| <p>Filtering handlers – handlers that augment a request and pass it on to other handlers (<code>HandlerWrapper</code>, <code>ContextHandler</code>, <code>SessionHandler</code>)</p> |
| </li> |
| <li> |
| <p>Generating handlers – handlers that produce content (<code>ResourceHandler</code> and <code>ServletHandler</code>)</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect4"> |
| <h5>Nested Handlers and Handlers Called Sequentially</h5> |
| <div class="paragraph"> |
| <p>You can combine handlers to handle different aspects of a request by nesting them, |
| calling them in sequence, or by combining the two models.</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/basic-architecture-nested-handlers.png" alt="image" width="576"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>Handlers called in sequence perform actions that do not depend on the next invocation, nor on the handler order. |
| They handle a request and generate the response without interacting with other handlers. |
| The main class for this model is <code>HandlerCollection</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Nested handlers are called according to a before/invokeNext/after pattern. |
| The main class for nested handlers is <code>HandlerWrapper</code>. |
| Nested handlers are much more common than those called in sequence.</p> |
| </div> |
| <div class="paragraph"> |
| <p>See also <a href="#writing-custom-handlers">Writing Custom Handlers</a>.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Servlet Handler</h5> |
| <div class="paragraph"> |
| <p>The <code>ServletHandler</code> is a <code>Handler</code> that generates content by passing the request to any |
| configured Servlet Filters and then to a Servlet mapped by a URI pattern.</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/basic-architecture-servlet-handler.png" alt="image" width="576"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>A <code>ServletHandler</code> is normally deployed within the scope of a <code>ServletContext</code>, which is a |
| <code>ContextHandler</code> that provides convenience methods for mapping URIs to servlets.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Filters and Servlets can also use a <code>RequestDispatcher</code> to reroute a request to another context |
| or another Servlet in the current context.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="what-is-a-context">Contexts</h4> |
| <div class="paragraph"> |
| <p>Contexts are handlers that group other handlers below a particular URI context path or a virtual host. |
| Typically a context can have:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A context path that defines which requests are handled by the context (e.g. <code>/myapp</code>)</p> |
| </li> |
| <li> |
| <p>A resource base for static content (a document root)</p> |
| </li> |
| <li> |
| <p>A class loader to obtain classes specific to the context (typically from <code>/WEB-INF/classes</code> and <code>/WEB-INF/lib</code>)</p> |
| </li> |
| <li> |
| <p>Virtual host names</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Contexts implementations include:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>ContextHandler</code></p> |
| </li> |
| <li> |
| <p><code>ServletContextHandler</code></p> |
| </li> |
| <li> |
| <p><code>WebAppContext</code></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>A web application context combines handlers for security, session and servlets in a single unit |
| that you can configure with a <code>web.xml</code> descriptor.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Web Application</h4> |
| <div class="paragraph"> |
| <p>A <code>WebAppContext</code> is a derivation of <code>ServletContextHandler</code> that supports the standardized layout |
| of a web application and configuration of session, security, listeners, filter, servlets, and JSP |
| via a <code>web.xml</code> descriptor normally found in the <code>/WEB-INF</code> directory of a web application.</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/basic-architecture-web-application.png" alt="image" width="576"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>Essentially <code>WebAppContext</code> is a convenience class that assists the construction and configuration |
| of other handlers to achieve a standard web application configuration. |
| Configuration is actually done by pluggable implementations of the Configuration class and the |
| prime among these is <code>WebXmlConfiguration.</code></p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-classloading">Jetty Classloading</h3> |
| <div class="paragraph"> |
| <p>Class loading in a web container is slightly more complex than a normal Java application. |
| The normal configuration is that each web context (web application or WAR file) has its own classloader, which has the system classloader as its parent. |
| Such a classloader hierarchy is normal in Java, however the servlet specification complicates the hierarchy because it requires the following:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Classes contained within <code>WEB-INF/lib</code> or <code>WEB-INF/classes</code> have priority over classes on the parent classloader. |
| This is the opposite of the normal behavior of a Java 2 classloader.</p> |
| </li> |
| <li> |
| <p>System classes such as <code>java.lang.String</code> are excluded from the webapp priority, and you may not replace them with classes in <code>WEB-INF/lib</code> or <code>WEB-INF/</code> classes. |
| Unfortunately the specification does not clearly state what classes are <em>System</em> classes, and it is unclear if all <code>javax</code> classes should be treated as System classes.</p> |
| </li> |
| <li> |
| <p>Server implementation classes like <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/Server.html">Server</a> should be hidden from the web application and should not be available in any classloader. |
| Unfortunately the specification does not state what classes are <em>Server</em> classes, and it is unclear if common libraries like the Xerces parser should be treated as Implementation classes.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect3"> |
| <h4 id="configuring-webapp-classloading">Configuring Webapp Classloading</h4> |
| <div class="paragraph"> |
| <p>Jetty provides configuration options to control the three webapp class loading issues identified above.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can configure webapp classloading by several methods on the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html">WebAppContext</a>. |
| You can call these methods directly if you are working with the Jetty API, or you can inject methods from a context XML file if you are using the Context Provider (<a href="#using-context-provider">[using-context-provider]</a>). |
| You CANNOT set these methods from a <code>jetty-web.xml</code> file, as it executes after the classloader configuration is set. |
| As a note, <code>jetty-web.xml</code> uses the webapp classpath and not the classpath of the server.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="controlling-webapp-classloader-priority">Controlling Webapp Classloader Priority</h5> |
| <div class="paragraph"> |
| <p>The method <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#isParentLoaderPriority()">org.eclipse.jett .webapp.WebAppContext.setParentLoaderPriority(boolean)</a> allows control over the priority given to webapp classes over system classes. |
| If you set it to false (the default), Jetty uses standard webapp classloading priority. |
| However, if in this mode some classes that are dependencies of other classes are loaded from the parent classloader (due to settings of system classes below), ambiguities might arise as both the webapp and system classloader versions can end up being loaded.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If set to true, Jetty uses normal JavaSE classloading priority, and gives priority to the parent/system classloader. |
| This avoids the issues of multiple versions of a class within a webapp, but the version the parent/system loader provides must be the right version for all webapps you configure in this way.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="configuring-webapp-caching">Configuring Webapp Classloader Caching</h5> |
| <div class="paragraph"> |
| <p>Introduced in Jetty 9.3.6, the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/CachingWebAppClassLoader.html">CachingWebAppClassLoader</a> can be used to cache <code>getResource(String)</code> results. |
| For webapps that search for classes and resources regularly, this can increase speed and performance. |
| This is an optional feature and it should be noted that it can conflict with several other libraries such as JSP, JSTL, JSF and CDI. |
| As such, this feature must be manually enabled for each webapp you want to use it in.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Below is an example of implementing this feature using Jetty IoC XML format:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="mywebapp" class="org.eclipse.jetty.webapp.WebAppContext"> |
| |
| ... |
| |
| <Set name="classLoader"> |
| <New class="org.eclipse.jetty.webapp.CachingWebAppClassLoader"> |
| <Arg><Ref refid="mywebapp"/></Arg> |
| </New> |
| </Set> |
| |
| ... |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="classloading-setting-system-classes">Setting System Classes</h5> |
| <div class="paragraph"> |
| <p>You can call the methods |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setSystemClasses%28java.lang.String%5B%5D%29">WebAppContext.setSystemClasses(String[])</a> |
| or |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#getSystemClasspathPattern()">WebAppContext.getSystemClasspathPattern().add(String)</a> |
| to allow fine control over which classes are considered system classes.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A web application can see a System class.</p> |
| </li> |
| <li> |
| <p>A WEB-INF class cannot replace a System class.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The default system classes are:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 9. Default System Classes</caption> |
| <colgroup> |
| <col style="width: 8%;"> |
| <col style="width: 92%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">System Classes</th> |
| <th class="tableblock halign-left valign-top">Note</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">java.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Java SE classes (per servlet spec v2.5 / SRV.9.7.2).</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">javax.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Java SE classes (per servlet spec v2.5 / SRV.9.7.2).</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.xml.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Needed by javax.xml.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.w3c.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Needed by javax.xml.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.continuation.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Webapp can see and not change continuation classes.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.jndi.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Webapp can see and not change naming classes.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.jaas.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Webapp can see and not change JAAS classes.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.websocket.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">WebSocket is a Jetty extension.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.servlet.DefaultServlet</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Webapp can see and not change default servlet.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>Absolute classname can be passed, names ending with <code>.</code> are treated as packages names, and names starting with <code>-</code> are treated as negative matches and must be listed before any enclosing packages.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="setting-server-classes">Setting Server Classes</h5> |
| <div class="paragraph"> |
| <p>You can call the methods <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setServerClasses%28java.lang.String%5B%5D%29">org.eclipse.jetty.webapp.WebAppContext.setServerClasses(String Array)</a> or |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#addServerClass(java.lang.String)">org.eclipse.jetty.webapp.WebAppContext.addServerClass(String)</a> to allow fine control over which classes are considered Server classes.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A web application cannot see a Server class.</p> |
| </li> |
| <li> |
| <p>A WEB-INF class can replace a Server class.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>The default server classes are:</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <caption class="title">Table 10. Default Server Classes</caption> |
| <colgroup> |
| <col style="width: 8%;"> |
| <col style="width: 92%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Server Classes</th> |
| <th class="tableblock halign-left valign-top">-org.eclipse.jetty.continuation.</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Don’t hide continuation classes.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">-org.eclipse.jetty.jndi.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Don’t hide naming classes.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">-org.eclipse.jetty.jaas.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Don’t hide jaas classes.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">-org.eclipse.jetty.servlets.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Don’t hide utility servlet classes if provided.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">-org.eclipse.jetty.servlet.DefaultServlet</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Don’t hide default servlet.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">-org.eclipse.jetty.servlet.listener.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Don’t hide utility listeners</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">-org.eclipse.jetty.websocket.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Don’t hide websocket extension.</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="adding-extra-classpaths">Adding Extra Classpaths to Jetty</h4> |
| <div class="paragraph"> |
| <p>You can add extra classpaths to Jetty in several ways.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="classpaths-using-start-jar">Using <code>start.jar</code></h5> |
| <div class="paragraph"> |
| <p>If you are using <code>start.jar</code> via the Jetty distribution, at startup the Jetty runtime automatically loads option Jars from the top level <code>$jetty.home/lib</code> directory. The default settings include:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Adding Jars under <code>$jetty.home/lib/ext</code> to the system classpath. |
| You can place additional Jars here.</p> |
| </li> |
| <li> |
| <p>Adding the directory <code>$jetty.home/resources</code> to the classpath (may contain classes or other resources).</p> |
| </li> |
| <li> |
| <p>Adding a single path defined by the command line parameter <em>path</em>.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="using-extra-classpath-method">Using the extraClasspath() method</h5> |
| <div class="paragraph"> |
| <p>You can add an additional classpath to a context classloader by calling <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setExtraClasspath(java.lang.String)">org.eclipse.jetty.webapp.WebAppContext.setExtraClasspath(String)</a> with a comma-separated list of paths. |
| You can do so directly to the API via a context XML file such as the following:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure class="org.eclipse.jetty.webapp.WebAppContext"> |
| ... |
| <Set name="extraClasspath">../my/classes,../my/jars/special.jar,../my/jars/other.jar</Set> |
| ...</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="using-custom-webappclassloader">Using a Custom WebAppClassLoader</h4> |
| <div class="paragraph"> |
| <p>If none of the alternatives already described meet your needs, you can always provide a custom classloader for your webapp. |
| We recommend, but do not require, that your custom loader subclasses <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppClassLoader.html">WebAppClassLoader</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you do not subclass WebAppClassLoader, we recommend that you implement the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/util/ClassVisibilityChecker.html">ClassVisibilityChecker</a> interface. |
| Without this interface, session persistence will be slower.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You configure the classloader for the webapp like so:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">MyCleverClassLoader myCleverClassLoader = new MyCleverClassLoader(); |
| ... |
| WebAppContext webapp = new WebAppContext(); |
| ... |
| webapp.setClassLoader(myCleverClassLoader);</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You can also accomplish this in a context xml file.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="starting-jetty-custom-classloader">Starting Jetty with a Custom ClassLoader</h4> |
| <div class="paragraph"> |
| <p>If you start a Jetty server using a custom class loader–consider the Jetty classes not being available to the system class loader, only your custom class loader–you may run into class loading issues when the <code>WebAppClassLoader</code> kicks in. |
| By default the <code>WebAppClassLoader</code> uses the system class loader as its parent, hence the problem. This is easy to fix, like so:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">context.setClassLoader(new WebAppClassLoader(this.getClass().getClassLoader(), context));</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>or</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">context.setClassLoader(new WebAppClassLoader(new MyCustomClassLoader(), context));</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-1xx-responses">Managing 1xx Responses</h3> |
| <div class="paragraph"> |
| <p>The <a href="http://www.ietf.org/rfc/rfc2616.txt">HTTP RFC</a> allows for 1xx informational responses to be sent before a real content response. |
| Unfortunately the servlet specification does not provide a way for these to be sent, so Jetty has had to provide non-standard handling of these headers.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-100-continue">100 Continue</h4> |
| <div class="paragraph"> |
| <p>The 100 Continue response should be sent by the server when a client sends a request with a Expect: 100-continue header, as the client will not send the body of the request until the 100 continue response has been sent.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The intent of this feature is to allow a server to inspect the headers and to tell the client to not send a request body that might be too large or insufficiently private or otherwise unable to be handled.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty achieves this by waiting until the input stream or reader is obtained by the filter/servlet, before sending the 100 continues response. |
| Thus a filter/servlet may inspect the headers of a request before getting the input stream and send an error response (or redirect etc.) rather than the 100 continues.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-102-processing">102 Processing</h4> |
| <div class="paragraph"> |
| <p><a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a> defines the 102 processing response that can be sent "when the server has a reasonable expectation that the request will take significant time to complete. |
| As guidance, if a method is taking longer than 20 seconds (a reasonable, but arbitrary value) to process the server SHOULD return a 102 (Processing) response".</p> |
| </div> |
| <div class="paragraph"> |
| <p>So if a request is received with the Expect: 102-processing header, then a filter/servlet may send a 102 response (without terminating further processing) by calling <code>servletResponse.sendError(102);</code>.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="creating-custom-protocol">Creating a Custom Protocol</h3> |
| <div class="paragraph"> |
| <p>You can create custom protocols with Jetty. This page provides an example of how to do so, with Telnet as the protocol.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To create a custom Telnet protocol, complete the following tasks:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Implement a <code>TelnetServerConnectionFactory</code>.</p> |
| </li> |
| <li> |
| <p>Implement a <code>TelnetServerConnection</code> by extending <code>o.e.j.io.AbstractConnection</code>.</p> |
| </li> |
| <li> |
| <p>Create a parser/interpreter for the bytes you receive (this is totally independent from Jetty).</p> |
| </li> |
| <li> |
| <p>If needed, design an API for the application to use to process the bytes received (also independent from Jetty). |
| The API likely has a <em>respond back</em> primitive that uses a Jetty provided <code>EndPoint</code> and <code>EndPoint.write(Callback, Buffer…​)</code> to write the response bytes.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect3"> |
| <h4 id="server-connection-factory">Implementing a TelnetServerConnectionFactory</h4> |
| <div class="paragraph"> |
| <p>Begin with an <code>org.eclipse.jetty.server.ServerConnector</code>, which you can use as is. <code>ServerConnector</code> takes a <code>o.e.j.server.ConnectionFactory</code>, which creates <code>o.e.j.io.Connection</code> objects that interpret the bytes the connector receives. |
| You must implement <code>ConnectionFactory</code> with a <code>TelnetServerConnectionFactory</code>, where you return a Connection implementation (for example, <code>TelnetServerConnection</code>).</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="telnet-server-connection">Implementing the TelnetServerConnection</h4> |
| <div class="paragraph"> |
| <p>For the Connection implementation you need to extend from <code>o.e.j.io.AbstractConnection</code> because it provides many facilities that you would otherwise need to re-implement from scratch.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For each Connection instance there is associated an <code>o.e.j.io.EndPoint</code> instance. |
| Think of <code>EndPoint</code> as a specialized version of JDK’s <code>SocketChannel</code>. |
| You use the <code>EndPoint</code> to read, write, and close. |
| You don’t need to implement <code>EndPoint</code>, because Jetty provides concrete |
| classes for you to use.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The Connection is the <em>passive</em> side (that is, Jetty calls it when there is data to read), while the <code>EndPoint</code> is the active part (that is, applications call it to write data to the other end). |
| When there is data to read, Jetty calls <code>AbstractConnection.onFillable()</code>, which you must implement in your <code>TelnetServerConnection</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>A typical implementation reads bytes from the <code>EndPoint</code> by calling <code>EndPoint.fill(ByteBuffer)</code>. |
| For examples, look at both the simpler <code>SPDYConnection</code> (in the SPDY client package, but server also uses it), and the slightly more complex <code>HttpConnection</code>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="parser-interpreter">Parsing the Bytes Received</h4> |
| <div class="paragraph"> |
| <p>After you read the bytes, you need to parse them. |
| For the Telnet protocol there is not much to parse, but perhaps you have your own commands that you want to interpret and execute. |
| Therefore typically every connection has an associated parser instance. |
| In turn, a parser usually emits parse events that a parser listener interprets, as the following examples illustrate:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>In HTTP, the Jetty HTTP parser parses the request line (and emits a parser event), then parses the headers (and emits a parser event for each) until it recognizes the end of the headers (and emits another parser event). |
| At that point, the <em>interpreter</em> or parser listener (which for HTTP is <code>o.e.j.server.HttpChannel</code>) has all the information necessary to build a <code>HttpServletRequest</code> object and can call the user code (the web application, that is, servlets/filters).</p> |
| </li> |
| <li> |
| <p>In SPDY, the Jetty SPDY parser parses a SPDY frame (and emits a parser event), and the parser listener (an instance of o.e.j.spdy.StandardSession) interprets the parser events and calls user code (application-provided listeners).</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>With <code>ConnectionFactory</code>, Connection, parser, and parser listeners in place, you have configured the read side.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="api-byte-processor">Designing an API to Process Bytes</h4> |
| <div class="paragraph"> |
| <p>At this point, server applications typically write data back to the client.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The Servlet API (for HTTP) or application-provided listeners (for SPDY) expose an interface to web applications so that they can write data back to the client. |
| The implementation of those interfaces must link back to the <code>EndPoint</code> instance associated with the Connection instance so that it can write data via <code>EndPoint.write(Callback, ByteBuffer…​)</code>. |
| This is an asynchronous call, and it notifies the callback when all the buffers have been fully written.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example, in the Servlet API, applications use a <code>ServletOutputStream</code> to write the response content. |
| <code>ServletOutputStream</code> is an abstract class that Jetty implements, enabling Jetty to handle the writes from the web application; the writes eventually end up in an <code>EndPoint.write(…​)</code> call.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="api-tips">Tips for Designing an API</h5> |
| <div class="paragraph"> |
| <p>If you want to write a completely asynchronous implementation, your API to write data to the client must have a callback/promise concept: “Call me back when you are done, and (possibly) give me the result of the computation."</p> |
| </div> |
| <div class="paragraph"> |
| <p>SPDY’s Stream class is a typical example. |
| Notice how the methods there exist in two versions, a synchronous (blocking) one, and an asynchronous one that takes as last parameter a Callback (if no result is needed), or a Promise (if a result is needed). |
| It is trivial to write the synchronous version in terms of the asynchronous version.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can use <code>EndPoint.write(Callback, ByteBuffer…​)</code> in a blocking way as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">FutureCallback callback = new FutureCallback(); |
| endPoint.write(callback, buffers); |
| callback.get();</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>With the snippet above your API can be synchronous or asynchronous (your choice), but implemented synchronously.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="platforms">Platforms, Stacks and Alternative Distributions</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3>Many many options…​</h3> |
| <div class="paragraph"> |
| <p>In addition to using Jetty in its distribution form and its multiple embedded forms, there are a number of alternative ways to use Jetty. |
| Many products and open source projects out there distribute Jetty themselves, in both distribution and embedded forms, not to mention different operating systems bundling Jetty in other installable forms.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If your platform supports Jetty from a distribution or deployment perspective and want to be included on this list just fork the documentation and submit a pull request, or contact us. |
| Check out our list of <a href="http://www.eclipse.org/jetty/powered">Powered By</a> page for software that makes use of Jetty, often in novel and exciting ways.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jelastic">Jelastic</h3> |
| <div class="paragraph"> |
| <p>Jelastic is a wonderful place to host your applications with solid support for Jetty. |
| As a cloud hosting platform they take the majority of configuration and installation details out of the picture and focus on letting you focus on your web application.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="http://jelastic.com/why">Why Jelastic?</a></p> |
| </li> |
| <li> |
| <p><a href="http://jelastic.com/jetty-hosting">Jetty Hosting</a></p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="cloudfoundry">CloudFoundry</h3> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock warning"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-warning" title="Warning"></i> |
| </td> |
| <td class="content"> |
| This is an increasingly aged integration, things like likely changed enough this is not directly useful but may serve as a useful starting point should someone want to look into it. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="sect3"> |
| <h4 id="cloudfoundry-overview">Overview</h4> |
| <div class="paragraph"> |
| <p><a href="http://www.cloudfoundry.com">CloudFoundry</a> is an open platform intended as a place to deploy end user applications in a manner which is both simple and eminently scalable to fit the needs of the application. |
| With the release of their V2 framework the Jetty project has created a buildpack which allows you to deploy your java based web application onto Jetty and still make use of the remainder of the CloudFoundry platform.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This buildpack itself is quite simple to use. |
| A collection of ruby scripting and the buildpack conventions will allow Jetty to be downloaded, configured and customized to your needs and then have your web application deployed onto it. |
| While the default buildpack we have created is useful to deploy a stock configuration of jetty, it is quite likely that you will want to fork the buildpack and tweak it to fit your immediate needs. |
| This process is made trivial since buildpacks install from a github repository. |
| For example, to change the jetty version simply fork it in GitHub and tweak the <code>JETTY_VERSION</code> string in the <code>jetty_web.rb</code> file.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you have additional modifications to make to the Jetty server, like perhaps configuring additional static contexts, setting up a proxy servlet, adding jar files to the jetty home/lib/ext directory, etc you can either adapt the ruby scripting directly or place them under the appropriate location in the <code>/resources</code> directory of this buildpack and they will be copied into the correct location.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For the time being I’ll leave this buildpack under my personal github account and should there be interest expressed I am more then happy to push it over to <a href="https://github.com/jetty-project" class="bare">https://github.com/jetty-project</a> down the road for proper contributions, etc.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="cloudfoundry-usage">Usage</h4> |
| <div class="paragraph"> |
| <p>To show how incredibly easy it is to use the Jetty buildpack with cloudfoundry, this is all the more you need to do to deploy your application. |
| Refer to the CloudFoundry <a href="http://docs.cloudfoundry.com/">documentation</a> to get started, get the <code>cf</code> utilities installed and an environment configured.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">$ cf push snifftest --buildpack=git://github.com/jmcc0nn3ll/jetty-buildpack.git</code></pre> |
| </div> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock tip"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-tip" title="Tip"></i> |
| </td> |
| <td class="content"> |
| In this example the web application is uploaded from the <strong>current</strong> directory so make sure you have changed directory into the root of your web application. |
| The <code>snifftest</code> on the commandline refers to what you are calling the application, not the directory to deploy. |
| Also note that the webapplication is installed into the <code>ROOT</code> context of Jetty as is available at the root context of the server. |
| Any additional web applications will have to be configured within the buildpack as mentioned above. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>You will be prompted to answer a series of questions describing the execution environment and any additional services you need enabled (databases, etc).</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Instances> 1 |
| |
| Custom startup command> none |
| |
| 1: 64M |
| 2: 128M |
| 3: 256M |
| 4: 512M |
| 5: 1G |
| Memory Limit> 256M |
| |
| Creating snifftest... OK |
| |
| 1: snifftest |
| 2: none |
| Subdomain> snifftest |
| |
| 1: a1-app.cf-app.com |
| 2: none |
| Domain> a1-app.cf-app.com |
| |
| Binding snifftest.a1-app.cf-app.com to snifftest... OK |
| |
| Create services for application?> n |
| |
| Save configuration?> n</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Once answered you will see the installation process of your application.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Uploading snifftest... OK |
| Starting snifftest... OK |
| -> Downloaded app package (4.0K) |
| Initialized empty Git repository in /tmp/buildpacks/jetty-buildpack.git/.git/ |
| Installing jetty-buildpack.git. |
| Downloading JDK... |
| Copying openjdk-1.7.0_21.tar.gz from the buildpack cache ... |
| Unpacking JDK to .jdk |
| Downloading Jetty: jetty-distribution-10.0.0-SNAPSHOT.tar.gz |
| Downloading jetty-distribution-10.0.0-SNAPSHOT.tar.gz from http://repo2.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.0.3.v20130506/ ... |
| Unpacking Jetty to .jetty |
| -> Uploading staged droplet (36M) |
| -> Uploaded droplet |
| Checking snifftest... |
| Staging in progress... |
| Staging in progress... |
| Staging in progress... |
| Staging in progress... |
| Staging in progress... |
| Staging in progress... |
| 0/1 instances: 1 starting |
| 0/1 instances: 1 starting |
| 0/1 instances: 1 starting |
| 0/1 instances: 1 starting |
| 1/1 instances: 1 running |
| OK</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The application is now available at the configured location! Under the url <code><a href="http://snifftest.a1-app.cf-app.com/" class="bare">http://snifftest.a1-app.cf-app.com/</a></code> in this particular example.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="cloudfoundry-acknowledgements">Acknowledgements</h4> |
| <div class="paragraph"> |
| <p>The Jetty buildpack was forked from the CloudFoundry Java buildpack. The Virgo Buildpack that Glyn worked on was used as a sanity check.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="http://github.com/cloudfoundry/cloudfoundry-buildpack-java" class="bare">http://github.com/cloudfoundry/cloudfoundry-buildpack-java</a></p> |
| </li> |
| <li> |
| <p><a href="http://github.com/glyn/virgo-buildpack" class="bare">http://github.com/glyn/virgo-buildpack</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>CloudFoundry buildpacks were modelled on Heroku buildpacks.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="elastic-beanstalk">Amazon Elastic Beanstalk</h3> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock warning"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-warning" title="Warning"></i> |
| </td> |
| <td class="content"> |
| This is an increasingly aged integration, things like likely changed enough this is not directly useful but may serve as a useful starting point should someone want to look into it. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p><a href="http://aws.amazon.com/elasticbeanstalk/">Elastic Beanstalk</a> is a component with the <a href="http://aws.amazon.com">Amazon Web Services</a> offering that allows you to configure an entire virtual machine based on one of several available baseline configurations and then customize it through a powerful configuration system. While the default offerings currently available are based on Tomcat for for the java community, we worked out the basics using that configuration system to enable the usage of Jetty instead.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="elastic-beanstalk-overview">Overview</h4> |
| <div class="paragraph"> |
| <p>Elastic beanstalk has a very <a href="http://aws.amazon.com/about-aws/whats-new/2012/10/02/introducing-aws-elastic-beanstalk-configuration-files/">powerful configuration mechanism</a> so this integration taps into that to effectively rework the tomcat configuration and replace it with the bits required to make jetty run in its place. Below is a walk through of what the various configuration files are doing and how the general flow of configuration on beanstalk happens.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There is an <code>.ebextensions</code> directory in your beanstalk application which contains all of the files requires to configure and customize your beanstalk and application combo. |
| Files that end in .config in this directory are processed in alphabetical order.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">00-java7.config</dt> |
| <dd> |
| <p>installs java 7 onto the beanstalk environment and makes it the default</p> |
| </dd> |
| <dt class="hdlist1">10-tweak.config</dt> |
| <dd> |
| <p>not required, but changes the <code>/opt/elasticbeanstalk</code> directory to be readable making debugging easier</p> |
| </dd> |
| <dt class="hdlist1">11-jetty.config</dt> |
| <dd> |
| <p>installs jetty9 into <code>/opt/jetty-9</code> and removes unneeded distribution files</p> |
| </dd> |
| <dt class="hdlist1">12-beanstalk.config</dt> |
| <dd> |
| <p>handles replacing tomcat with jetty in many configuration files, configures logging and wires up system startup processes. |
| Some files in your <code>.ebextensions</code> directory are moved to replace files under /opt/elasticbeanstalk.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>If you look in the <code>.ebextensions</code> directory of your application you should also see other jetty specific xml and ini files. |
| The final config file handles these as they are largely customization for your application.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">20-testapp.config</dt> |
| <dd> |
| <p>layers application specific configuration files into the jetty installation</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>The files in our example test webapp here enable various OPTIONS for libraries that need to be loaded, customize the root application being deployed and even deploy additional contexts like we do in our jetty distribution demo. |
| This is also the mechanism that you would use to wire up application specific things, for example if you needed additional software installed, customized directories made, etc.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="elastic-beanstalk-maven">Maven Bits</h4> |
| <div class="paragraph"> |
| <p>Support for this feature leverages Maven to make things easy and is composed of three different modules.</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">jetty-beanstalk-overlay</dt> |
| <dd> |
| <p>This is the collection of scripts that are required to wedge jetty into the normal beanstalk setup. |
| This module is intended to extract into an webapp to enable it for beanstalk usage with jetty.</p> |
| </dd> |
| <dt class="hdlist1">jetty-beanstalk-resources</dt> |
| <dd> |
| <p>This generates an artifact of files that are downloaded by the configuration process and contains replacements for certain beanstalk files as well as various system level jetty configuration files like an updated <code>jetty.sh</code> script for the <code>/etc/init.d</code> setup.</p> |
| </dd> |
| <dt class="hdlist1">jetty-beanstalk-testapp</dt> |
| <dd> |
| <p>An example webapp that shows both how to combine the war file from another maven module with the jetty-beanstalk-overlay to produce a beanstalk enabled application bundle. |
| Also included is examples of how to alter the jetty configuration for things like a customized |
| <code>start.ini</code> file.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| The test webapps needs access to a snapshot version of the test-jetty-webapp so it really serves as more of an example of how to layer your webapp with the bits required to customize your app for beanstalk and jetty. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>To actually make use of these artifacts you currently must clone this git repository and build it locally. |
| Once you have the artifacts you simply need to copy the approach in the jetty-beanstalk-testapp to apply the configuration to your webapp.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="https://github.com/jmcc0nn3ll/jetty-beanstalk" class="bare">https://github.com/jmcc0nn3ll/jetty-beanstalk</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock important"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-important" title="Important"></i> |
| </td> |
| <td class="content"> |
| Bluepill is used to manage the start and stop process of the app server. |
| This seems to be a problematic bit of software with a colored history and the version in use at the time of this writing is old. |
| When starting and stopping (or restarting) the appserver you may see error messages show up that the Server timed out getting a response or things like that. |
| These are red herrings and my experience is that jetty has started and stopped just fine, the pid file required shows up in a very timely fashion (under <code>/var/run/jetty.pid</code>) so do check that the app server has started, but please be aware there is a strangeness here that hasn’t been sorted out yet. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="fedora">Fedora</h3> |
| <div class="paragraph"> |
| <p>As of Fedora 19, Jetty 9 is the version of Jetty available. |
| This distribution of Jetty is not created or maintained by the Jetty project though we have had a fair amount of communication with the folks behind it and we are very pleased with how this Linux distribution has stayed current. |
| Releases are kept largely in sync with our releases as there is a wonderful automatic notification mechanism in place for Fedora that detects our releases and immediately opens an issue for them to update.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="https://admin.fedoraproject.org/pkgdb/acls/name/jetty">Jetty on Fedora</a></p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="ubuntu">Ubuntu</h3> |
| <div class="paragraph"> |
| <p>Currently there are no actual <code>.deb</code> files available for installing on Debian based Linux machines but there is a handy blog that as been largely been kept up to date on the steps involved through the comments.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="http://pietervogelaar.nl/ubuntu-12-04-install-jetty-9/">Install Jetty9 |
| on Ubuntu</a></p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="reference-section">Jetty XML Reference</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="jetty-xml-syntax">Jetty XML Syntax</h3> |
| <div class="paragraph"> |
| <p>The Jetty XML syntax is a straightforward mapping of XML elements to a Java API so that POJOs can be instantiated and getters, setters, and methods called. |
| It is very similar to Inversion Of Control (IOC) or Dependency Injection (DI) frameworks like Spring or Plexus (but it predates all of them). |
| Typically Jetty XML is used by <code>jetty.xml</code> to configure a Jetty server or by a <code>context.xml</code> file to configure a ContextHandler or subclass, but you can also use the mechanism to configure arbitrary POJOs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This page describes the basic syntax of Jetty XML configuration. See <a href="#jetty-xml-usage">Jetty XML Usage</a> for information on how you can use and combine Jetty XML. |
| See configuration files for specific examples.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="basic-xml-configuration-file-example">Basic XML Configuration File Example</h4> |
| <div class="paragraph"> |
| <p>The following XML configuration file creates some Java objects and sets some attributes:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0"?> |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| <Configure id="foo" class="com.acme.Foo"> |
| <Set name="name">demo</Set> |
| <Set name="nested"> |
| <New id="bar" class="com.acme.Bar"> |
| <Arg>true</Arg> |
| <Set name="wibble">10</Set> |
| <Set name="wobble">xyz</Set> |
| <Set name="parent"><Ref refid="foo"/></Set> |
| <Call name="init"> |
| <Arg>false</Arg> |
| </Call> |
| </New> |
| </Set> |
| |
| <Ref refid="bar"> |
| <Set name="wibble">20</Set> |
| <Get name="parent"> |
| <Set name="name">demo2</Set> |
| </Get> |
| </Ref> |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The XML above is equivalent to the following Java code:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">com.acme.Foo foo = new com.acme.Foo(); |
| foo.setName("demo"); |
| |
| com.acme.Bar bar = new com.acme.Bar(true); |
| bar.setWibble(10); |
| bar.setWobble("xyz"); |
| bar.setParent(foo); |
| bar.init(false); |
| |
| foo.setNested(bar); |
| |
| bar.setWibble(20); |
| bar.getParent().setName("demo2");</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Overview</h4> |
| <div class="sect4"> |
| <h5 id="jetty-xml-dtd">Understanding DTD and Parsing</h5> |
| <div class="paragraph"> |
| <p>The document type descriptor |
| (<a href="https://github.com/eclipse/jetty.project/tree/master/jetty-xml/src/main/resources/org/eclipse/jetty/xml/configure_9_0.dtd?h=release-9">configure.dtd</a>) describes all valid elements in a Jetty XML configuration file using the Jetty IoC format. |
| The first two lines of an XML must reference the DTD to be used to validate the XML like:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| ...</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Typcically a good XML editor will fetch the DTD from the URL and use it to give syntax highlighting and validation while a configuration file is being edited. |
| Some editors also allows DTD files to be locally cached. |
| The URL may point to configure.dtd if you want the latest current version, or to a specific version like configure_9_3.dtd if you want a particular validation feature set.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Files that conform to the configure.dtd format are processed in Jetty by the <code>XmlConfiguration</code> class which may also validate the XML (using a version of the DTD from the classes jar file), but is by default run in a forgiving mode that tries to work around validation failures.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To ensure your <code>web.xml</code>, <code>web-fragment.xml</code> and <code>webdefault.xml</code> files are validated, you will also need to set the <code>validateXml</code> attribute to true:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Call name="setAttribute"> |
| <Arg>org.eclipse.jetty.webapp.validateXml</Arg> |
| <Arg type="Boolean">true</Arg> |
| </Call></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Jetty XML Configuration Scope</h5> |
| <div class="paragraph"> |
| <p>The configuration of object instances with Jetty IoC XML is done on a scoped basis, so that for any given XML element there is a corresponding Object in scope and the nested XML elements apply to that. |
| The outer most scope is given by a Configure element and elements like Call, New and Get establish new scopes. |
| The following example uses the name fields to explain the scope.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure class="com.example.Foo"> |
| <Set name="fieldOnFoo">value</Set> |
| <Set name="fieldOnFoo"> |
| <New class="com.example.Bar"> |
| <Set name=fieldOnBar>value</Set> |
| <Call name="methodOnBarWithNoArgs"/> |
| </New> |
| </Set> |
| |
| <Call name="methodOnFoo"> |
| <Arg>value for first arg of methodOnFoo</Arg> |
| <Arg><New class="com.example.Bar"/></Arg> |
| <Set name="fieldOnObjectReturnedByMethodOnFoo">value</Set> |
| <Call name="methodOnObjectReturnedByMethodOnFooWithNoArgs"/> |
| </Call> |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Coercing Arguments to a Type</h5> |
| <div class="paragraph"> |
| <p>When trying to match XML elements to java elements, Jetty <code>XmlConfiguration</code> may need to coerces values to match method arguments. |
| By default it does so on a best effort basis, but you can also specify explicit types with the <code>type</code> attribute. |
| Supported values for type are: <code>String</code>, <code>Character</code>, <code>Short</code>, <code>Byte</code>, <code>Integer</code>, <code>Long</code>, <code>Boolean</code>, <code>Float</code>, <code>Double</code>, <code>char</code>, <code>short</code>, <code>byte</code>, <code>int</code>, <code>long</code>, <code>boolean</code>, <code>float</code>, <code>double</code>, <code>URL</code>, <code>InetAddress</code>, <code>InetAddrPort</code>, and <code>void</code>.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Referring to a Class</h5> |
| <div class="paragraph"> |
| <p>If you do not specify the classname, Jetty assumes you are calling the method on the object that is current in scope (eg the object of the surrounding <code>Configure</code>, <code>New</code> or <code>Get</code> clause). |
| If the class attribute is specified to a fully-qualified class name, then it is either used to create a new instance (<code>Configure</code> and <code>New</code> elements) or is used to access a static (<code>Call</code>, <code>Set</code> or <code>Get</code> elements).</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Referring to an Object</h5> |
| <div class="paragraph"> |
| <p>You can use the id attribute to store a reference to the current object when first creating or referring to this object. |
| You can then use the <a href="#jetty-xml-ref">Ref element</a> to reference the object later. |
| The ID must be unique for each object you create.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Attribute vs Element Style</h5> |
| <div class="paragraph"> |
| <p>For XML elements that contain only other XML Elements, there is a choice of using attributes or elements style. |
| The following is an example of attribute style:</p> |
| </div> |
| <div class="literalblock"> |
| <div class="content"> |
| <pre> <Call id="result" class="org.example.SomeClass" name="someMethod" arg="value0,value1"/></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Attribute style has the benefit of brevity, but is limited by: values can only be Strings; multivalued items can not contain ','; values may not be subject to property expansion or other elements that return values. |
| Thus, the more verbose element style is available and the following is semantically equivalent to the attribute style above:</p> |
| </div> |
| <div class="literalblock"> |
| <div class="content"> |
| <pre> <Call> |
| <Id>result</Id> |
| <Class>org.example.SomeClass</Class> |
| <Name>someMethod</Name> |
| <Arg>value0</Arg> |
| <Arg>value1</Arg> |
| </Call></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Note that multivalued elements like <code>Arg</code> must be repeated and may not be comma-separated like they are when provided as attributes. |
| It is possible to use a mix of styles and the following example shows a moretypical example that uses property expansion as the reason for element style:</p> |
| </div> |
| <div class="literalblock"> |
| <div class="content"> |
| <pre> <Call id="result" name="someMethod"> |
| <Class><Property name="which.class"> |
| <Default><Property name="default.class" default="org.example.SomeClass"/> |
| </Property></Class> |
| <Arg>value0</Arg> |
| <Arg>value1</Arg> |
| </Call></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Attributes may not be expressed as elements when their parent element is one that contains data. |
| Thus <code>Arg</code>, <code>Item</code>, <code>Set</code>, <code>Put</code> and <code>Get</code> elements may not have their attributes expressed as elements.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-configure"><Configure></h4> |
| <div class="paragraph"> |
| <p>This is the root element that specifies the class of object that is to be configured. |
| It is usually either the Server, in <code>jetty.xml</code>, or a <code>WebAppContext</code> in <code>jetty-web.xml</code>.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">A reference to the object that was created. If you define |
| multiple <a href="#jetty-xml-configure">Configure element</a>s with the same id, |
| they will be treated as one object, even if they’re in different files. |
| You can use this to break up configuration of an object (such as the |
| Server) across multiple files.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">class</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The fully qualified classname of the object to be |
| configured. Could be <code>org.eclipse.jetty.server.Server</code>, |
| <code>org.eclipse.jetty.webapp.WebAppContext</code>, a handler, etc.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p><a href="#jetty-xml-set">Set element</a>, <a href="#jetty-xml-get">Get element</a>, |
| <a href="#jetty-xml-put">Put element</a>, <a href="#jetty-xml-call">Call element</a>, |
| <a href="#jetty-xml-new">New element</a>, <a href="#jetty-xml-ref">Ref element</a>, |
| <a href="#jetty-xml-array">Array element</a>, <a href="#jetty-xml-map">Map element</a>, |
| <a href="#jetty-xml-property">Property element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Examples</h5> |
| <div class="sect5"> |
| <h6>Basic Example</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure class="org.eclipse.jetty.server.Server"> |
| <Set name="port">8080</Set> |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">org.eclipse.jetty.server.Server server = new org.eclipse.jetty.server.Server(); |
| server.setPort(8080);</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Using id to break up configuration of one object across multiple files</h6> |
| <div class="paragraph"> |
| <p>In <code>etc/jetty.xml</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="Server" class="org.eclipse.jetty.server.Server"> |
| <!-- basic configuration here --> |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>In <code>etc/jetty-logging.xml</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="Server" class="org.eclipse.jetty.server.Server"> |
| <!-- assumes that you have the basic server configuration set up; this file only contains additional configuration for logging --> |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Then run the combined configuration using:</p> |
| </div> |
| <div class="literalblock"> |
| <div class="content"> |
| <pre>java -jar start.jar etc/jetty.xml jetty-logging.xml</pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-set"><Set></h4> |
| <div class="paragraph"> |
| <p>A Set element maps to a call to a setter method or field on the current object. |
| It can contain text and/or elements such as <code>Call</code>, <code>New</code>, <code>SystemProperty</code>, etc., as values. |
| The name and optional type attributes are used to select the setter method. |
| If you do not specify a value type, white space is trimmed out of the value. |
| If it contains multiple elements as values, they are added as strings before being converted to any specified type.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">yes</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">the name of the setter method to call, or the field to set. |
| If the name given is xxx, then a setXxx method is used. If the setXxx |
| method cannot be found, then the xxx field is used.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">the declared type of the argument. See also discussion of |
| type for Arg for how to define null and empty string values.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">class</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">if present, then this Set is treated as a static set method |
| invocation</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p>value text, <a href="#jetty-xml-get">Get element</a>, <a href="#jetty-xml-call">Call |
| element</a>, <a href="#jetty-xml-new">New element</a>, <a href="#jetty-xml-ref">Ref |
| element</a>, <a href="#jetty-xml-array">Array element</a>, <a href="#jetty-xml-map">Map |
| element</a>, <a href="#jetty-xml-system-property">System Property element</a>, |
| <a href="#jetty-xml-property">Property element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Examples</h5> |
| <div class="sect5"> |
| <h6>Basic Example</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="server" class="org.eclipse.jetty.server.Server"> |
| <Set name="port">8080</Set> |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Set via a System Property</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="server" class="org.eclipse.jetty.server.Server"> |
| <Set name="port"><SystemProperty name="jetty.http.port" /></Set> |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Creating a NewObject and Setting It on the Server</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="server" class="org.eclipse.jetty.server.Server"> |
| <Set name="threadPool"> |
| <New class="org.eclipse.jetty.util.thread.QueuedThreadPool"> |
| <Set name="minThreads">10</Set> |
| <Set name="maxThreads">1000</Set> |
| </New> |
| </Set> |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">org.eclipse.jetty.server.Server server = new org.eclipse.jetty.server.Server(); |
| |
| org.eclipse.jetty.util.thread.QueuedThreadPool threadPool = new org.eclipse.jetty.util.thread.QueuedThreadPool(); |
| threadPool.setMinThreads(10); |
| threadPool.setMaxThreads(1000); |
| |
| server.setThreadPool(threadPool);</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Invoking a Static Setter</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="server" class="org.eclipse.jetty.server.Server"> |
| <Set class="org.eclipse.jetty.util.log.Log" name="logToParent">loggerName</Set> |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-get"><Get></h4> |
| <div class="paragraph"> |
| <p>A Get element maps to a call to a getter method or field on the current object. |
| It can contain nested elements such as <code>Set</code>, <code>Put</code>, <code>Call</code>, etc.; these act on the object returned by the <code>Get</code> call.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">yes</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">the name of the getter method to call, or the field to get. |
| If the name given is xxx, then a getXxx method is used. If the getXxx |
| method cannot be found, then the xxx field is used.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">class</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">f present, then this Get is treated as a static getter or |
| field.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">if present, then you can use this id to refer to the returned |
| object later.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p><a href="#jetty-xml-set">Set element</a>, <a href="#jetty-xml-get">Get element</a>, |
| <a href="#jetty-xml-put">Put element</a>, <a href="#jetty-xml-call">Call element</a>, |
| <a href="#jetty-xml-new">New element</a>, <a href="#jetty-xml-ref">Ref element</a>, |
| <a href="#jetty-xml-array">Array element</a>, <a href="#jetty-xml-map">Map element</a>, |
| <a href="#jetty-xml-property">Property element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Examples</h5> |
| <div class="sect5"> |
| <h6>Basic Example</h6> |
| <div class="paragraph"> |
| <p>This simple example doesn’t do much on its own. |
| You would normally use this in conjunction with a <code><Ref id="Logger" /></code>.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="server" class="org.eclipse.jetty.server.Server"> |
| <Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log"/> |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Invoking a Static Getter and Call Methods on the Returned Object</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="server" class="org.eclipse.jetty.server.Server"> |
| <Get class="java.lang.System" name="out"> |
| <Call name="println"> |
| <Arg>Server version is: <Get class="org.eclipse.jetty.server.Server" name="version"/></Arg> |
| </Call> |
| </Get> |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-put"><Put></h4> |
| <div class="paragraph"> |
| <p>A Put element maps to a call to a put method on the current object, which must implement the Map interface. |
| It can contain text and/or elements such as <code>Call</code>, <code>New</code>, <code>SystemProperty</code>, etc. as values. |
| If you do not specify a no value type, white space is trimmed out of the value. |
| If it contains multiple elements as values, they are added as strings before being converted to any specified type.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">yes</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">used as the put key</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">forces the type of the value. See also discussion of type for |
| Arg for how to define null and empty string values.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p>value text, <a href="#jetty-xml-get">Get element</a>, <a href="#jetty-xml-call">Call |
| element</a>, <a href="#jetty-xml-new">New element</a>, <a href="#jetty-xml-ref">Ref |
| element</a>, <a href="#jetty-xml-array">Array element</a>, <a href="#jetty-xml-map">Map |
| element</a>, <a href="#jetty-xml-system-property">System Property element</a>, |
| <a href="#jetty-xml-property">Property element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Example</h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Get name="someKindOfMap"> |
| <Put name="keyName">objectValue</Put> |
| </Get></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-call"><Call></h4> |
| <div class="paragraph"> |
| <p>A <code>Call</code> element maps to an arbitrary call to a method on the current object. |
| It can contain a sequence of Arg elements followed by a sequence of configuration elements, such as Set, Put, Call. |
| The <Arg>s are passed as arguments to the method; the sequence of configuration elements act on the object returned by the original call.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">yes</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">the name of the arbitrary method to call. The method called |
| will use the exact name you provide it.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">class</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">if present, then this Call is treated as a static method.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">if present, you can use this id to refer to any object returned |
| by the call, for later use.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">arg</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">comma separated list of arguments may be used for simple |
| string values rather than Arg elements</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p>Attributes as elements (Id, Name, Class) plus <a href="#jetty-xml-arg">Arg |
| element</a>, <a href="#jetty-xml-set">Set element</a>, <a href="#jetty-xml-get">Get |
| element</a>, <a href="#jetty-xml-put">Put element</a>, <a href="#jetty-xml-call">Call |
| element</a>, <a href="#jetty-xml-new">New element</a>, <a href="#jetty-xml-ref">Ref |
| element</a>, <a href="#jetty-xml-array">Array element</a>, <a href="#jetty-xml-map">Map |
| element</a>, <a href="#jetty-xml-property">Property element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Examples</h5> |
| <div class="sect5"> |
| <h6>Basic example</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Call name="doFoo"> |
| <Arg>bar</Arg> |
| <Set name="test">1, 2, 3</Set> |
| </Call></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Object o2 = o1.doFoo("bar"); |
| o2.setTest("1, 2, 3");</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Invoking a static method</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Call class="com.acme.Foo" name="setString"> |
| <Arg>somestring</Arg> |
| </Call></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Which is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">com.acme.Foo.setString("somestring");</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Invoking the Actual MethodInstead of Relying on Getter/Setter Magic</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="Server" class="org.eclipse.jetty.server.Server"> |
| <Call name="getPort" id="port" /> |
| <Call class="com.acme.Environment" name="setPort"> |
| <Arg> |
| <Ref refid="port"/> |
| </Arg> |
| </Call> |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Which is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">org.mortbay.jetty.Server server = new org.mortbay.jetty.Server(); |
| com.acme.Environment.setPort( server.getPort() );</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-arg"><Arg></h4> |
| <div class="paragraph"> |
| <p>An Arg element can be an argument of either a method or a constructor. |
| Use it within <a href="#jetty-syntax-call">[jetty-syntax-call]</a> and <a href="#jetty-syntax-new">[jetty-syntax-new]</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It can contain text and/or elements, such as <code>Call</code>, <code>New</code>, <code>SystemProperty</code>, etc., as values. |
| The optional type attribute can force the type of the value. |
| If you don’t specify a type, white space is trimmed out of the value. |
| If it contains multiple elements as values, they are added as strings before being converted to any specified type. |
| Simple <code>String</code> arguments can also be specified as a string separated arg attribute on the parent element.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">force the type of the argument. If you do not provide a value |
| for the element, if you use type of "String", the value will be the |
| empty string (""), otherwise it is null.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p>value text, <a href="#jetty-xml-get">Get element</a>, <a href="#jetty-xml-call">Call |
| element</a>, <a href="#jetty-xml-new">New element</a>, <a href="#jetty-xml-ref">Ref |
| element</a>, <a href="#jetty-xml-array">Array element</a>, <a href="#jetty-xml-map">Map |
| element</a>, <a href="#jetty-xml-system-property">System Property element</a>, |
| <a href="#jetty-xml-property">Property element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Examples</h5> |
| <div class="sect5"> |
| <h6>Basic examples</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Arg>foo</Arg> <!-- String --> |
| <Arg>true</Arg> <!-- Boolean --> |
| <Arg>1</Arg> <!-- int, long, short, float, double --> |
| <Arg><Ref refid="foo" /></Arg> <!-- any object; reference a previously created object with id "foo", and pass it as a parameter --> |
| <Arg></Arg> <!-- null value --> |
| <Arg type="String"></Arg> <!-- empty string "" --></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Coercing Type</h6> |
| <div class="paragraph"> |
| <p>This explicitly coerces the type to a boolean:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Arg type="boolean">False</Arg></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>As a Parameter</h6> |
| <div class="paragraph"> |
| <p>Here are a couple of examples of <a href="#jetty-xml-arg">Arg element</a> being used as a parameter to methods and to constructors:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Call class="com.acme.Environment" name="setFoo"> |
| <Arg> |
| <New class="com.acme.Foo"> |
| <Arg>bar</Arg> |
| </New> |
| </Arg> |
| </Call></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">com.acme.Environment.setFoo(new com.acme.Foo("bar"));</code></pre> |
| </div> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><New class="com.acme.Baz"> |
| <Arg> |
| <Call id="bar" class="com.acme.MyStaticObjectFactory" name="createObject"> |
| <Arg>2</Arg> |
| </Call> |
| </Arg> |
| </New></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">new com.acme.Baz(com.acme.MyStaticObjectFactory.createObject(2));</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-new"><New></h4> |
| <div class="paragraph"> |
| <p>Instantiates an object. |
| Equivalent to <code>new</code> in Java, and allows the creation of a new object. |
| A <code>New</code> element can contain a sequence of <a href="#jetty-xml-arg"><code>Arg</code> element</a>'s, followed by a sequence of configuration elements (<code>Set</code>, <code>Put</code>, etc). |
| <a href="#jetty-xml-arg"><code>Arg</code> element</a>'s are used to select a constructor for the object to be created. |
| The sequence of configuration elements then acts on the newly-created object.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">class</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">yes</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">fully qualified classname, which determines the type of the |
| new object that is instantiated.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">gives a unique name to the object which can be referenced later |
| by Ref elements.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">arg</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">comma separated list of arguments may be used for simple |
| string values rather than Arg elements</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p>Attributes as elements (Id, Class) plus <a href="#jetty-xml-arg">Arg |
| element</a>, <a href="#jetty-xml-set">Set element</a>, <a href="#jetty-xml-get">Get |
| element</a>, <a href="#jetty-xml-put">Put element</a>, <a href="#jetty-xml-call">Call |
| element</a>, <a href="#jetty-xml-new">New element</a>, <a href="#jetty-xml-ref">Ref |
| element</a>, <a href="#jetty-xml-array">Array element</a>, <a href="#jetty-xml-map">Map |
| element</a>, <a href="#jetty-xml-property">Property element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Examples</h5> |
| <div class="sect5"> |
| <h6>Basic example</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><New class="com.acme.Foo"> |
| <Arg>bar</Arg> |
| </New></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Which is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">com.acme.Foo foo = new com.acme.Foo("bar");</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Instantiate with the Default Constructor</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><New class="com.acme.Foo" /></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Which is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">com.acme.Foo foo = new com.acme.Foo();</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Instantiate with Multiple Arguments, Then Configuring Further</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><New id="foo" class="com.acme.Foo"> |
| <Arg>bar</Arg> |
| <Arg>baz</Arg> |
| <Set name="test">1, 2, 3</Set> |
| </New></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Which is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Object foo = new com.acme.Foo("bar", "baz"); |
| foo.setTest("1, 2, 3");</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-ref"><Ref></h4> |
| <div class="paragraph"> |
| <p>A <code>Ref</code> element allows a previously created object to be referenced by a unique id. |
| It can contain a sequence of elements, such as <code>Set</code> or <code>Put</code> which then act on the referenced object. |
| You can also use a <code>Ref</code> element as a value for other elements such as <code>Set</code> and <code>Arg</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>Ref</code> element provides convenience and eases readability. |
| You can usually achieve the effect of the <code>Ref</code> by nesting elements (method calls), but this can get complicated very easily. |
| The Ref element makes it possible to refer to the same object if you’re using it multiple times, or passing it into multiple methods. |
| It also makes it possible to split up configuration across multiple files.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">refid</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">yes</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">the unique identifier used to name a previously created |
| object.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p><a href="#jetty-xml-set">Set element</a>, <a href="#jetty-xml-get">Get element</a>, |
| <a href="#jetty-xml-put">Put element</a>, <a href="#jetty-xml-call">Call element</a>, |
| <a href="#jetty-xml-new">New element</a>, <a href="#jetty-xml-ref">Ref element</a>, |
| <a href="#jetty-xml-array">Array element</a>, <a href="#jetty-xml-map">Map element</a>, |
| <a href="#jetty-xml-property">Property element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Examples</h5> |
| <div class="sect5"> |
| <h6>Basic example</h6> |
| <div class="paragraph"> |
| <p>Use the referenced object as an argument to a method call or constructor:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Get id="foo" name="xFoo" /> |
| <Set name="test"><Ref refid="foo"/></Set></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">foo = getXFoo(); |
| setSomeMethod(foo);</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Manipulating the Object Returned by Ref</h6> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Get id="foo" name="xFoo" /> |
| <Ref refid="foo"> |
| <Set name="test">1, 2, 3</Set> |
| </Ref></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">foo = getXFoo(); |
| foo.setTest("1, 2, 3");</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect5"> |
| <h6>Ref vs. Nested Elements</h6> |
| <div class="paragraph"> |
| <p>Here is an example of the difference in syntax between using the <code>Ref</code> element, and nesting method calls. |
| They are exactly equivalent:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><!-- using Ref in conjunction with Get --> |
| <Configure id="Server" class="org.eclipse.jetty.server.Server"> |
| <Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log"/> |
| <Ref refid="Logger"> |
| <Set name="debugEnabled">true</Set> |
| </Ref> |
| </Configure> |
| <!-- calling the setter directly on the object returned by Get --> |
| <Configure id="Server" class="org.eclipse.jetty.server.Server"> |
| <Get class="org.eclipse.jetty.util.log.Log" name="log"> |
| <Set name="debugEnabled">true</Set> |
| </Get> |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Here is a more practical example, taken from the handler configuration section in <code>etc/jetty.xml</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Set name="handler"> |
| <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection"> |
| <Set name="handlers"> |
| <Array type="org.eclipse.jetty.server.Handler"> |
| <Item> |
| <!-- create a new instance of a ContextHandlerCollection named "Contexts" --> |
| <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/> |
| </Item> |
| <Item> |
| <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/> |
| </Item> |
| <Item> |
| <!-- create a new instance of a RequestLogHandler named "RequestLog" --> |
| <New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler"/> |
| </Item> |
| </Array> |
| </Set> |
| </New> |
| </Set> |
| |
| <Call name="addBean"> |
| <Arg> |
| <New class="org.eclipse.jetty.deploy.ContextDeployer"> |
| <!-- pass in the ContextHandlerCollection object ("Contexts") that was created earlier, as an argument --> |
| <Set name="contexts"><Ref refid="Contexts"/></Set> |
| </New> |
| </Arg> |
| </Call> |
| |
| <!-- configure the RequestLogHandler object ("RequestLog") that we created earlier --> |
| <Ref refid="RequestLog"> |
| .... |
| </Ref></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-array"><Array></h4> |
| <div class="paragraph"> |
| <p>An <code>Array</code> element allows the creation of a new array.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">specify what types of items the array can contain.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">unique identifier you can use to refer to the array later.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p><a href="#jetty-xml-item">Item element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Example</h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Array type="java.lang.String"> |
| <Item>value0</Item> |
| <Item><New class="java.lang.String"><Arg>value1</Arg></New></Item> |
| </Array></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">String[] a = new String[] { "value0", new String("value1") };</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-item"><Item></h4> |
| <div class="paragraph"> |
| <p>An <code>Item</code> element defines an entry for Array and Map elements.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">force the types of value.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">unique identifier that you can use to refer to the array later.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p><a href="#jetty-xml-get">Get element</a>, <a href="#jetty-xml-call">Call element</a>, |
| <a href="#jetty-xml-new">New element</a>, <a href="#jetty-xml-ref">Ref element</a>, |
| <a href="#jetty-xml-array">Array element</a>, <a href="#jetty-xml-map">Map element</a>, |
| <a href="#jetty-xml-system-property">System Property element</a>, |
| <a href="#jetty-xml-property">Property element</a></p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-map"><Map></h4> |
| <div class="paragraph"> |
| <p>A <code>Map</code> element allows the creation of a new HashMap and to populate it with <code>(key, value)</code> pairs.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">unique identifier you can use to refer to the map later.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p><a href="#jetty-xml-entry">Entry element</a></p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Example</h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Map> |
| <Entry> |
| <Item>keyName</Item> |
| <Item><New class="java.lang.String"><Arg>value1</Arg></New></Item> |
| </Entry> |
| </Map></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Map m = new HashMap(); |
| m.put("keyName", new String("value1"));</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-entry"><Entry></h4> |
| <div class="paragraph"> |
| <p>An <code>Entry</code> element contains a key-value <a href="#jetty-xml-item">Item element</a> pair for a <code>Map</code>.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p><a href="#jetty-xml-item">Item element</a></p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-system-property"><SystemProperty></h4> |
| <div class="paragraph"> |
| <p>A <code>SystemProperty</code> element gets the value of a JVM system property. |
| It can be used within elements that accept values, such as <code>Set</code>, <code>Put</code>, <code>Arg</code>.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">yes</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">property name</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">default</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a default value as a fallback</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">unique identifier which you can use to refer to the array |
| later.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p>Only attributes as Elements (<code>Id</code>, <code>Name</code>, <code>Default</code>).</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Example</h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><SystemProperty name="jetty.http.port" default="8080"/></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>That is equivalent to:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">System.getProperty("jetty.http.port", "8080");</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Both try to retrieve the value of <code>jetty.http.port</code>. |
| If <code>jetty.http.port</code> is not set, then 8080 is used.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-property"><Property></h4> |
| <div class="paragraph"> |
| <p>A <code>Property</code> element allows arbitrary properties to be retrieved by name. |
| It can contain a sequence of elements, such as <code>Set</code>, <code>Put</code>, <code>Call</code> that act on the retrieved object.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3333%;"> |
| <col style="width: 33.3334%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Attribute</th> |
| <th class="tableblock halign-left valign-top">Required</th> |
| <th class="tableblock halign-left valign-top">Description</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">yes</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">property name</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">default</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">a default value as a fallback</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">no</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">unique identifier which you can use to refer to the array |
| later.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>The <code>Name</code> attribute may be a comma separated list of property names, with the first property name being the "official" name, and the others names being old, deprecated property names that are kept for backward compatibility. |
| A warning log is issued when deprecated property names are used. |
| The <code>Default</code> attribute contains the value to use in case none of the property names is found.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Can Contain</h5> |
| <div class="paragraph"> |
| <p>The attributes may be expressed as contained Elements (<code>Id</code>, <code>Name</code>, <code>Default</code>).</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Example</h5> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Property name="Server"> |
| <Call id="jdbcIdMgr" name="getAttribute"> |
| <Arg>jdbcIdMgr</Arg> |
| </Call> |
| </Property></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-xml-usage">Jetty XML Usage</h3> |
| <div class="paragraph"> |
| <p>Jetty provides an XML-based configuration. |
| It is grounded in Java’s Reflection API. Classes in the <code>java.lang.reflect</code> represent Java methods and classes, such that you can instantiate objects and invoke their methods based on their names and argument types. |
| Behind the scenes, Jetty’s XML config parser translates the XML elements and attributes into Reflection calls.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="using-jettyxml">Using jetty.xml</h4> |
| <div class="paragraph"> |
| <p>To use <code>jetty.xml</code>, specify it as a configuration file when running Jetty.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java"> java -jar start.jar etc/jetty.xml</code></pre> |
| </div> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| If you start Jetty without specifying a configuration file, Jetty automatically locates and uses the default installation <code>jetty.xml</code> file. |
| Therefore <code>java -jar start.jar</code> is equivalent to <code>java -jar start.jar etc/jetty.xml</code> . |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="using-multiple-configuration-files">Using Multiple Configuration Files</h4> |
| <div class="paragraph"> |
| <p>You are not limited to one configuration file; you can use multiple configuration files when running Jetty, and Jetty will configure the appropriate server instance. |
| The ID of the server in the <code><Configure></code> tag specifies the instance you want to configure. |
| Each server ID in a configuration file creates a new server instance within the same JVM. |
| If you use the same ID across multiple configuration files, those configurations are all applied to the same server.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="setting-parameters-in-configuration-files">Setting Parameters in Configuration Files</h4> |
| <div class="paragraph"> |
| <p>You can set parameters in configuration files either with system properties (using <code><SystemProperty></code>) or properties files (using <code><Property></code>) passed via the command line. |
| For example, this code in <code>jetty.xml</code> allows the port to be defined on the command line, falling back onto `8080`if the port is not specified:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"> <Set name="port"><SystemProperty name="jetty.http.port" default="8080"/></Set></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Then you modify the port while running Jetty by using this command:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java"> java -Djetty.http.port=8888 -jar start.jar etc/jetty.xml</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>An example of defining both system properties and properties files from the command line:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java"> java -Djetty.http.port=8888 -jar start.jar myjetty.properties etc/jetty.xml etc/other.xml</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-xml-config">jetty.xml</h3> |
| <div class="paragraph"> |
| <p><code>jetty.xml</code> is the default configuration file for Jetty, typically located at <code>$JETTY_HOME/etc/jetty.xml</code>. Usually the <code>jetty.xml</code> configures:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>The Server class (or subclass if extended) and global options.</p> |
| </li> |
| <li> |
| <p>A ThreadPool (min and max thread).</p> |
| </li> |
| <li> |
| <p>Connectors (ports, timeouts, buffer sizes, protocol).</p> |
| </li> |
| <li> |
| <p>The handler structure (default handlers and/or a contextHandlerCollections).</p> |
| </li> |
| <li> |
| <p>The deployment manager that scans for and deploys webapps and contexts.</p> |
| </li> |
| <li> |
| <p>Login services that provide authentication checking.</p> |
| </li> |
| <li> |
| <p>A request log.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Not all Jetty features are configured in <code>jetty.xml</code>. |
| There are several optional configuration files that share the same format as <code>jetty.xml</code> and, if specified, concatenate to it. |
| These configuration files are also stored in <code>$JETTY_HOME/etc/</code>, and examples of them are in <a href="http://github.com/eclipse/jetty.project/jetty-server/src/main/config/etc/">Github Repository</a>. |
| The selection of which configuration files to use is controlled by <code>start.jar</code> and the process of merging configuration is described in <a href="#jetty-xml-usage">Jetty XML Usage</a>.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="root-element-jetty-xml">Root Element</h4> |
| <div class="paragraph"> |
| <p><code>jetty.xml</code> configures an instance of the <code>Jetty org.eclipse.jetty.server.Server.</code></p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0"?> |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| |
| <Configure id="Server" class="org.eclipse.jetty.server.Server"> |
| ... |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-examples">Examples</h4> |
| <div class="paragraph"> |
| <p><code>$JETTY_HOME/etc</code> contains the default <code>jetty.xml</code>, as well as other sample configuration files (<code>jetty-*.xml</code>) which can be passed to the server via the command line.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-xml-additional-resources">Additional Resources</h4> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#jetty-xml-syntax">Jetty XML Syntax</a> –in-depth reference for Jetty-specific configuration XML syntax.</p> |
| </li> |
| <li> |
| <p><a href="#jetty-xml-config">jetty.xml</a> –configuration file for configuring the entire server</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-web-xml-config">jetty-web.xml</h3> |
| <div class="paragraph"> |
| <p><code>jetty-web.xml</code> is a Jetty configuration file that you can bundle with a specific web application. |
| The format of <code>jetty-web.xml</code> is the same as <a href="#jetty-xml-config">jetty.xml</a> – it is an XML mapping of the Jetty API.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This document offers an overview for using the <code>jetty-web.xml</code> configuration file. |
| For a more in-depth look at the syntax, see <a href="#jetty-xml-syntax">Jetty XML Syntax</a>.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="root-element-jetty-web-xml">Root Element</h4> |
| <div class="paragraph"> |
| <p><code>jetty-web.xml</code> applies on a per-webapp basis, and configures an instance of <code>org.eclipse.jetty.webapp.WebAppContext</code>.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| |
| <Configure class="org.eclipse.jetty.webapp.WebAppContext"> |
| .. |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock caution"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-caution" title="Caution"></i> |
| </td> |
| <td class="content"> |
| Make sure you are applying the configuration to an instance of the proper class. <code>jetty-web.xml</code> configures an instance of <code>WebAppContext</code>; <code>jetty.xml</code> configures an instance of <code>Server</code>. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="using-jetty-web-xml">Using jetty-web.xml</h4> |
| <div class="paragraph"> |
| <p>Place the <code>jetty-web.xml</code> into your web application’s <code>WEB-INF</code> folder. |
| When Jetty deploys a web application, it looks for a file called <code>WEB-INF/jetty-web.xml</code> or <code>WEB-INF/web-jetty.xml</code> within the web application (or WAR) and applies the configuration found there. |
| Be aware that <code>jetty-web.xml</code> is called <em>after</em> all other configuration has been applied to the web application.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock important"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-important" title="Important"></i> |
| </td> |
| <td class="content"> |
| It is important to note that <code>jetty-web.xml</code> files utilize the webapp classpath, not the classpath of the server. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-web-xml-examples">jetty-web.xml Examples</h4> |
| <div class="paragraph"> |
| <p>The distribution contains an example of <code>jetty-web.xml</code> inside the WEB-INF folder of the <code>test</code> webapp WAR (<code>$JETTY_HOME/demo-base/webapps/test.war/WEB-INF/jetty-web.xml</code>).</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="additional-jetty-web-xml-resources">Additional <code>jetty-web.xml</code> Resources</h4> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#jetty-xml-syntax">Jetty XML Syntax</a> –in-depth reference for Jetty-specific configuration XML syntax.</p> |
| </li> |
| <li> |
| <p><a href="#jetty-xml-config">jetty.xml</a> –configuration file for configuring the entire server</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jetty-env-xml">jetty-env.xml</h3> |
| <div class="paragraph"> |
| <p><code>jetty-env.xml</code> is an optional Jetty file that configures JNDI resources for an individual webapp. |
| The format of <code>jetty-env.xml</code> is the same as <a href="#jetty-xml-config">jetty.xml</a> –it is an XML mapping of the Jetty API.</p> |
| </div> |
| <div class="paragraph"> |
| <p>When Jetty deploys a web application, it automatically looks for a file called ` WEB-INF/jetty-env.xml` within the web application (or WAR), and sets up the webapp naming environment so that naming references in the <code>WEB-INF/web.xml</code> file can be resolved from the information provided in the <code>WEB-INF/jetty-env.xml</code> and <a href="#jetty-xml-config">jetty.xml</a> files. |
| You define global naming resources on the server via <code>jetty.xml</code>.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="jetty-env-root-element">jetty-env.xml Root Element</h4> |
| <div class="paragraph"> |
| <p>Jetty applies <code>jetty-env.xml</code> on a per-webapp basis, and configures an instance of <code>org.eclipse.jetty.webapp.WebAppContext.</code></p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| |
| <Configure class="org.eclipse.jetty.webapp.WebAppContext"> |
| .. |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock caution"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-caution" title="Caution"></i> |
| </td> |
| <td class="content"> |
| Make sure you are applying the configuration to an instance of the proper class. <code>jetty-env.xml</code> configures an instance of WebAppContext, and not an instance of Server. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="using-jetty-env-xml">Using <code>jetty-env.xml</code></h4> |
| <div class="paragraph"> |
| <p>Place the <code>jetty-env.xml</code> file in your web application’s WEB-INF folder.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"> <?xml version="1.0"?> |
| <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd"> |
| |
| <Configure class="org.eclipse.jetty.webapp.WebAppContext"> |
| |
| <!-- Add an EnvEntry only valid for this webapp --> |
| <New id="gargle" class="org.eclipse.jetty.plus.jndi.EnvEntry"> |
| <Arg>gargle</Arg> |
| <Arg type="java.lang.Double">100</Arg> |
| <Arg type="boolean">true</Arg> |
| </New> |
| |
| <!-- Add an override for a global EnvEntry --> |
| <New id="wiggle" class="org.eclipse.jetty.plus.jndi.EnvEntry"> |
| <Arg>wiggle</Arg> |
| <Arg type="java.lang.Double">55.0</Arg> |
| <Arg type="boolean">true</Arg> |
| </New> |
| |
| <!-- an XADataSource --> |
| <New id="mydatasource99" class="org.eclipse.jetty.plus.jndi.Resource"> |
| <Arg>jdbc/mydatasource99</Arg> |
| <Arg> |
| <New class="com.atomikos.jdbc.SimpleDataSourceBean"> |
| <Set name="xaDataSourceClassName">org.apache.derby.jdbc.EmbeddedXADataSource</Set> |
| <Set name="xaDataSourceProperties">databaseName=testdb99;createDatabase=create</Set> |
| <Set name="UniqueResourceName">mydatasource99</Set> |
| </New> |
| </Arg> |
| </New> |
| |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="additional-jetty-env-xml-resources">Additional jetty-env.xml Resources</h4> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#jetty-xml-syntax">Jetty XML Syntax</a> –In-depth reference for Jetty-specific configuration XML syntax.</p> |
| </li> |
| <li> |
| <p><a href="#jetty-xml-config">jetty.xml</a> –Configuration file for configuring the entire server.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="webdefault-xml">webdefault.xml</h3> |
| <div class="paragraph"> |
| <p>The <code>webdefault.xml</code> file saves web applications from having to define a lot of house-keeping and container-specific elements in their own <code>web.xml</code> files. |
| For example, you can use it to set up MIME-type mappings and JSP servlet-mappings. |
| Jetty applies <code>webdefault.xml</code> to a web application <em>before</em> the application’s own <code>WEB-INF/web.xml</code>, which means that it <strong>cannot</strong> override values inside the webapp’s <code>web.xml</code>. |
| It uses the <a href="#jetty-xml-config">jetty.xml</a> syntax. |
| Generally, it is convenient for all webapps in a Jetty instance to share the same <code>webdefault.xml</code> file. |
| However, it is certainly possible to provide differentiated ` webdefault.xml` files for individual web applications.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>webdefault.xml</code> file is located in <code>$(jetty.home)/etc/webdefault.xml</code>.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="using-webdefault-xml">Using webdefault.xml</h4> |
| <div class="paragraph"> |
| <p>You can specify a custom configuration file to use for specific webapps, or for all webapps. If you do not specify an alternate defaults descriptor, the <code>$JETTY-HOME/etc/jetty-deploy.xml</code> file will configure jetty to automatically use <code>$JETTY_HOME/etc/webdefault.xml</code>.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| To ensure your <code>webdefault.xml</code> files are validated, you will need to set the <code>validateXml</code> attribute to true as described <a href="#jetty-xml-dtd">here.</a> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>webdefault.xml</code> <a href="{GITBROWSURL}/jetty-webapp/src/main/config/etc/webdefault.xml">included with the Jetty Distribution</a> contains several configuration options, such as init params and servlet mappings, and is separated into sections for easy navigation. |
| Some of the more common options include, but are not limited to:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">dirAllowed</dt> |
| <dd> |
| <p>If true, directory listings are returned if no welcome file is found. |
| Otherwise 403 Forbidden displays.</p> |
| </dd> |
| <dt class="hdlist1">precompressed</dt> |
| <dd> |
| <p>If set to a comma separated list of file extensions, these indicate compressed formats that are known to map to a MIME-type that may be listed in a requests Accept-Encoding header. |
| If set to a boolean True, then a default set of compressed formats will be used, otherwise no pre-compressed formats.</p> |
| </dd> |
| <dt class="hdlist1">maxCacheSize</dt> |
| <dd> |
| <p>Maximum total size of the cache or 0 for no cache.</p> |
| </dd> |
| <dt class="hdlist1">maxCachedFileSize</dt> |
| <dd> |
| <p>Maximum size of a file to cache.</p> |
| </dd> |
| <dt class="hdlist1">maxCachedFiles</dt> |
| <dd> |
| <p>Maximum number of files to cache.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="sect4"> |
| <h5 id="creating-custom-webdefault-xml-one-webapp">Creating a Custom webdefault.xml for One WebApp</h5> |
| <div class="paragraph"> |
| <p>You can specify a custom <code>webdefault.xml</code> for an individual web application in that webapp’s <a href="#jetty-xml-config">jetty.xml</a> as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure class="org.eclipse.jetty.webapp.WebAppContext"> |
| ... |
| <!-- Set up the absolute path to the custom webdefault.xml --> |
| <Set name="defaultsDescriptor">/my/path/to/webdefault.xml</Set> |
| ... |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The equivalent in code is:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">import org.eclipse.jetty.webapp.WebAppContext; |
| |
| ... |
| |
| WebAppContext wac = new WebAppContext(); |
| ... |
| //Set up the absolute path to the custom webdefault.xml. |
| wac.setDefaultsDescriptor("/my/path/to/webdefault.xml"); |
| ...</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Alternatively, you can use a <a href="#jetty-classloading">Jetty Classloading</a> to find the resource representing your custom <code>webdefault.xml</code>.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="creating-custom-webdefault-xml-multiple-webapps">Creating a Custom webdefault.xml for Multiple WebApps</h5> |
| <div class="paragraph"> |
| <p>If you want to apply the same custom <code>webdefault.xml</code> to a number of webapps, provide the path to the file in <a href="#jetty-xml-config">jetty.xml</a> in the <code>$JETTY_HOME/etc/jetty-deploy.xml</code> file:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"> <Set name="defaultsDescriptor"><Property name="jetty.home" default="." />/other/path/to/another/webdefault.xml</Set></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="webdefault-xml-using-jetty-maven-plugin">Using the Jetty Maven Plugin</h5> |
| <div class="paragraph"> |
| <p>Similarly, when using the <a href="#jetty-maven-plugin">Jetty Maven Plugin</a> you provide a customized <code>webdefault.xml</code> file for your webapp as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project> |
| ... |
| <plugins> |
| <plugin> |
| ... |
| <artifactId>jetty-maven-plugin</artifactId> |
| <configuration> |
| <webApp> |
| ... |
| <defaultsDescriptor>/my/path/to/webdefault.xml</defaultsDescriptor> |
| </webApp> |
| </configuration> |
| </plugin> |
| ... |
| </plugins> |
| ... |
| </project></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="webdefault-xml-additional-resources">Additional Resources</h5> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#jetty-web-xml-config">jetty-web.xml</a> –Reference for <code>web.xml</code> files</p> |
| </li> |
| <li> |
| <p><a href="#override-web-xml">Jetty override-web.xml</a> –Information for this <code>web.xml</code> -formatted file, applied after the webapp’s <code>web.xml</code> webapp.</p> |
| </li> |
| <li> |
| <p><a href="#jetty-xml-config">jetty.xml</a> –Reference for <code>jetty.xml</code> files</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="override-web-xml">Jetty override-web.xml</h3> |
| <div class="paragraph"> |
| <p>To deploy a web application or WAR into different environments, most likely you will need to customize the webapp for compatibility with each environment. |
| The challenge is to do so without changing the webapp itself. You can use a <code>jetty.xml</code> file for some of this work since it is not part of the webapp. |
| But there are some changes that <code>jetty.xml</code> cannot accomplish, for example, modifications to servlet init-params and context init-params. |
| Using <code>webdefault.xml</code> is not an option because Jetty applies <code>webdefault.xml</code> to a web application <em>before</em> the application’s own <code>WEB-INF/web.xml</code>, which means that it cannot override values inside the webapp’s ` web.xml`.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The solution is <code>override-web.xml</code>. |
| It is a <code>web.xml</code> file that Jetty applies to a web application <em>after</em> the application’s own <code>WEB-INF/web.xml</code>, which means that it can override values or add new elements. |
| This is defined on a per-webapp basis, using the <a href="#jetty-xml-syntax">Jetty XML Syntax</a>.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="using-override-web-xml">Using override-web.xml</h4> |
| <div class="paragraph"> |
| <p>You can specify the <code>override-web.xml</code> to use for an individual web application in a deployable xml file located in Jetty webapps folder . |
| For example, if you had a webapp named MyApp, you would place a deployable xml file named <code>myapp.xml</code> in <code>${jetty.base}/webapps</code> which includes an <code>overrideDescriptor</code> entry for the <code>override-web.xml</code> file.</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure class="org.eclipse.jetty.webapp.WebAppContext"> |
| ... |
| <!-- Set up the path to the custom override descriptor, |
| relative to your $(jetty.home) directory or to the current directory --> |
| <Set name="overrideDescriptor"><SystemProperty name="jetty.home" default="."/>/my/path/to/override-web.xml</Set> |
| ... |
| </Configure></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The equivalent in code is:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">import org.eclipse.jetty.webapp.WebAppContext; |
| |
| ... |
| |
| WebAppContext wac = new WebAppContext(); |
| ... |
| //Set the path to the override descriptor, based on your $(jetty.home) directory |
| wac.setOverrideDescriptor(System.getProperty("jetty.home")+"/my/path/to/override-web.xml"); |
| ...</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Alternatively, you can use the classloader (<a href="#jetty-classloading">Jetty Classloading</a>) to get the path to the override descriptor as a resource.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="override-using-jetty-maven-plugin">Using the Jetty Maven Plugin</h4> |
| <div class="paragraph"> |
| <p>Use the <code><overrideDescriptor></code> tag as follows:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><project> |
| ... |
| <plugins> |
| <plugin> |
| ... |
| <artifactId>jetty-maven-plugin</artifactId> |
| <configuration> |
| <webAppConfig> |
| ... |
| <overrideDescriptor>src/main/resources/override-web.xml</overrideDescriptor> |
| </webAppConfig> |
| </configuration> |
| </plugin> |
| ... |
| </plugins> |
| ... |
| </project></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="override-web-xml-additional-resources">Additional Resources</h4> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#webdefault-xml">webdefault.xml</a> –Information for this <code>web.xml</code> -formatted file, applied before the webapp’s <code>web.xml</code> webapp.</p> |
| </li> |
| <li> |
| <p><a href="#jetty-xml-config">jetty.xml</a> –Reference for <code>jetty.xml</code> files</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="troubleshooting">Troubleshooting</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>This is a collection of helpful tricks and tips that we have come across to address odd issues that might arise.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="troubleshooting-zip-exceptions">Troubleshooting Zip Exceptions</h3> |
| <div class="paragraph"> |
| <p>A Zip exception occurs when Jetty rereads a Jar or WAR file.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The JVM maintains a cache of zip file indexes, and does not support hot replacement of zip files. |
| Thus if you redeploy a web application using the same WAR or Jar files, exceptions occur when Jetty rereads the jars. |
| See <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4774421">Oracle Bug 4774421</a> for more information.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="remedy">Remedy</h4> |
| <div class="paragraph"> |
| <p>The remedy is to avoid hot replacing Jar or WAR files, which can be difficult if you are using the |
| <a href="#configuring-specific-webapp-deployment">Webapp Provider</a>. |
| You can use the following techniques to reduce exposure to this issue:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Deploy unpacked classes in the <code>WEB-INF/classes</code> directory rather than as a Jar file under <code>WEB-INF/lib</code>.</p> |
| </li> |
| <li> |
| <p>Deploy all WAR and Jar files with a version number in their filename or path. |
| If the code changes, a new version number applies, avoiding the cache problem.</p> |
| </li> |
| <li> |
| <p>Deploy a packed WAR file with the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setExtractWAR(boolean)">setExtractWAR</a> option set to true. |
| This causes the WAR to be extracted to a <a href="#ref-temporary-directories">temporary directory</a> and thus to a new location. |
| This might not be sufficient if you want to hot-replace and re-extract the WAR, so you might also need to use <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setCopyWebInf(boolean)">WebAppContext.setCopyWebInf(true)</a>, which (re)copies just the WEB-INF directory to a different location.</p> |
| </li> |
| <li> |
| <p>Deploy an unpacked WAR file with the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setCopyWebDir(boolean)">setCopyWebDir</a> option set to true. |
| This causes the directory to be extracted to a new location.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If you have problems with <a href="#troubleshooting-locked-files-on-windows">Windows file-locking</a> preventing static file editing (such as JSP or HTML), use the <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/webapp/WebAppContext.html#setCopyWebDir(boolean)">WebAppContext .setCopyWebDir(true)</a> option.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="troubleshooting-locked-files-on-windows">Troubleshooting Locked Files on Windows</h3> |
| <div class="paragraph"> |
| <p>Jetty buffers static content for webapps such as HTML files, CSS files, images, etc. |
| If you are using NIO connectors, Jetty uses memory-mapped files to do this. |
| The problem is that on Windows, memory mapping a file causes the file to lock, so that you cannot update or replace the file. |
| Effectively this means that you have to stop Jetty to update a file.</p> |
| </div> |
| <div class="sect3"> |
| <h4>Remedy</h4> |
| <div class="paragraph"> |
| <p>Jetty provides a configuration switch for the <code>DefaultServlet</code> that enables or disables the use of memory-mapped files. |
| If you are running on Windows and are having file-locking problems, you should set this switch to disable memory-mapped file buffers. |
| Use one of the following options to configure the switch.</p> |
| </div> |
| <div class="sect4"> |
| <h5>Using override-web.xml</h5> |
| <div class="paragraph"> |
| <p>An <a href="#override-web-xml">override-web.xml</a> file can be placed in your webapp’s <code>WEB-INF</code> directory to change the default setting of the <code>DefaultServlet</code> for memory-mapped file buffers. |
| Create an <code>override-web.xml</code> file with appropriate headers for your version of the servlet specification, and place the following inside the <code><web-app></code> element:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"> <servlet> |
| <servlet-name>default</servlet-name> |
| <init-param> |
| <param-name>useFileMappedBuffer</param-name> |
| <param-value>false</param-value> |
| </init-param> |
| </servlet></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Using a Context XML File</h5> |
| <div class="paragraph"> |
| <p>You can create or update a context xml file that configures your webapp to apply the setting to disable memory-mapped file buffers. |
| Add the following to your context xml file:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"> <Call name="setInitParameter"> |
| <Arg>org.eclipse.jetty.servlet.Default.useFileMappedBuffer</Arg> |
| <Arg>false</Arg> |
| </Call></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Using the Jetty Maven Plugin</h5> |
| <div class="paragraph"> |
| <p>If you don’t want to use either of the other two solutions, you can configure the plugin directly to disable memory-mapped file buffers. |
| Add the following to the plugin’s configuration under the <code><webApp></code> element:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"> <_initParams> |
| <org.eclipse.jetty.servlet.Default.useFileMappedBuffer>false</org.eclipse.jetty.servlet.Default.useFileMappedBuffer> |
| </_initParams></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4>Alternate Remedy</h4> |
| <div class="paragraph"> |
| <p>You can force a <code>WebAppContext</code> to always copy a web app directory on deployment. |
| The base directory of your web app (i.e. the root directory where your static content exists) will be copied to the <a href="#ref-temporary-directories">temp directory</a>. |
| Configure this in an xml file like so:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><New id="myWebAppContext" class="org.eclipse.jetty.webapp.WebAppContext"> |
| <Set name="contextPath">/</Set> |
| <Set name="war">./webapps/fredapp</Set> |
| <Set name="copyWebDir">true</Set> |
| . |
| . |
| </New></code></pre> |
| </div> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| Be careful with this option when using an explicitly set<a href="#ref-temp-directories">temp directory</a> name - as the name of the temp directory will not unique across redeployments, copying the static content into the same directory name each time may not avoid the locking problem. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="preventing-memory-leaks">Preventing Memory Leaks</h3> |
| <div class="paragraph"> |
| <p>If you have memory leaks, and you have thoroughly investigated tools like jconsole, yourkit, jprofiler, jvisualvm or any of the other profiling and analysis tools, and you can eliminate your code as the source of the problem, read the following sections about how to prevent memory leaks in your application.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="preventing-webapp-classloader-pinning">Preventing WebApp Classloader Pinning</h4> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| This feature is available for Jetty 7.6.6 and later. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>Code that keeps references to a webapp classloader can cause memory leaks. |
| These leaks fall generally into two categories: static fields and daemon threads.</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>A static field is initialized with the value of the classloader, which happens to be a webapp classloader; as Jetty undeploys and redeploys the webapp, the static reference lives on, meaning garbage collecting cannot occur for the webapp classloader.</p> |
| </li> |
| <li> |
| <p>When Jetty starts as a daemon thread and is outside the lifecycle of the webapp, threads have references to the context classloader that created them, leading to a memory leak if that classloader belongs to a webapp. |
| For a good discussion of the issue see <a href="http://cdivilly.wordpress.com/tag/sun-awt-appcontext/">Anatomy of a PermGen Memory Leak.</a></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>We provide a number of <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT//org/eclipse/jetty/util/preventers/package-summary.html">workaround classes</a> that preemptively invoke the problematic code with the Jetty classloader, thereby ensuring the webapp classloader is not pinned. |
| Be aware that since some of the problematic code creates threads, you should be selective about which preventers you enable, and use only those that are specific to your application.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="preventers-table">Preventers</h5> |
| <div class="paragraph"> |
| <p>Jetty includes the following preventers.</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 50%;"> |
| <col style="width: 50%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">Preventer Name</th> |
| <th class="tableblock halign-left valign-top">Problem Addressed</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">AppContextLeakPreventer</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The call to <code>AppContext.getAppContext()</code> keeps a static reference to the context classloader. The JRE can invoke AppContext in many different places.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">AWTLeakPreventer</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The <code>java.awt.Toolkit</code> class has a static field that is the default toolkit. |
| Creating the default toolkit causes the creation of an <code>EventQueue</code>, which has a classloader field initialized with the thread context class loader. |
| See <a href="https://issues.jboss.org/browse/AS7-3733">JBoss bug AS7-3733.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">DOMLeakPreventer</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">DOM parsing can cause the webapp classloader to be pinned, due to the static field ` RuntimeException` of <code>com.sun.org.apache.xerces.internal.parsers.AbstractDOMParser.</code> <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6916498">Oracle bug 6916498</a> specifically mentions that a heap dump might not identify the GCRoot as the uncollected loader, making it difficult to identify the cause of the leak.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">DriverManagerLeakPreventer</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The number of threads dedicated to accepting incoming connections.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">GCThreadLeakPreventer</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Calls to <code>sun.misc.GC.requestLatency</code> create a daemon thread that keeps a reference to the context classloader. |
| A known caller of this method is the RMI impl. See <a href="http://stackoverflow.com/questions/6626680/does-java-garbage-collection-log-entry-full-gc-system-mean-some-class-called">Stackoverflow: Does java garbage collection log entry 'Full GC system' mean some class |
| called System.gc()?</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Java2DLeakPreventer</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><code>sun.java2d.Disposer</code> keeps a reference to the classloader. |
| See <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=51687">ASF bug 51687.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">LDAPLeakPreventer</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">If <code>com.sun.jndi.LdapPoolManager</code> class is loaded and the system property ` com.sun.jndi.ldap.connect.pool.timeout` is set to a nonzero value, a daemon thread starts and keeps a reference to the context classloader.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">LoginConfigurationLeakPreventer</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">The <code>javax.security.auth.login.Configuration</code> class keeps a static reference to the thread context classloader.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">SecurityProviderLeakPreventer</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Some security providers, such as <code>sun.security.pkcs11.SunPKCS11</code> start a deamon thread that traps the thread context classloader.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| <div class="sect4"> |
| <h5 id="configuring-preventers">Configuring Preventers</h5> |
| <div class="paragraph"> |
| <p>You can individually enable each preventer by adding an instance to a Server with the ` addBean(Object)` call. Here’s an example of how to do it in code with the <code>org.eclipse.jetty.util.preventers.AppContextLeakPreventer</code>:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Server server = new Server(); |
| server.addBean(new AppContextLeakPreventer());</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You can add the equivalent in code to the <code>$JETTY_HOME/etc/jetty.xml</code> file or any jetty xml file that is configuring a Server instance. |
| Be aware that if you have more than one Server instance in your JVM, you should configure these preventers on just <em>one</em> of them. |
| Here’s the example from code put into xml:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-xml" data-lang="xml"><Configure id="Server" class="org.eclipse.jetty.server.Server"> |
| |
| <Call name="addBean"> |
| <Arg> |
| <New class="org.eclipse.jetty.util.preventers.AppContextLeakPreventer"/> |
| </Arg> |
| </Call> |
| |
| </Configure></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jsp-bugs">JSP Bugs: Permgen Problems</h4> |
| <div class="paragraph"> |
| <p>The JSP engine in Jetty is Jasper. |
| This was originally developed under the Apache Tomcat project, but over time many different project have forked it. |
| All Jetty versions up to 6 used Apache-based Jasper exclusively, with Jetty 6 using Apache Jasper only for JSP 2.0. |
| With the advent of JSP 2.1, Jetty 6 switched to using Jasper from Sun’s <a href="https://glassfish.java.net/">Glassfish</a> project, which is now the reference implementation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>All forks of Jasper suffer from a problem whereby using JSP tag files puts the permgen space under pressure. |
| This is because of the classloading architecture of the JSP implementation. |
| Each JSP file is effectively compiled and its class loaded in its own classloader to allow for hot replacement. |
| Each JSP that contains references to a tag file compiles the tag if necessary and then loads it using its own classloader. |
| If you have many JSPs that refer to the same tag file, the tag’s class is loaded over and over again into permgen space, once for each JSP. |
| See <a href="http://java.net/jira/browse/GLASSFISH-3963">Glassfish bug 3963</a> and <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=43878">Apache bug 43878.</a> |
| The Apache Tomcat project has already closed this bug with status WON’T FIX, however the Glassfish folks still have the bug open and have scheduled it to be fixed. |
| When the fix becomes available, the Jetty project will pick it up and incorporate into our release program.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="jvm-bugs">JVM Bugs</h4> |
| <div class="paragraph"> |
| <p>This section describes garbage collection and direct ByteBuffer problems.</p> |
| </div> |
| <div class="sect4"> |
| <h5 id="jvm-garbage-collection-problems">Garbage Collection Problems</h5> |
| <div class="paragraph"> |
| <p>One symptom of a cluster of JVM related memory issues is the OOM exception accompanied by a message such as <code>java.lang.OutOfMemoryError: requested xxxx bytes for xxx. |
| Out of swap space?</code></p> |
| </div> |
| <div class="paragraph"> |
| <p><a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4697804">Oracle bug 4697804</a> describes how this can happen in the scenario when the garbage collector needs to allocate a bit more space during its run and tries to resize the heap, but fails because the machine is out of swap space. |
| One suggested work around is to ensure that the JVM never tries to resize the heap, by setting min heap size to max heap size:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-text" data-lang="text">java -Xmx1024m -Xms1024m</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Another workaround is to ensure you have configured sufficient swap space on your device to accommodate all programs you are running concurrently.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5 id="direct-byte-buffers">Direct ByteBuffers</h5> |
| <div class="paragraph"> |
| <p>Exhausting native memory is another issue related to JVM bugs. |
| The symptoms to look out for are the process size growing, but heap use remaining relatively constant. |
| Both the JIT compiler and nio ByteBuffers can consume native memory. |
| <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6210541">Oracle bug 6210541</a> discusses a still-unsolved problem whereby the JVM itself allocates a direct ByteBuffer in some circumstances while the system never garbage collects, effectively eating native memory. |
| Guy Korland’s blog discusses this problem <a href="http://www.jroller.com/gkorland/entry/java_s_memory_isn_t">here</a> and <a href="http://www.jroller.com/gkorland/entry/java_s_memory_managment_is">here.</a> |
| As the JIT compiler consumes native memory, the lack of available memory may manifest itself in the JIT as OutOfMemory exceptions such as <code>Exception in thread "CompilerThread0" java.lang.OutOfMemoryError: requested xxx bytes for ChunkPool::allocate. Out of swap |
| space?</code></p> |
| </div> |
| <div class="paragraph"> |
| <p>By default, Jetty allocates and manages its own pool of direct ByteBuffers for io if you configure the nio SelectChannelConnector. |
| It also allocates MappedByteBuffers to memory-map static files via the DefaultServlet settings. |
| However, you could be vulnerable to this JVM ByteBuffer allocation problem if you have disabled either of these options. |
| For example, if you’re on Windows, you may have disabled the use of memory-mapped buffers for the static file cache on the DefaultServlet to avoid the file-locking problem.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="troubleshooting-slow-deployment">Troubleshooting Slow Deployment</h3> |
| <div class="paragraph"> |
| <p>After upgrading to a version of Jetty that supports Servlet Spec 3.0 or above, enabling some new modules, or introducing some new jars to your webapp, you notice that your deployment time is increased. |
| This could be due to scanning for classes caused by a ServletContainerInitializer.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As documented in the section on <a href="#using-annotations">Using Annotations</a>, even if your webapp has set <code>metadata-complete=true</code> in web.xml, all jars within your webapp may still be scanned due to one or more ServletContainerInitializers that have a <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/annotation/HandlesTypes.html">@HandlesTypes</a> annotation listing the names of classes in which it is interested.</p> |
| </div> |
| <div class="paragraph"> |
| <p>There are 3 ways to speed up deployment time:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>limit which ServletContainerInitializers to include</p> |
| </li> |
| <li> |
| <p>limit which jars to scan</p> |
| </li> |
| <li> |
| <p>limit the scan to the first deployment only</p> |
| </li> |
| </ul> |
| </div> |
| <div class="sect3"> |
| <h4>Remedies</h4> |
| <div class="sect4"> |
| <h5>Limit Which ServletContainerInitializers to Execute</h5> |
| <div class="paragraph"> |
| <p>As documented in the section <a href="#excluding-scis">Excluding ServletContainerInitializers</a>, you can provide a context attribute that defines a pattern of ServletContainerInitializer (SCI) class names to ignore. |
| These SCIs will not be examined for <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/annotation/HandlesTypes.html">@HandlesTypes</a> and will not be executed. |
| This is useful if you have included a 3rd party jar that has a SCI on which your code does not rely.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Limit Which Jars to Scan</h5> |
| <div class="paragraph"> |
| <p>As documented in the section <a href="#jars-scanned-for-annotations">Jars Scanned for Annotations</a>, you can explicitly define which jars to include in the scanning process. |
| This is helpful if you have a lot of jars in your webapp, and you know that they do not contain any classes referenced by an @HandlesTypes annotation on a ServletContainerInitializer that will be executed.</p> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Limit Scanning to First Deployment Only (Quickstart)</h5> |
| <div class="paragraph"> |
| <p>The <a href="#quickstart-webapp">quickstart mechanism</a> will do a normal deployment - obeying any limits on SCIs and jars to scan as documented here - the first time the webapp is deployed only. |
| Subsequent deployments will re-use the information discovered during the first deployment. |
| This is useful if you cannot limit the scan significantly by using any of the mechanisms described here, but you don’t want to incur the cost of scanning on every redeployment. |
| The <a href="#quickstart-webapp">quickstart mechanism</a> and how to use it is described <a href="#quickstart-webapp">here</a>.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="security-reports">Jetty Security Reports</h3> |
| <div class="paragraph"> |
| <p>The following sections provide information about Jetty security issues.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If you would like to report a security issue please follow these <a href="#security-reporting">instructions</a>.</p> |
| </div> |
| <table class="tableblock frame-all grid-all" style="width: 99%;"> |
| <caption class="title">Table 11. Resolved Issues</caption> |
| <colgroup> |
| <col style="width: 11%;"> |
| <col style="width: 19%;"> |
| <col style="width: 14%;"> |
| <col style="width: 9%;"> |
| <col style="width: 14%;"> |
| <col style="width: 14%;"> |
| <col style="width: 19%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">yyyy/mm/dd</th> |
| <th class="tableblock halign-left valign-top">ID</th> |
| <th class="tableblock halign-left valign-top">Exploitable</th> |
| <th class="tableblock halign-left valign-top">Severity</th> |
| <th class="tableblock halign-left valign-top">Affects</th> |
| <th class="tableblock halign-left valign-top">Fixed Version</th> |
| <th class="tableblock halign-left valign-top">Comment</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2019/08/13</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2019-9518</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.20</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.4.21</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9518">Some HTTP/2 implementations are vulnerable to a flood of empty frames, potentially leading to a denial of service.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2019/08/13</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2019-9516</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.20</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.4.21</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9516">Some HTTP/2 implementations are vulnerable to a header leak, potentially leading to a denial of service.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2019/08/13</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2019-9515</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.20</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.4.21</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9515">Some HTTP/2 implementations are vulnerable to a settings flood, potentially leading to a denial of service when an attacker sent a stream of SETTINGS frames to the peer.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2019/08/13</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2019-9514</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.20</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.4.21</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9514">Some HTTP/2 implementations are vulnerable to a reset flood, potentially leading to a denial of service.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2019/08/13</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2019-9512</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.20</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.4.21</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9512">Some HTTP/2 implementations are vulnerable to ping floods which could lead to a denial of service.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2019/08/13</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2019-9511</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.20</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.4.21</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9511">Some HTTP/2 implementations are vulnerable to window size manipulation and stream prioritization manipulation which could lead to a denial of service.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2019/04/11</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2019-10247</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Med</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.16</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.2.28, 9.3.27, 9.4.17</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10247">If no webapp was mounted to the root namespace and a 404 was encountered, an HTML page would be generated displaying the fully qualified base resource location for each context.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2019/04/11</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2019-10246</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">High</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">High</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.16</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.2.28, 9.3.27, 9.4.17</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10246">Use of <code>DefaultServlet</code> or <code>ResourceHandler</code> with indexing was vulnerable to XSS behaviors to expose the directory listing on Windows operating systems.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2019/04/11</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2019-10241</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">High</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">High</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.15</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.2.27, 9.3.26, 9.4.16</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10241">Use of <code>DefaultServlet</code> or <code>ResourceHandler</code> with indexing was vulnerable to XSS behaviors to expose the directory listing.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2018/06/25</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2018-12538</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">High</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">High</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">>= 9.4.0, < = 9.4.8</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.4.9</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12538"><code>HttpSessions</code> present specifically in the FileSystem’s storage could be hijacked/accessed by an unauthorized user.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2018/06/25</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2018-12536</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">High</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">See <a href="https://cwe.mitre.org/data/definitions/209.html">CWE-202</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.10</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.2.25, 9.3.24, 9.4.11</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12536"><code>InvalidPathException</code> Message reveals webapp system path.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2018/06/25</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2017-7658</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">See <a href="https://cwe.mitre.org/data/definitions/444.html">CWE-444</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">See <a href="https://cwe.mitre.org/data/definitions/444.html">CWE-444</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.10</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.2.25, 9.3.24, 9.4.11</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-7658">Too Tolerant Parser, Double Content-Length + Transfer-Encoding + Whitespace.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2018/06/25</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2017-7657</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">See <a href="https://cwe.mitre.org/data/definitions/444.html">CWE-444</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">See <a href="https://cwe.mitre.org/data/definitions/444.html">CWE-444</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.10</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.2.25, 9.3.24, 9.4.11</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7657">HTTP/1.1 Request smuggling with carefully crafted body content (Does not apply to HTTP/1.0 or HTTP/2).</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2018/06/25</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2017-7656</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">See <a href="https://cwe.mitre.org/data/definitions/444.html">CWE-444</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">See <a href="https://cwe.mitre.org/data/definitions/444.html">CWE-444</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 9.4.10</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.2.25, 9.3.24, 9.4.11</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-7656">HTTP Request Smuggling when used with invalid request headers (for HTTP/0.9).</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2016/05/31</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CVE-2016-4800</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">>= 9.3.0, < = 9.3.8</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.3.9</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://www.ocert.org/advisories/ocert-2016-001.html">Alias vulnerability allowing access to protected resources within a webapp on Windows.</a></p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2015/02/24</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html">CVE-2015-2080</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">>=9.2.3 <9.2.9</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.2.9</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">JetLeak exposure of past buffers during HttpParser error</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2013/11/27</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://en.securitylab.ru/lab/PT-2013-65">PT-2013-65</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">>=9.0.0 <9.0.5</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">9.0.6 |
| <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=418014">418014</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Alias checking disabled by NTFS errors on Windows.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2013/07/24</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=413684">413684</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">>=7.6.9 <9.0.5</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">7.6.13,8.1.13,9.0.5 |
| <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=413684">413684</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Constraints bypassed if Unix symlink alias checker used on Windows.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2011/12/29</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://www.ocert.org/advisories/ocert-2011-003.html">CERT2011-003</a> <a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2011-4461">CVE-2011-4461</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">All versions</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">7.6.0.RCO |
| <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=367638">Jetty-367638</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Added ContextHandler.setMaxFormKeys (intkeys) to limit the number of parameters (default 1000).</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2009/11/05</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://www.kb.cert.org/vuls/id/120541">CERT2011-003</a> <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-3555">CERT2011-003</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">JVM<1.6u19</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">jetty-7.01.v20091125, jetty-6.1.22</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Work |
| around by turning off SSL renegotiation in Jetty. If using JVM > 1.6u19 |
| setAllowRenegotiate(true) may be called on connectors.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2009/06/18</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Jetty-1042</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 6.1.18, < = 7.0.0.M4</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6.1.19, 7.0.0.Rc0</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Cookie leak between |
| requests sharing a connection.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2009/04/30</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://www.kb.cert.org/vuls/id/402580">CERT402580</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">< = 6.1.16, < = 7.0.0.M2</p></td> |
| <td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph"> |
| <p>5.1.15, 6.1.18, 7.0.0.M2</p> |
| </div> |
| <div class="paragraph"> |
| <p>Jetty-1004</p> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">View arbitrary disk content in some specific configurations.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2007/12/22</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://www.kb.cert.org/vuls/id/553235">CERT553235</a> <a href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2007-6672">CVE-2007-6672</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6.1.rrc0-6.1.6</p></td> |
| <td class="tableblock halign-left valign-top"><div class="content"><div class="paragraph"> |
| <p>6.1.7</p> |
| </div> |
| <div class="paragraph"> |
| <p>CERT553235</p> |
| </div></div></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Static content visible in WEB-INF and past security constraints.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2007/11/05</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://www.kb.cert.org/vuls/id/438616">CERT438616</a> <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-5614">CVE-2007-5614</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><6.1.6</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6.1.6rc1 (patch in CVS for jetty5)</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Single quote in |
| cookie name.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2007/11/05</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://www.kb.cert.org/vuls/id/237888">CERT237888></a> <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-5613">CVE-2007-5613</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><6.1.6</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6.1.6rc0 (patch in CVS for jetty5)</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">XSS in demo dup |
| servlet.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2007/11/03</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://www.kb.cert.org/vuls/id/212984">CERT212984 |
| ></a> <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-5615">CVE-2007-5615</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><6.1.6</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6.1.6rc0 (patch in CVS for jetty5)</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">CRLF |
| Response splitting.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2006/11/22</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-6969">CVE-2006-6969</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">low</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><6.1.0, <6.0.2, <5.1.12, <4.2.27</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6.1.0pre3, 6.0.2, 5.1.12, |
| 4.2.27</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Session ID predictability.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2006/06/01</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-2759">CVE-2006-2759</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><6.0.*, <6.0.0Beta17</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">6.0.0Beta17</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">JSP source |
| visibility.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2006/01/05</p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><5.1.10</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">5.1.10</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Fixed //security |
| constraint bypass on Windows.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2005/11/18</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-2758">CVE-2006-2758</a></p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><5.1.6</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">5.1.6, 6.0.0Beta4</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">JSP source visibility.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2004/02/04</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">JSSE 1.0.3_01</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><4.2.7</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">4.2.7</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Upgraded JSSE |
| to obtain downstream security fix.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2002/09/22</p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><4.1.0</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">4.1.0</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Fixed CGI servlet remove |
| exploit.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2002/03/12</p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><3.1.7</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">4.0.RC2, 3.1.7</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Fixed // security |
| constraint bypass.</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">2001/10/21</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">medium</p></td> |
| <td class="tableblock halign-left valign-top"></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">high</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock"><3.1.3</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">3.1.3</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">Fixed trailing null security |
| constraint bypass.</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| <div class="sect2"> |
| <h3 id="watchservice">Java WatchService</h3> |
| <div class="paragraph"> |
| <p>The JVM <a href="https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html"><code>WatchService</code></a> is in place to monitor objects like a directory for changes, and then update it’s contents and notify the application of those changes. |
| This service is useful for features like <a href="#hot-deployment">Hot Deployment</a>. |
| When a change is detected, the <code>WatchService</code> will enter a "quiet time" where it is waiting for the change (or changes) to be made and completed before notifying the application of the change.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Example: |
| A new war file is copied into <code>/webapps</code>. |
| The <code>WatchService</code> can (depending on implementation) see that the file was created (which is registered as an event!, and that its growing in size (another event). |
| With the quiet time, each of the events are gated behind that timeout before the aggregated events are sent to the application.</p> |
| </div> |
| <div class="paragraph"> |
| <p>While some operating systems such as Windows have a native value for this quiet time, not all do, notably OSX. |
| At the core this is a limitation of the JVM’s FileSystem-specific implementation, but one that has been raised to the <a href="https://bugs.openjdk.java.net/browse/JDK-7133447">attention of the project.</a></p> |
| </div> |
| <div class="sect3"> |
| <h4>Remedy</h4> |
| <div class="paragraph"> |
| <p>To help offset the delay in systems like OSX, Jetty defaults the value for non-native implementations to a <a href="https://github.com/eclipse/jetty.project/tree/master/jetty-util/src/main/java/org/eclipse/jetty/util/PathWatcher.java#L1431">time of 5000ms.</a> |
| Using values lower than 5000ms is not recommended and has shown to frequently fail.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="advanced-debugging">Debugging</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3>Options</h3> |
| <div class="paragraph"> |
| <p>Given how flexible Jetty is in how it can be configured and deployed into development and production, there exists a wealth of different options for debugging your application in you favorite environment. |
| In this section we will gather up some of these different options available and explain how you can use them. |
| If you would like to contribute to this section simply fork the repository and contribute the information, or open a github issue with the information and we’ll bring it over.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="enable-remote-debugging">Enable remote debugging</h3> |
| <div class="sect3"> |
| <h4 id="remote-debugging">Remote Debugging</h4> |
| <div class="paragraph"> |
| <p>If you have a web application deployed into Jetty you can interact with it remotely from a debugging perspective easily. |
| The basics are that you must start up the remote JVM with additional parameters and then start up a remote debugging session in Eclipse for the webapp in question. |
| This is easily accomplished.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| This example assumes you are deploying your web application into the jetty-distribution. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="sect4"> |
| <h5>Starting Jetty</h5> |
| <div class="paragraph"> |
| <p>Assuming you have your webapp deployed into jetty, there are two different ways to approach this:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">Via command line</dt> |
| <dd> |
| <p>Add the required parameters on the commandline like so.</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-screen" data-lang="screen">$ java -Xdebug -agentlib:jdwp=transport=dt_socket,address=9999,server=y,suspend=n -jar start.jar</code></pre> |
| </div> |
| </div> |
| </dd> |
| <dt class="hdlist1">Via <code>start.ini</code></dt> |
| <dd> |
| <p>This approach is best used if you want to debug a particular jetty-distribution and not have to remember the commandline incantations.</p> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>Edit the <code>start.ini</code> and uncomment the --exec line, this is required if you are adding jvm options to the start.ini file as jetty-start must generate the classpath required and fork a new jvm.</p> |
| </li> |
| <li> |
| <p>Add the parameters mentioned above in the Command Line option so your start.ini looks like this:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">#=========================================================== |
| # Configure JVM arguments. |
| # If JVM args are include in an ini file then --exec is needed |
| # to start a new JVM from start.jar with the extra args. |
| # If you wish to avoid an extra JVM running, place JVM args |
| # on the normal command line and do not use --exec |
| #----------------------------------------------------------- |
| --exec |
| -Xdebug |
| -agentlib:jdwp=transport=dt_socket,address=9999,server=y,suspend=n |
| # -Xmx2000m |
| # -Xmn512m |
| # -XX:+UseConcMarkSweepGC |
| # -XX:ParallelCMSThreads=2 |
| # -XX:+CMSClassUnloadingEnabled |
| # -XX:+UseCMSCompactAtFullCollection |
| # -XX:CMSInitiatingOccupancyFraction=80 |
| # -verbose:gc |
| # -XX:+PrintGCDateStamps |
| # -XX:+PrintGCTimeStamps |
| # -XX:+PrintGCDetails |
| # -XX:+PrintTenuringDistribution |
| # -XX:+PrintCommandLineFlags |
| # -XX:+DisableExplicitGC</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Uncomment any other jvm environmental options you so desire for your debugging session.</p> |
| </div> |
| </li> |
| <li> |
| <p>Regardless of the option chosen, you should see the following lines at the top of your jetty-distribution startup.</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-plain" data-lang="plain">Listening for transport dt_socket at address: 9999</code></pre> |
| </div> |
| </div> |
| </li> |
| </ol> |
| </div> |
| </dd> |
| </dl> |
| </div> |
| </div> |
| <div class="sect4"> |
| <h5>Linking with your IDE</h5> |
| <div class="paragraph"> |
| <p>Refer to the documentation for your ide:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><a href="#debugging-with-intellij">Debugging With IntelliJ</a></p> |
| </li> |
| <li> |
| <p><a href="#debugging-with-eclipse">Debugging With Eclipse</a></p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="debugging-with-intellij">Debugging With IntelliJ</h3> |
| <div class="paragraph"> |
| <p>There are a number of options available to debug your application in IntelliJ.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If not done already prepare your application for remote debugging as described here: <a href="#enable-remote-debugging">Enable remote debugging</a></p> |
| </div> |
| <div class="sect3"> |
| <h4>Linking with IntelliJ</h4> |
| <div class="paragraph"> |
| <p>Next we need to link the IntelliJ project with the deployed webapp.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>Within IntelliJ, open the project containing the webapp deployed into jetty that you want to debug. Select<strong>Run → Edit Configurations</strong>. |
| Add a new configuration by clicking the "+" icon. Choose <strong>Remote</strong>. |
| Make sure the port you choose is the same as the one you added in <a href="#enable-remote-debugging">Enable remote debugging</a>.</p> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/intellij_new_remote_config.png" alt="image" width="800"></span></p> |
| </div> |
| </li> |
| <li> |
| <p>Next in your webapp you can set a breakpoint within a servlet which when it is tripped will halt the remote jvm’s processing thread to await for debugging commands from your IntelliJ instance. |
| To set a breakpoint, simply open the servlet or any other class you want to debug and click left to the line you want to set the breakpoint at (where the red dot is on the next screenshot). |
| The red dot and red background on the line mark the breakpoint.</p> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/intellij_set_breakpoint.png" alt="image" width="800"></span></p> |
| </div> |
| </li> |
| <li> |
| <p>Accessing that servlet within your browser, pointed at your remote debug configured jetty-distribution, should transition your IntelliJ instance to the standard debugger view.</p> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/intellij_debug_view.png" alt="image" width="800"></span></p> |
| </div> |
| </li> |
| </ol> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="intellij-within-intellij">Within IntelliJ</h4> |
| <div class="paragraph"> |
| <p>Since Jetty can be incredibly simple to embed, many people choose to create a small <code>main</code> method which they can launch directly within IntelliJ in order to more easily debug their entire application. |
| The best place to get started on this approach is to look through <a href="#embedding-jetty">Embedding Jetty</a> and the <a href="#embedded-examples">Embedded Examples</a> sections.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Once you have a main method defined in order to launch your application, open the source file and right-click the main method. |
| Select <strong>Debug</strong> or simply hit CTRL+SHIFT+D. |
| In your <strong>Console</strong> tab within IntelliJ you should see your application startup and once it has completed startup you should be able to configure breakpoints and hit the Jetty instance as normal via your web browser. |
| The same thing works for unit tests. |
| Instead of the main method run debug on the test method you want to debug.</p> |
| </div> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/intellij_select_debug.png" alt="image" width="800"></span></p> |
| </div> |
| <div class="paragraph"> |
| <p>Debugging in IntelliJ is extremely powerful. |
| For example it’s possible to have conditional breakpoints that only trigger a break if the configured conditions are met. |
| Have a look at the various tutorials in the internet or the <a href="http://www.jetbrains.com/idea/webhelp/getting-help.html">IntelliJ documentation</a> for further details.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock tip"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-tip" title="Tip"></i> |
| </td> |
| <td class="content"> |
| You can easily configure logging through a <code>jetty-logging.properties</code> file. |
| If this file is on your classpath then Jetty will use it for configuring logging, we use this approach extensively throughout Jetty development and it makes life ever so much easier. |
| You can see this in action in the <a href="#configuring-jetty-stderrlog">[configuring-jetty-stderrlog]</a> section. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="debugging-with-eclipse">Debugging With Eclipse</h3> |
| <div class="paragraph"> |
| <p>There are a number of options available to debug your application in Eclipse.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If not done already prepare your application for remote debugging as described here: <a href="#enable-remote-debugging">Enable remote debugging</a></p> |
| </div> |
| <div class="sect3"> |
| <h4>Linking with Eclipse</h4> |
| <div class="paragraph"> |
| <p>Next we need to link the Eclipse project with the deployed webapp.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>Within Eclipse, right-click on the project containing the webapp deployed into jetty and select <strong>Debug → Debug Configurations</strong> and create a new configuration of <strong>Remote Java Application</strong>. |
| Make sure the port you choose is the same as the one you added in <a href="#enable-remote-debugging">Enable remote debugging</a>.</p> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/debug-eclipse-1.png" alt="image" width="576"></span></p> |
| </div> |
| </li> |
| <li> |
| <p>Next in your webapp you can set a breakpoint within a servlet which when it is tripped will halt the remote jvm’s processing thread to await for debugging commands from your Eclipse instance.</p> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/debug-eclipse-2.png" alt="image" width="576"></span></p> |
| </div> |
| </li> |
| <li> |
| <p>Accessing that servlet within your browser, pointed at your remote debug configurated jetty-distribution, should transition your Eclipse instance to the standard Debug view.</p> |
| <div class="paragraph"> |
| <p><span class="image"><img src="images/debug-eclipse-3.png" alt="image" width="576"></span></p> |
| </div> |
| </li> |
| </ol> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="eclipse-within-eclipse">Within Eclipse</h4> |
| <div class="paragraph"> |
| <p>Since Jetty can be incredibly simple to embed, many people choose to create a small <code>main</code> method which they can launch directly within Eclipse in order to more easily debug their entire application. |
| The best place to get started on this approach is to look through <a href="#embedding-jetty">Embedding Jetty</a> and the <a href="#embedded-examples">Embedded Examples</a> sections.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Once you have a main method defined in order to launch your application, right-click on the source file and select<strong>Debug As → Java Application</strong>. |
| In your <strong>Console</strong> tab within Eclipse you should see your application startup and once it has completed startup you should be able to configure breakpoints and hit the Jetty instance as normal via your web browser.</p> |
| </div> |
| <div class="quoteblock"> |
| <blockquote> |
| <div class="admonitionblock tip"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-tip" title="Tip"></i> |
| </td> |
| <td class="content"> |
| You can easily configure logging through a <code>jetty-logging.properties</code> |
| file. If this file is on your classpath then Jetty will use it for |
| configuring logging, we use this approach extensively throughout Jetty |
| development and it makes life ever so much easier. You can see this in |
| action in the <a href="#configuring-jetty-stderrlog">[configuring-jetty-stderrlog]</a> section. |
| </td> |
| </tr> |
| </table> |
| </div> |
| </blockquote> |
| </div> |
| <div class="paragraph"> |
| <p>Unresolved directive in server/server.adoc - include::upgrading/chapter.adoc[]</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="io-arch">Appendix A: Jetty I/O Architecture</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Jetty libraries (both client and server) use Java NIO to handle I/O, so that |
| at its core Jetty I/O is completely non-blocking.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="io-arch-selector-manager">Jetty I/O: <code>SelectorManager</code></h3> |
| <div class="paragraph"> |
| <p>The core class of Jetty I/O is |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/SelectorManager.html"><code>SelectorManager</code></a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>SelectorManager</code> manages internally a configurable number of |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/ManagedSelector.html"><code>ManagedSelector</code></a>s. |
| Each <code>ManagedSelector</code> wraps an instance of <code>java.nio.channels.Selector</code> that |
| in turn manages a number of <code>java.nio.channels.SocketChannel</code> instances.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| TODO: add image |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p><code>SocketChannel</code> instances can be created by network clients when connecting |
| to a server and by a network server when accepting connections from network |
| clients. |
| In both cases the <code>SocketChannel</code> instance is passed to <code>SelectorManager</code> |
| (and to <code>ManagedSelector</code> and eventually to <code>java.nio.channels.Selector</code>) |
| to be registered for use within Jetty.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It is therefore possible for an application to create the <code>SocketChannel</code> |
| instances outside Jetty, even perform some initial network traffic also |
| outside Jetty (for example for authentication purposes), and then pass the |
| <code>SocketChannel</code> instance to <code>SelectorManager</code> for use within Jetty.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This example shows how to connect to a server:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Unresolved directive in io-arch.adoc - include::/home/jesse/src/jetty/jetty.project/jetty-documentation/src/main/java/embedded/SelectorManagerDocSnippets.java[tags=connect]</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This example shows how to accept a client connection:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="highlight"><code class="language-java" data-lang="java">Unresolved directive in io-arch.adoc - include::/home/jesse/src/jetty/jetty.project/jetty-documentation/src/main/java/embedded/SelectorManagerDocSnippets.java[tags=accept]</code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="io-arch-endpoint-connection">Jetty I/O: <code>EndPoint</code> and <code>Connection</code></h3> |
| <div class="paragraph"> |
| <p><code>SocketChannel</code>s that are passed to <code>SelectorManager</code> are wrapped into two |
| related components: |
| an <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/EndPoint.html"><code>EndPoint</code></a> and a |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/Connection.html"><code>Connection</code></a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>EndPoint</code> is the Jetty abstraction for a <code>SocketChannel</code>: you can read bytes |
| from an <code>EndPoint</code> via <code>EndPoint.fill(ByteBuffer)</code>, you can write bytes to an |
| <code>EndPoint</code> via <code>EndPoint.flush(ByteBuffer…​)</code> and |
| <code>EndPoint.write(Callback, ByteBuffer…​)</code>, you can close an <code>EndPoint</code> via |
| <code>EndPoint.close()</code>, etc.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>Connection</code> is the Jetty abstraction that is responsible to read bytes from |
| the <code>EndPoint</code> and to deserialize the read bytes into objects. |
| For example, a HTTP/1.1 server-side <code>Connection</code> implementation is responsible |
| to deserialize HTTP/1.1 request bytes into a HTTP request object. |
| Conversely, a HTTP/1.1 client-side <code>Connection</code> implementation is responsible |
| to deserialize HTTP/1.1 response bytes into a HTTP response object.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>Connection</code> is the abstraction that implements the reading side of a specific |
| protocol such as HTTP/1.1, or HTTP/2, or WebSocket: it is able to read incoming |
| communication in that protocol.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The writing side for a specific protocol <em>may</em> be implemented in the <code>Connection</code> |
| but may also be implemented in other components, although eventually the bytes |
| to be written will be written through the <code>EndPoint</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>While there is primarily just one implementation of <code>EndPoint</code>, |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/SocketChannelEndPoint.html"><code>SocketChannelEndPoint</code></a> |
| (used both on the client-side and on the server-side), there are many |
| implementations of <code>Connection</code>, typically two for each protocol (one for the |
| client-side and one for the server-side).</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>EndPoint</code> and <code>Connection</code> pairs can be chained, for example in case of |
| encrypted communication using the TLS protocol. |
| There is an <code>EndPoint</code> and <code>Connection</code> TLS pair where the <code>EndPoint</code> reads the |
| encrypted bytes from the network and the <code>Connection</code> decrypts them; next in the |
| chain there is an <code>EndPoint</code> and <code>Connection</code> pair where the <code>EndPoint</code> provides |
| decrypted bytes and the <code>Connection</code> deserializes them into specific protocol |
| objects (for example a HTTP/1.1 request object).</p> |
| </div> |
| <div class="paragraph"> |
| <p>Certain protocols, such as WebSocket, start the communication with the server |
| using one protocol (e.g. HTTP/1.1), but then change the communication to use |
| another protocol (e.g. WebSocket). |
| <code>EndPoint</code> supports changing the <code>Connection</code> object on-the-fly via |
| <code>EndPoint.upgrade(Connection)</code>. |
| This allows to use the HTTP/1.1 <code>Connection</code> during the initial communication |
| and later to replace it with a WebSocket <code>Connection</code>.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| TODO: add a section on <code>UpgradeFrom</code> and <code>UpgradeTo</code>? |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p><code>SelectorManager</code> is an abstract class because while it knows how to create |
| concrete <code>EndPoint</code> instances, it does not know how to create protocol |
| specific <code>Connection</code> instances.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Creating <code>Connection</code> instances is performed on the server-side by |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/ConnectionFactory.html"><code>ConnectionFactory</code></a>s. |
| and on the client-side by |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/io/ClientConnectionFactory.html"><code>ClientConnectionFactory</code></a>s</p> |
| </div> |
| <div class="paragraph"> |
| <p>On the server-side, the component that aggregates a <code>SelectorManager</code> with a |
| set of <code>ConnectionFactory</code>s is |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/server/ServerConnector.html"><code>ServerConnector</code></a>s.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| TODO: add a link to a server-side specific architecture section |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="paragraph"> |
| <p>On the client-side, the components that aggregates a <code>SelectorManager</code> with a |
| set of <code>ClientConnectionFactory</code>s are |
| <a href="http://www.eclipse.org/jetty/javadoc/10.0.0-SNAPSHOT/org/eclipse/jetty/client/HttpClientTransport.html"><code>HttpClientTransport</code></a> |
| subclasses.</p> |
| </div> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| TODO: add a link to a client-side specific architecture section |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="io-arch-endpoint">Jetty I/O: <code>EndPoint</code></h3> |
| <div class="paragraph"> |
| <p>The Jetty I/O library use Java NIO to handle I/O, so that I/O is non-blocking.</p> |
| </div> |
| <div class="paragraph"> |
| <p>At the Java NIO level, in order to be notified when a <code>SocketChannel</code> has data |
| to be read, the <code>SelectionKey.OP_READ</code> flag must be set.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the Jetty I/O library, you can call <code>AbstractEndPoint.fillInterested(Callback)</code> |
| to declare interest in the "read" (or "fill") event, and the <code>Callback</code> parameter |
| is the object that is notified when such event occurs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>At the Java NIO level, a <code>SocketChannel</code> is always writable, unless it becomes |
| TCP congested. In order to be notified when a <code>SocketChannel</code> uncongests and it |
| is therefore writable again, the <code>SelectionKey.OP_WRITE</code> flag must be set.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In the Jetty I/O library, you can call <code>EndPoint.write(Callback, ByteBuffer…​)</code> |
| to write the <code>ByteBuffer</code>s and the <code>Callback</code> parameter is the object that is |
| notified when the whole write is finished(i.e. <em>all</em> <code>ByteBuffer</code>s have been |
| fully written).</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="io-arch-connection">Jetty I/O: Implementing <code>Connection</code></h3> |
| <div class="paragraph"> |
| <p>Implementing a <code>Connection</code> is how you deserialize incoming bytes into objects |
| that can be used by more abstract layers, for example a HTTP request object or |
| a WebSocket frame object.</p> |
| </div> |
| </div> |
| </div> |
| </div></div><div id="footer"><div id="footer-text">Version 1.0<br>Last updated 2020-03-18 12:02:51 CDT</div></div></div></main><a href="#" class="scrollup">Back to the top</a></body></html> |