Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-11.0.x

This commit is contained in:
Joakim Erdfelt 2020-10-12 08:44:37 -05:00
commit c79246d507
No known key found for this signature in database
GPG Key ID: 2D0E1FB8FE4B68B4
6 changed files with 229 additions and 168 deletions

View File

@ -1,165 +0,0 @@
//
// ========================================================================
// 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
// ========================================================================
//
[[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 referred 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. `jakarta.servlet.Servlet`, `jakarta.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[jakarta.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[jakarta.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[jakarta.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.
____
[NOTE]
As of Jetty 10, Annotations will be discovered even for old versions of `web.xml` (2.5).
Users wishing not to use annotations from the webapp classpath must call `WebAppContext.setConfigurationDiscovered(false)` either programmatically or in xml.
____
===== 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.jakarta.server.JakartaWebSocketServletContainerInitializer, 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.

View File

@ -0,0 +1,224 @@
//
// ========================================================================
// 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
// ========================================================================
//
[[og-annotations]]
=== Annotations
Enable the `annotations` module if your webapp - or any of its third party libraries - uses any of the following:
* Annotations:
** @Resource
** @Resources
** @PostConstruct
** @PreDestroy
** @DeclaredRoles
** @RunAs
** @MultipartConfig
** @WebServlet
** @WebFilter
** @WebListener
** @WebInitParam
** @ServletSecurity, @HttpConstraint, @HttpMethodConstraint
** @HandlesTypes
* javax.servlet.ServletContainerInitializers
* JSP
[[og-annotations-scanning]]
==== Annotation Scanning
According to more recent versions of the Servlet Specification, the web.xml file can contain the attribute `metadata-complete`.
If this is set to `true`, then _no_ annotation scanning takes place, and your descriptor must contain the equivalent xml statements of any annotations.
If it is `metadata-complete=false`, or your web.xml predates the inclusion of this attribute, annotation scanning is required to take place.
To prevent annotation scanning you can use the `WebAppContext.setConfigurationDiscovered(false)` method.
Here's an example context xml file that calls this method:
[source,xml,subs=verbatim]
----
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext"> <1>
<Set name="configurationDiscovered">false</Set> <2>
</Configure>
----
<1> Configures a link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[`WebAppContext`], which is the Jetty component that represents a standard Servlet web application.
<2> Specifies that scanning should not take place.
However, despite `metadata-complete=true`, 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.
We will now look at ways to limit the jars that are scanned.
===== The container classpath
By default, Jetty will _not_ scan any classes that are on the container's classpath.
Sometimes, you may have third party libraries on the container's classpath that you need to be scanned.
In this case, use the `org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern` context attribute to define which container jars and class directories to scan.
The value of this attribute is a regular expression.
Here's an example from a context xml file that includes any jar whose name starts with "foo-" or "bar-", or a directory named "classes":
[source,xml,subs=verbatim]
----
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext"> <1>
<Call name="setAttribute"> <2>
<Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg> <3>
<Arg>.*/foo-[^/]*\.jar$|.*/bar-[^/]*\.jar$|.*/classes/.*</Arg> <4>
</Call>
</Configure>
----
<1> Configures a link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[`WebAppContext`], which is the Jetty component that represents a standard Servlet web application.
<2> Specifies a context attribute.
<3> Specifies the name of the context attribute.
<4> Specifies the value of the context attribute.
Note that the order of the patterns defines the ordering of the scanning of the jars or class directories.
===== The webapp classpath
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 that you know do not contain any annotations, you can significantly speed up deployment by omitting them from scanning.
However, be careful if your webapp uses a `ServletContainerInitializer` with an `@HandlesTypes` annotation that you don't exclude jars that contain classes matching the annotation.
Use the `org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern` context attribute to define a regular expression for jars and class directories to select for scanning.
Here's an example of a context xml file that sets a pattern that matches any jar on the webapp's classpath that starts with `spring-`:
[source,xml,subs=verbatim]
----
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext"> <1>
<Call name="setAttribute"> <2>
<Arg>org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</Arg> <3>
<Arg>.*/spring-[^/]*\.jar$</Arg> <4>
</Call>
</Configure>
----
<1> Configures a link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[`WebAppContext`], which is the Jetty component that represents a standard Servlet web application.
<2> Specifies a context attribute.
<3> Specifies the name of the context attribute.
<4> Specifies the value of the context attribute.
===== Multi-threading
By default Jetty performs annotation scanning in a multi-threaded manner in order to complete it in the minimum amount of time.
If you don't want multi-threaded scanning, you can configure Jetty to revert to single-threaded scanning.
There are several options to configure this:
1. Set the context attribute `org.eclipse.jetty.annotations.multiThreaded` to `false`
2. Set the `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 context attribute `org.eclipse.jetty.annotations.maxWait`
2. Set the `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.
[[og-annotations-scis]]
==== 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 extraClasspath that you have configured on the webapp.
The 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.
===== Exclusions
By default, as according to the Servlet Specification, all `ServletContainerInitializer` that are discovered are invoked.
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` 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 of setting the context attribute in a context xml file:
[source,xml,subs=verbatim]
----
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext"> <1>
<Call name="setAttribute"> <2>
<Arg>org.eclipse.jetty.containerInitializerExclusionPattern</Arg> <3>
<Arg>com.acme.*|com.corp.SlowContainerInitializer</Arg> <4>
</Call>
</Configure>
----
<1> Configures a link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[`WebAppContext`], which is the Jetty component that represents a standard Servlet web application.
<2> Specifies a context attribute.
<3> Specifies the name of the context attribute.
<4> Specifies the value of the context attribute.
In this example we exclude *all* `ServletContainerInitializer` instances in the `com.acme package`, and the specific class `com.corp.SlowContainerInitializer`.
It is possible to use exclusion and ordering together to control `ServletContainerInitializer` invocation - the exclusions will be applied before the ordering.
===== Ordering
If you need `ServletContainerInitializer` classes called in a specific order, you can use the context attribute `org.eclipse.jetty.containerInitializerOrder`.
Set it 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` classes not explicitly named in the list.
Here is an example context xml file that ensures the `com.example.PrioritySCI` will be called first, followed by the `com.acme.FooSCI`, then all other SCIs:
[source,xml,subs=verbatim]
----
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext"> <1>
<Call name="setAttribute"> <2>
<Arg>org.eclipse.jetty.containerInitializerOrder</Arg> <3>
<Arg>org.eclipse.jetty.websocket.javax.server.JavaxWebSocketServletContainerInitializer, com.acme.FooSCI, *</Arg> <4>
</Call>
</Configure>
----
<1> Configures a link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html[`WebAppContext`], which is the Jetty component that represents a standard Servlet web application.
<2> Specifies a context attribute.
<3> Specifies the name of the context attribute.
<4> Specifies the value of the context attribute.

View File

@ -34,3 +34,4 @@ include::modules/chapter.adoc[]
include::xml/chapter.adoc[]
include::sessions/chapter.adoc[]
include::quickstart/chapter.adoc[]
include::annotations/chapter.adoc[]

View File

@ -32,6 +32,7 @@ If you know Eclipse Jetty already, jump to a feature:
* xref:og-sessions[HTTP Session Caching and Clustering]
* xref:og-protocols-http2[HTTP/2 Support]
* xref:og-quickstart[Faster Web Application Deployment]
* xref:og-annotations[Annotations]
TODO

View File

@ -983,7 +983,7 @@ public class AsyncMiddleManServletTest
startClient();
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
.timeout(5, TimeUnit.SECONDS)
.timeout(15, TimeUnit.SECONDS)
.send();
assertEquals(HttpStatus.OK_200, response.getStatus());

View File

@ -750,7 +750,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
@ -1178,7 +1178,7 @@
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.3.2.Final</version>
<version>${jboss.logging.version}</version>
</dependency>
<dependency>
<groupId>com.github.jnr</groupId>