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
Web applications require a certain amount of processing before they can be deployed: they may need to be unpacked, a special classloader created for their jars, web.xml and web-fragment.xml descriptors processed, and classes scanned for annotations amongst many other things. As web applications have become more complex, we have added ways to help you customize by either broadening or lessening the amount of processing that is done at deployment time. The two principal means for doing this are org.eclipse.jetty.webapp.Configuration classes and some context attributes.
As a webapp is being deployed, a series of org.eclipse.jetty.webapp.Configuration classes are applied to it, each one performing a specific function. The ordering of these Configurations is significant as subsequent Configurations tend to build on information extracted or setup in foregoing Configurations. These are the default list, in order, of Configurations that are applied to each org.eclipse.jetty.webapp.WebAppContext:
Table 5.1. Default Configuration classes
org.eclipse.jetty.webapp.WebInfConfiguration | Extracts war, orders jars and defines classpath |
org.eclipse.jetty.webapp.WebXmlConfiguration | Processes a WEB-INF/web.xml file |
org.eclipse.jetty.webapp.MetaInfConfiguration | Looks in container and webapp jars for META-INF/resources and META-INF/web-fragment.xml |
org.eclipse.jetty.webapp.FragmentConfiguration | Processes all discovered META-INF/web-fragment.xml files |
org.eclipse.jetty.webapp.JettyWebXmlConfiguration | Processes a WEB-INF/jetty-web.xml file |
A Configuration class is called 5 times in different phases of the WebAppContext's lifecycle:
As the WebAppContext is starting up this phase is executed. The Configuration should discover any of the resources it will need during the subsequent phases.
This phase is where the work of the class is done, usually using the resources discovered during the preConfigure phase.
This phase allows the Configuration to clear down any resources that may have been created during the previous 2 phases that are not needed for the lifetime of the WebAppContext.
This phase occurs whenever a WebAppContext is being stopped and allows the Configuration to undo any resources/metadata that it created. A WebAppContext should be able to be cleanly start/stopped multiple times without resources being held.
This phase is called when a WebAppContext is actually removed from service. For example, the war file associated with it is deleted from the $JETTY_HOME/webapps directory.
Each phase is called on each Configuration class in the order in which the Configuration class is listed. So for example, using our default Configuration classes as an example, preConfigure() will be called on WebInfConfiguration, WebXmlConfiguration, MetaInfConfiguration, FragmentConfiguration and then JettyWebXmlConfiguration. The cycle begins again for the configure() phase and again for the postConfigure() phases. The cycle is repeated in reverse order for the deconfigure() and eventually the destroy() phases.
As we have seen, there is a default set of Configurations that support basic deployment of a webapp. You will notice that we have not mentioned JavaEE features such as JNDI, nor advanced servlet spec features such as annotations. That is because Jetty's philosophy is to allow the user to tailor the container exactly to his needs. If you do not need these kind of features, then you do not pay the price of them - an important consideration because features such as annotations require extensive and time-consuming scanning of WEB-INF/lib jars. As modern webapps may have scores of these jars, it can be a source of significant deployment delay. We will see in the section Other Configuration another helpful webapp facility that Jetty provides for cutting down the time spent analysing jars.
Jetty makes use of the flexibility of Configurations to make JNDI and annotation support pluggable.
Firstly, lets look at how Configurations help enable JNDI.
JNDI lookups within web applications require the container to hookup resources defined in the container's environment to that of the web application. To acheive that, we use 2 extra Configurations:
Table 5.2. JNDI Configuration classes
org.eclipse.jetty.plus.webapp.EnvConfiguration | Creates java:comp/env for the webapp, applies a WEB-INF/jetty-env.xml file |
org.eclipse.jetty.plus.webapp.PlusConfiguration | Processes JNDI related aspects of WEB-INF/web.xml and hooks up naming entries |
These configurations must be added in exactly the order shown above and should be inserted immediately before the org.eclipse.jetty.webapp.JettyWebXmlConfiguration class in the list of configurations. To fully support JNDI, you need to do a couple of other things, full details of which you can find here.
We need just one extra Configuration class to help provide servlet annotation scanning:
Table 5.3. Annotation Configuration classes
org.eclipse.jetty.annotations.AnnotationConfiguration | Scan container and web app jars looking for @WebServlet, @WebFilter, @WebListener etc |
The above configuration class must be inserted immediately before the org.eclipse.jetty.webapp.JettyWebXmlConfiguration class in the list of configurations. To fully support annotations, you need to do a couple of other things, details of which can be found here.
You have a number of options for how to make Jetty use a different list of Configurations.
If you have only one webapp that you wish to affect, this may be the easiest option. You will, however, either need to have a context xml file that represents your web app, or you need to call the equivalent in code. Let's see an example of how we would add in the Configurations for both JNDI and annotations:
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd"> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/my-cool-webapp</Set> <Set name="configurationClasses"> <Array type="java.lang.String"> <Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item> <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item> <Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item> <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item> <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item> <Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item> <Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item> <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item> </Array> </Set> </Configure>
Of course, you can also use this method to reduce the Configurations applied to a specific WebAppContext.
If you use the deployer, you can set up the list of Configuration classes on the WebAppProvider. They will then be applied to each WebAppContext deployed by the deployer:
<?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 id="webappprovider" name="addAppProvider"> <Arg> <New class="org.eclipse.jetty.deploy.providers.WebAppProvider"> <Set name="monitoredDirName"><Property name="jetty.home" default="." />/webapps</Set> <Set name="configurationClasses"> <Array type="java.lang.String"> <Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item> <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item> <Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item> <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item> <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item> <Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item> <Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item> <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item> </Array> </Set> </New> </Arg> </Call> </New> </Arg> </Call> </Configure>
Instead of having to enumerate the list in its entirety, you can simply nominate classes that you want to add, and indicate whereabouts in the list you want them inserted. Let's look at an example of using this method to add in Configuration support for JNDI - as usual you can either do this in an xml file, or via equivalent code. This example uses an xml file, in fact it is the $JETTY_HOME/etc/jetty-plus.xml file from the Jetty distribution:
<?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"> <!-- =========================================================== --> <!-- Add plus Configuring classes to all webapps for this Server --> <!-- =========================================================== --> <Call class="org.eclipse.jetty.webapp.Configuration$ClassList" name="setServerDefault"> <Arg><Ref refid="Server" /></Arg> <Call name="addAfter"> <Arg name="afterClass">org.eclipse.jetty.webapp.FragmentConfiguration</Arg> <Arg> <Array type="String"> <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item> <Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item> </Array> </Arg> </Call> </Call> </Configure>
The org.eclipse.jetty.webapp.Configuration.ClassList class provides these methods for insertion:
inserts the supplied list of Configuration class names after the given Configuration class name
inserts the supplied list of Configuration class names before the given Configuration class name
This is a context attribute that can be set on an org.eclipse.jetty.webapp.WebAppContext to control which parts of the container's classpath should be processed for things like annotations, META-INF/resources, META-INF/web-fragment.xml etc.
Normally, nothing from the container classpath will be included for processing. However, sometimes you will need to include some. For example, you may have some libraries that are shared amongst your webapps and thus you have put them into a $JETTY_HOME/lib directory. The libraries contain annotations and therefore must be scanned.
The value of this attribute is a regexp that defines which jars and class directories from the container's classpath should be examined.
Here's an example from a context xml file (although as always, you could have accomplished the same in code), which would match any jar whose name starts with "foo-" or "bar-", or a directory named "classes":
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd"> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Call name="setContextAttribute"> <Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg> <Arg>.*/foo-[^/]*\.jar$|.*/bar-[^/]*\.jar$|.*/classes/.*</Arg> </Call> </Configure>
Note that the order of the patterns defines the ordering of the scanning of the jars or class directories.
Similarly to the previous context attribute, this attribute controls which jars are processed for things like annotations and META-INF resources. However, this attribute controls which jars from the webapp's classpath (usually WEB-INF/lib) are processed. This can be particularly useful when you have dozens of jars in WEB-INF/lib, but you know that only a few need to be scanned.
Here's an example (in an xml file, but you can do the same in code) of a pattern that matches any jar that starts with "spring-":
<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd"> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <Call name="setContextAttribute"> <Arg>org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</Arg> <Arg>.*/spring-[^/]*\.jar$</Arg> </Call> </Configure>
Note that the order of the patterns defines the ordering of the scanning of the jars.
See an error or something missing? Contribute to this documentation at Github!