private support for your internal/customer projects ... custom extensions and distributions ... versioned snapshots for indefinite support ... scalability guidance for your apps and Ajax/Comet projects ... development services from 1 day to full product delivery
This page contains content that we have migrated from Jetty 7 or Jetty 8 documentation into the correct format, but we have not yet audited it for technical accuracy in with Jetty 9. Be aware that examples or information contained on this page may be incorrect. Please check back soon as we continue improving the documentation, or submit corrections yourself to this page through Github. Thank you.
The Jetty OSGi infrastructure provides a Jetty container inside an OSGi container. Traditional JavaEE webapps can be deployed, in addition to Jetty ContextHandlers, along with OSGi web bundles. In addition, the infrastructure also supports the OSGi HttpService interface.
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 download a distribution of jetty. Here's the minimal set:
Jar | Bundle Symbolic Name |
---|---|
jetty-util | org.eclipse.jetty.util |
jetty-http | org.eclipse.jetty.http |
jetty-io | org.eclipse.jetty.io |
jetty-security | org.eclipse.jetty.security |
jetty-server | org.eclipse.jetty.server |
jetty-servlet | org.eclipse.jetty.servlet |
jetty-webapp | org.eclipse.jetty.webapp |
jetty-deploy | org.eclipse.jetty.deploy |
jetty-xml | org.eclipse.jetty.xml |
Now that you have the basic set of Jetty jars installed, you can install the jetty-osgi-boot.jar bundle, downloadable from the maven central repo here.
This bundle will instantiate and make available the Jetty OSGi container.
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 name=value pairs.
The available System properties are:
If not specified, this defaults to the usual jetty port of 8080.
Either this property or the jetty.home.bundle must
be specified. This property should point to a file system location
that has an etc/
directory containing xml files to
configure the Jetty container on startup. For example:
jetty.home=/opt/custom/jetty
Where /opt/custom/jetty
contains:
etc/jetty.xml etc/jetty-selector.xml etc/jetty-deployer.xml etc/jetty-special.xml
Either this property or the jetty.home property must be specified. This
property should specify the symbolic name of a bundle which
contains a directory called jettyhome/
. The
jettyhome/
directory should have a subdirectory called
etc/
that contains the xml files to be applied to
Jetty on startup. The jetty-osgi-boot.jar contains a
jettyhome/
directory with a default set of xml
configuration files. Here's how you would specify it:
jetty.home.bundle=org.eclipse.jetty.osgi.boot
Here's a partial listing of that jar that shows you the names of the xml files contained within it:
META-INF/MANIFEST.MF jettyhome/etc/jetty.xml jettyhome/etc/jetty-deployer.xml jettyhome/etc/webdefault.xml jettyhome/etc/jetty-selector.xml
This specifies the paths of the xml files - relative to jetty.home or jetty.home.bundle/jettyhome - that are to be used. If not specified, they default to:
etc/jetty.xml,etc/jetty-selector.xml,etc/jetty-deployer.xml
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:
org.osgi.framework.BundleContext bc; org.osgi.framework.ServiceReference ref = bc.getServiceReference("org.eclipse.jetty.server.Server");
The Server service has a couple of properties associated with it that you can retrieve using the org.osgi.framework.ServiceReference.getProperty(String) method:
The Jetty Server instance created by the jetty-osgi-boot.jar will be called "defaultJettyServer"
The list of xml files resolved from either jetty.home or jetty.home.bundle/jettyhome
The Jetty OSGi container listens for the installation of bundles, and will automatically attempt to deploy any that appear to be webapps.
Any of the following criteria are sufficient for Jetty to deploy the bundle as a webapp:
If the bundle contains a web descriptor, then it is automatically deployed. This is an easy way to deploy classic JavaEE webapps.
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 web/
:
MANIFEST
:
Bundle-Name: Web Jetty-WarFolderPath: web Import-Package: javax.servlet;version="2.6.0", javax.servlet.resources;version="2.6.0" Bundle-SymbolicName: com.acme.sample.web
Bundle contents:
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
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 eample based on the previous one where we use the Web-ContextPath header to set its deployment context path to be "/sample" :
MANIFEST
:
Bundle-Name: Web Jetty-WarFolderPath: web Web-ContextPath: /sample Import-Package: javax.servlet;version="2.6.0", javax.servlet.resources;version="2.6.0" Bundle-SymbolicName: com.acme.sample.web
As we have seen in the previous section, if the bundle
MANIFEST
contains the RFC-66 header Web-ContextPath, Jetty will use that as the
context path. If the MANIFEST does not contain that header, then Jetty
will concoct a context path based on the last element of the bundle's
location (by calling Bundle.getLocation()) after stripping off any file
extensions.
For example, suppose we have a bundle whose location is:
file://some/where/over/the/rainbow/oz.war
The corresponding synthesized context path would be:
/oz
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 ContextHandlers.
The following is the criteria used to decide if a bundle can be deployed as a ContextHandler:
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 jetty.home directory.
A context file that is inside the bundle:
Jetty-ContextFilePath: ./a/b/c/d/foo.xml
A context file that is on the file system:
Jetty-ContextFilePath: /opt/app/contexts/foo.xml
A context file that is relative to jetty.home:
Jetty-ContextFilePath: contexts/foo.xml
A number of different context files:
Jetty-ContextFilePath: ./a/b/c/d/foo.xml,/opt/app/contexts/foo.xml,contexts/foo.xml
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 Web-ContextPath header in the
MANIFEST
.
Before the Jetty OSGi container applies a context xml file found in a Jetty-ContextFilePath MANIFEST header, it sets a few useful properties that can be referred to within the xml file:
This is a reference to the Jetty org.eclipse.jetty.server.Server instance to which the ContextHandler being configured in the context xml file will be deployed.
This is a reference to the org.eclipse.jetty.util.resource.Resource that represents the location of the Bundle (obtained by calling Bundle.getLocation()). 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.
Here's an example of a context xml file that makes use of these properties:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.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 id="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 id="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>
In addition to listening for bundles whose format or
MANIFEST
entries define a webapp or ContextHandler for to be
deployed, the Jetty OSGi container also listens for the registration of
OSGi services that are instances of
org.eclipse.jetty.webapp.WebAppContext. So you may programmatically create
a WebAppContext, register it as a service, and have Jetty pick it up and
deploy it.
Here's an example of doing that with a simple bundle that serves static content, and an org.osgi.framework.BundleActivator that instantiates the WebAppContext:
The bundle contents:
META-INF/MANIFEST.MF index.html com/acme/osgi/Activator.class
The MANIFEST.MF
:
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
The Activator code:
public void start(BundleContext context) throws Exception { WebAppContext webapp = new WebAppContext(); Dictionary props = new Hashtable(); props.put("Jetty-WarFolderPath","."); props.put("contextPath","/acme"); context.registerService(ContextHandler.class.getName(),webapp,props); }
The above setup is sufficient for Jetty to recognize and deploy the WebAppContext at /acme.
As the example shows, you can use OSGi Service properties in order to communicate extra configuration information to Jetty:
The location within the bundle of the root of the static resources for the webapp
The context path at which to deploy the webapp.
The location within the bundle of a webdefault.xml file to apply to the webapp. Defaults to that of the Jetty OSGi container.
The location within the bundle of the web.xml file. Defaults to WEB-INF/web.xml
A classpath of additional items to add to the webapp's classloader.
The path to the base folder that overrides the computed bundle installation - mostly useful for those OSGi frameworks that unpack bundles by default.
A comma separated list of bundle symbolic names of bundles containing TLDs that this webapp depends upon.
Similarly to WebAppContexts, the Jetty OSGi container can detect the registration of an OSGi Service that represents a ContextHandler and ensure that it is deployed. The ContextHandler 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 ContextHandler can be partially configured, with the Jetty OSGi container completing the configuration via a context xml file and properties associated with the Service.
Here's an example of doing that with a simple bundle that serves static content with an org.osgi.framework.BundleActivator that instantiates a ContextHandler 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:
The bundle contents:
META-INF/MANIFEST.MF static/index.html acme.xml com/acme/osgi/Activator.class com/acme/osgi/Activator$1.class
The MANIFEST
:
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
The Activator code:
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); }
The contents of the acme.xml
context file:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.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 id="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 id="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>
Before the Jetty OSGi container applies a context xml file found in a Jetty-ContextFilePath property, it sets a few useful properties that can be referred to within the xml file:
This is a reference to the Jetty org.eclipse.jetty.server.Server instance to which the ContextHandler being configured in the context xml file will be deployed.
This is a reference to the org.eclipse.jetty.util.resource.Resource that represents the location of the Bundle publishing the ContextHandler as a Service(obtained by calling Bundle.getLocation()). 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.
In the example above, you can see both of these properties being used in the context xml file.
The Jetty OSGi container implements several aspects of the Enterprise Specification v4.2 for the WebAppContexts and ContextHandlers that it deploys from either bundles or OSGi services as outlined in foregoing sections.
For each WebAppContext or ContextHandler, the following context attribute is set, as required by section 128.6.1 Bundle Context pg 427:
The value of this attribute is the BundleContext representing the Bundle associated with the WebAppContext or ContextHandler.
As required by the specification section 128.3.4 Publishing the Servlet Context pg 421, each WebAppContext and ContextHandler 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:
The symbolic name of the Bundle associated with the WebAppContext or ContextHandler
The Bundle-Version header from the Bundle associated with the WebAppContext or ContextHandler
The context path of the WebAppContext or ContextHandler
As required by the specification section 128.5 Events pg 426, the following OSGi Event Admin events will be posted:
The Jetty OSGi container is about to deploy a WebAppContext or ContextHandler
The Jetty OSGi container has finished deploying a WebAppContext or ContextHandler and it is in service
The Jetty OSGi container is about to undeploy a WebAppContext or ContextHandler
The Jetty OSGi container has finished undeploying a WebAppContext or ContextHandler and it is no longer in service
The Jetty OSGi container failed to deploy a WebAppContext or ContextHandler
In order to use JSPs with your webapps and bundles you will need to install the JSP related jars into your OSGi container. You can use the jars from the jetty distribution in the $JETTY_HOME/lib/jsp directory, or you can download them from maven central. Here is the list of recommended jars (NOTE the version numbers may change in future):
Table 24.1. Jars Required for JSP
Jar | Bundle Symbolic Name |
---|---|
com.sun.el-2.2.0.v201303151357.jar | com.sun.el |
javax.el-2.2.0.v201303151357.jar | javax.el |
javax.servlet.jsp-2.2.0.v201112011158.jar | javax.servlet.jsp |
javax.servlet.jsp.jstl-1.2.0.v201105211821.jar | javax.servlet.jsp.jstl |
org.apache.jasper.glassfish-2.2.2.v201112011158.jar | org.apache.jasper.glassfish |
org.apache.taglibs.standard.glassfish-1.2.0.v201112081803.jar | org.apache.taglibs.standard.glassfish |
org.eclipse.jdt.core-3.8.2.v20130121.jar | org.eclipse.jdt.core.compiler.batch |
To be able to use JSPs you will need to also install the jetty-osgi-boot-jsp.jar into your OSGi container. This jar can be obtained from maven central here.
This bundle acts as a fragment extension to the jetty-osgi-boot.jar and adds in support for using JSP. If you do not use taglibs, or you only use the JSTL taglibs then you do not need to do any further configuration.
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.
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 MANIFEST 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 MANIFEST 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.
Firstly, lets look at an example of a web bundle's modified MANIFEST file so you get an idea of what is required. This example is a web bundle that uses the Spring servlet framework:
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)"
The Require-TldBundle header tells the Jetty OSGi container that this bundle contains TLDs that need to be passed over to the JSP container for processing. The Import-Bundle header ensures that the implementation classes for these TLDs will be available to the webapp on the OSGi classpath.
The format of the Require-TldBundle header is a comma separated list of one or more symbolic names of bundles containing TLDs.
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 org.eclipse.jetty.osgi.tldbundles:
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:
org.eclipse.jetty.osgi.tldbundles=com.acme.special.tags,com.foo.web,org.bar.web.framework
You will still need to define the Import-Bundle header in the MANIFEST file for the web bundle to ensure that the TLD bundles are on the OSGi classpath.
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.
This pattern must be specified as a context attribute of the WebAppContext representing the web bundle. Unless you are deploying your own WebAppContext (see Deploying Services as Webapps), you won't have a reference to the WebAppContext to do this. In that case, it can be specified on the org.eclipse.jetty.deploy.DeploymentManager, where it will be applied to every webapp deployed by the Jetty OSGi container. The jetty-osgi-boot.jar contains the default jettyhome/etc/jetty-deploy.xml file where the DeploymentManager is defined. To set the pattern, you will need to provide your own etc files - see the section on customizing the jetty container for how to do this. Here's how the jetty-deploy.xml file would look if we defined a pattern that matched all bundle symbolic names ending in "tag" and "web":
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.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>
Again, you will still need to define suitable Import-Bundle headers in your web bundle MANIFEST to ensure that bundles matching the pattern are available on the OSGi class path.
See an error or something missing? Contribute to this documentation at Github!