| // ======================================================================== |
| // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. |
| // ======================================================================== |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| |
| [[using-annotations]] |
| === Working with Annotations |
| |
| ==== Which Annotations Are Supported |
| |
| Jetty supports interpretation and application of the following annotations: |
| |
| * @Resource |
| * @Resources |
| * @PostConstruct |
| * @PreDestroy |
| * @DeclaredRoles |
| * @RunAs |
| * @MultipartConfig |
| * @WebServlet |
| * @WebFilter |
| * @WebListener |
| * @WebInitParam |
| * @ServletSecurity, @HttpConstraint, @HttpMethodConstraint |
| * @HandlesTypes (on ServletContainerInitializers) |
| |
| [[discoverable_introspectable_annotations]] |
| ==== Discovered vs Introspected Annotations |
| |
| Some types of annotation can be placed on any class, not necessarily just those with which the container interacts directly. |
| These type of annotations are refered to as "discovered" to indicate that the container must take proactive action to go out and find them. |
| The other type of annotation is call "introspected", meaning that they occur on classes with which the container interacts during their lifecycle (e.g. `javax.servlet.Servlet`, `javax.servlet.Filter`, ...etc.), and hence can be found by simple inspection of the class at that point. |
| |
| Some examples of discovered annotations are: |
| |
| * @WebServlet |
| * @WebFilter |
| * @WebListener |
| |
| Some examples of introspected annotations are: |
| |
| * @PostConstruct |
| * @PreDestroy |
| * @Resource |
| |
| [[jars-scanned-for-annotations]] |
| ==== Which Jar Files Are Scanned For Discovered Annotations |
| |
| The web.xml file can contain the attribute `metadata-complete`. |
| If this is set to `true`, then _no_ scanning of discoverable annotations takes place. |
| However, scanning of classes may _still_ occur because of http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html[javax.servlet.ServletContainerInitializer]s. |
| Classes implementing this interface are found by Jetty using the http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html[javax.util.ServiceLoader] mechanism, and if one is present _and_ it includes the @HandlesTypes annotation, then Jetty must scan the class hierarchy of the web application. |
| This may be very time-consuming if you have many jars in the container's path or in the webapp's WEB-INF/lib. |
| |
| If scanning is to take place - because either `metadata-complete` is `false` or missing, or because there are one or more http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html[javax.servlet.ServletContainerIntializer]s with @HandlesTypes - then Jetty must consider both the container's classpath and the webapp's classpath. |
| |
| By default, Jetty will _not_ scan any classes that are on the container's classpath. |
| If you need to cause jars and classes that are on the container's classpath to be scanned, then you can use the link:#container-include-jar-pattern[`org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern`] link:#context_attributes[context attribute] to specify a pattern for jars and directories from the container's classpath to scan. |
| |
| By default Jetty will scan __all__classes from `WEB-INF/classes` and all jars from `WEB-INF/lib` according to the order, if any, established by absolute or relative ordering clauses in web.xml. |
| If your webapp contains many jar files, you can significantly speed up deployment by omitting them from scanning. |
| To do this, use the link:#web-inf-include-jar-pattern[org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern] link:#context_attributes[context attribute] to define the patterns of jars that you specifically want to be scanned. |
| |
| Note that if you have configured an link:#using-extra-classpath-method[extraClasspath] for the webapp, then it participates in the scanning process too. |
| Any classes dirs are treated the same for scanning purposes as if they were in WEB-INF/classes and jars are treated as if they were in WEB-INF/lib. |
| |
| See also the next section on link:#servlet-container-initializers[ServletContainerInitializers] if you need to link:#servlet-container-initializers[control the order in which they are applied]. |
| |
| ==== Multi-threaded Annotation Scanning |
| |
| link:#jars-scanned-for-annotations[If annotation scanning is to be performed], by default Jetty will do it in a multi-threaded manner in order to complete it in the minimum amount of time. |
| |
| If for some reason you don't want multi-threaded scanning, you can configure Jetty to revert to single-threaded scanning. |
| There are several ways to configure this: |
| |
| 1. Set the link:#context_attributes[context attribute] `org.eclipse.jetty.annotations.multiThreaded` to `false` |
| 2. Set the link:#server_attributes[Server attribute] `org.eclipse.jetty.annotations.multiThreaded` to `false` |
| 3. Set the System property `org.eclipse.jetty.annotations.multiThreaded` to `false` |
| |
| Method 1 will only affect the current webapp. |
| Method 2 will affect all webapps deployed to the same Server instance. |
| Method 3 will affect all webapps deployed in the same JVM. |
| |
| By default, Jetty will wait a maximum of 60 seconds for all of the scanning threads to complete. |
| You can set this to a higher or lower number of seconds by doing one of the following: |
| |
| 1. Set the link:#context_attributes[context attribute] `org.eclipse.jetty.annotations.maxWait` |
| 2. Set the link:#server_attributes[Server attribute] `org.eclipse.jetty.annotations.maxWait` |
| 3. Set the System property `org.eclipse.jetty.annotations.maxWait` |
| |
| Method 1 will only affect the current webapp. |
| Method 2 will affect all webapps deployed to the same Server instance. |
| Method 3 will affect all webapps deployed in the same JVM. |
| |
| [[servlet-container-initializers]] |
| ==== ServletContainerInitializers |
| |
| The http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html[javax.servlet.ServletContainerInitializer] class can exist in: the container's classpath, the webapp's `WEB-INF/classes` directory, the webapp's `WEB-INF/lib` jars, or any external link:#using-extra-classpath-method[extraClasspath] that you have configured on the webapp. |
| |
| The http://jcp.org/aboutJava/communityprocess/final/jsr340/[Servlet Specification] does not define any order in which a `ServletContainerInitializer` must be called when the webapp starts. |
| By default Jetty will call them in the following order: |
| |
| 1. ServletContainerInitializers from the container's classpath |
| 2. ServletContainerInitializers from WEB-INF/classes |
| 3. ServletContainerInitializers from WEB-INF/lib jars __in the order established in web.xml__, or in the order that the SCI is returned by the http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html[javax.util.ServiceLoader] if there is _no_ ordering |
| |
| As is the case with annotation scanning, the link:#using-extra-classpath-method[extraClasspath] is fully considered for `ServletContainerInitializer` callbacks. `ServletContainerInitializer` derived from a classes directory on the `extraClasspath` and jars from an `extraClasspath` for the webapp are called in step 2 and 3, respectively. |
| |
| ===== Controlling the order of ServletContainerInitializer invocation |
| |
| If you need `ServletContainerInitializer` classes called in a specific order that is different from that outlined above, you can use the link:#context_attributes[context attribute] `org.eclipse.jetty.containerInitializerOrder`. |
| Set them to a list of comma separated class names of `ServletContainerInitializers` in the order that you want them applied. |
| You may optionally use the wildcard character "*" *once* in the list. |
| It will match all `ServletContainerInitializer` classed not explicitly named in the list. |
| |
| Here is an example, setting the context attribute in code (although you can also do the link:#intro-jetty-configuration-webapps[same in xml]): |
| |
| [source, java, subs="{sub-order}"] |
| ---- |
| WebAppContext context = new WebAppContext(); |
| context.setAttribute("org.eclipse.jetty.containerInitializerOrder", |
| "org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer, com.acme.Foo.MySCI, *"); |
| ---- |
| |
| In this example, we ensure that the `WebSocketServerContainerInitializer` is the very first `ServletContainerInitializer` that is called, followed by MySCI and then any other `ServletContainerInitializer` instances that were discovered but not yet called. |
| |
| [[excluding-scis]] |
| ===== Excluding ServletContainerInitializers |
| |
| By default, as according to the Servlet Specification, all `ServletContainerInitializer` that are discovered are invoked (see above for how to control the invocation order). |
| Sometimes, depending on your requirements, you may need to prevent some being called at all. |
| |
| In this case, you can define the `org.eclipse.jetty.containerInitializerExclusionPattern` link:#context_attributes[context attribute]. |
| This is a regular expression that defines http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html[patterns] of classnames that you want to exclude. |
| Here's an example, setting the context attribute in code, although you may do exactly the link:#intro-jetty-configuration-webapps[same in xml]: |
| |
| [source, java, subs="{sub-order}"] |
| ---- |
| WebAppContext context = new WebAppContext(); |
| context.setAttribute("org.eclipse.jetty.containerInitializerExclusionPattern", |
| "com.acme.*|com.corp.SlowContainerInitializer"); |
| ---- |
| |
| In this example we exclude *all* `ServletContainerInitializer` instances in the com.acme package, and the `SlowContainerInitializer`. |
| |
| It is possible to use exclusion and ordering together to control `ServletContainerInitializer` invocation - the exclusions will be applied before the ordering. |