Skip to content

Commit

Permalink
Issue #5162 CDI embedded integration improvements
Browse files Browse the repository at this point in the history
ventilated text
  • Loading branch information
gregw committed Aug 24, 2020
1 parent b0f16c6 commit e4d7712
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,49 +19,36 @@
[[framework-cdi]]
=== CDI

Contexts and Dependency Injection for Java EE (http://www.cdi-spec.org/[CDI])
is a standard implemented by frameworks such as
http://seamframework.org/Weld[Weld] and
https://openwebbeans.apache.org/[Apache OpenWebBeans]. This is a common way to
assemble and configure webapplications by a process often referred to as
'decoration'.

Jetty integration of CDI frameworks allows CDI to be used to inject the
Filters, Servlets and Listeners created within a Servlet Context. There are
two approaches to integration:

* CDI implementation can integrate with Jetty. This requires the CDI
implementation to have Jetty specific code. Since Jetty-9.4.20 a loosely
bound mechanism has been available for CDI implementations to extends
the Jetty `DecoratedObjectFactory` without hard API dependencies.
Prior to that, CDI implementations directly called jetty APIs that need
to be explicitly exposed to the webapp.

* Alternately, Jetty can integrate with CDI implementations by using standard
CDI SPIs.
Contexts and Dependency Injection for Java EE (http://www.cdi-spec.org/[CDI]) is a standard implemented by frameworks such as http://seamframework.org/Weld[Weld] and https://openwebbeans.apache.org/[Apache OpenWebBeans].
This is a common way to assemble and configure webapplications by a process often referred to as 'decoration'.

Jetty integration of CDI frameworks allows CDI to be used to inject the Filters, Servlets and Listeners created within a Servlet Context.
There are two approaches to integration:

* CDI implementation can integrate with Jetty.
This requires the CDI implementation to have Jetty specific code.
Since Jetty-9.4.20 a loosely bound mechanism has been available for CDI implementations to extends the Jetty `DecoratedObjectFactory` without hard API dependencies.
Prior to that, CDI implementations directly called jetty APIs that need to be explicitly exposed to the webapp.

* Alternately, Jetty can integrate with CDI implementations by using standard CDI SPIs.

==== Jetty CDI Modules

The Jetty distribution come with several CDI modules. These modules do not provide CDI,
but instead enable one of more integration mechanisms.
The Jetty distribution come with several CDI modules.
These modules do not provide CDI, but instead enable one of more integration mechanisms.

===== Jetty `cdi` Module
The `cdi` module supports either two modes of CDI integration which can be
selected either by the "org.eclipse.jetty.cdi" context init parameter or
the "org.eclipse.jetty.cdi" server attribute (which is initialised from
the "jetty.cdi.mode" start property). Supported modes are:
The `cdi` module supports either two modes of CDI integration which can be selected either by the "org.eclipse.jetty.cdi" context init parameter or the "org.eclipse.jetty.cdi" server attribute (which is initialised from the "jetty.cdi.mode" start property).
Supported modes are:

* `CdiSpiDecorator` Jetty will call the CDI SPI within the webapp to decorate
objects (default).
* `CdiSpiDecorator` Jetty will call the CDI SPI within the webapp to decorate objects (default).

* `CdiDecoratingLister` The webapp may register a decorator on the context attribute
"org.eclipse.jetty.cdi.decorator".
* `CdiDecoratingLister` The webapp may register a decorator on the context attribute "org.eclipse.jetty.cdi.decorator".
-------------------------
cd $JETTY_BASE
java -jar $JETTY_HOME/start.jar --add-to-start=cdi
-------------------------


===== Jetty `cdi-decorate` Module
This module depends on the `cdi` module and sets the default mode to `CdiDecoratingListener`.
This is the preferred mode for Weld integration.
Expand All @@ -79,8 +66,7 @@ java -jar $JETTY_HOME/start.jar --add-to-start=cdi-spi
-------------------------

===== Jetty `cdi2` Module
This module supports the *deprecated* technique of exposing private Jetty decorate APIs to the CDI
implementation in the webapp.
This module supports the *deprecated* technique of exposing private Jetty decorate APIs to the CDI implementation in the webapp.

-------------------------
cd $JETTY_BASE
Expand Down Expand Up @@ -123,11 +109,11 @@ ____
==== Embedded Jetty with CDI
When starting embedded Jetty programmatically from the `main` method, to use CDI it may be
necessary:

* enable a Jetty CDI integration mode

* and/or enable a CDI frame integration.

However, depending on the exact configuration of the embedded server, either or both steps
may not be required as Servlet Container Initializers may be discovered.
However, depending on the exact configuration of the embedded server, either or both steps may not be required as Servlet Container Initializers may be discovered.

The details for embedding CDI will be explain in the Embedded Jetty with Weld section, but
can be adapted to other CDI frameworks.
The details for embedding CDI will be explain in the Embedded Jetty with Weld section, but can be adapted to other CDI frameworks.
Original file line number Diff line number Diff line change
Expand Up @@ -26,37 +26,33 @@ It is easily configured with Jetty 9.
==== Weld Setup

The easiest way to configure weld is within the Jetty distribution itself.
This can be accomplished either by enabling one of the
startup link:#startup-modules[modules] described in link:#framework-cdi[CDI Framework]:
This can be accomplished either by enabling one of the startup link:#startup-modules[modules] described in link:#framework-cdi[CDI Framework]:

* the `cdi-decorate` module is the preferred Weld integration. The activation
of this module by Weld can be confirmed by the following Weld log:
* the `cdi-decorate` module is the preferred Weld integration.
The activation of this module by Weld can be confirmed by the following Weld log:
[source, screen, subs="{sub-order}"]
....
INFO: WELD-ENV-001212: Jetty CdiDecoratingListener support detected, CDI injection will be available in Listeners, Servlets and Filters.
....
* the `cdi-spi` module works with Weld, but may restrict some non standard features.The activation
of this module by Weld can be confirmed by the following Weld log:
* the `cdi-spi` module works with Weld, but may restrict some non standard features.
The activation of this module by Weld can be confirmed by the following Weld log:
[source, screen, subs="{sub-order}"]
....
INFO: WELD-ENV-001213: Jetty CDI SPI support detected, CDI injection will be available in Listeners, Servlets and Filters.
....
* the deprecated `cdi2` module works with Weld prior to 3.1.2.Final. The activation
of this module by Weld can be confirmed by the following Weld log:
* the deprecated `cdi2` module works with Weld prior to 3.1.2.Final.
The activation of this module by Weld can be confirmed by the following Weld log:
[source, screen, subs="{sub-order}"]
....
INFO: WELD-ENV-001201: Jetty 7.2+ detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported.
....


To activate the preferred `cdi-decorate` module use:

-------------------------
cd $JETTY_BASE
java -jar $JETTY_HOME/start.jar --add-to-start=cdi-decorate
-------------------------


____
[TIP]
For use with the jetty-maven-plugin, the best idea is to make the org.jboss.weld.servlet:weld-servlet and jetty-cdi artifacts _plugin_ dependencies (__not__ a webapp dependency).
Expand All @@ -71,12 +67,10 @@ When starting embedded Jetty programmatically from the `main` method it is neces

* enable Weld by registering either its `Listener` or `ServletContainerInitializer`


===== Using a `ServletContextHandler`

Embedded usage often uses a `ServletContextHandler` which is the base class of `WebappContext` and
lacks the features of "web.xml" configuration and must be configured directly. The examples in this section
based on a server and context set up as follows:
Embedded usage often uses a `ServletContextHandler` which is the base class of `WebappContext` and lacks the features of "web.xml" configuration and must be configured directly.
The examples in this section based on a server and context set up as follows:

[source.JAVA, java]
----
Expand Down Expand Up @@ -123,13 +117,11 @@ The best way to initialize both Jetty Weld integration is to use their respectiv
context.addBean(new ServletContextHandler.Initializer(context,
new CdiServletContainerInitializer()));
----
This code uses the `ServletContextHandler.Initializer` utility class added in Jetty-9.4.30. Prior
to that the same effect can be achieved with a custom implementation of
`ServletContextHandler.ServletContainerInitializerCaller`.
This code uses the `ServletContextHandler.Initializer` utility class added in Jetty-9.4.30.
Prior to that the same effect can be achieved with a custom implementation of `ServletContextHandler.ServletContainerInitializerCaller`.

====== Initialize Weld with Listeners
Jetty Weld integration can also be initialized by directly adding the listeners
required:
Jetty Weld integration can also be initialized by directly adding the listeners required:
[source.JAVA, java]
----
import org.eclipse.jetty.cdi.CdiDecoratingListener;
Expand All @@ -140,28 +132,25 @@ required:
----

====== Other Weld initializations
When running embedded without a context classloader, it is not actually required
to initialize Jetty at all. If just Weld is initialized then it will disover the
Jetty APIs and use the deprecated integration:
When running embedded without a context classloader, it is not actually required to initialize Jetty at all.
If just Weld is initialized then it will disover the Jetty APIs and use the deprecated integration:
[source.JAVA, java]
----
import org.jboss.weld.environment.servlet.Listener;
// ...
context.addEventListener(new Listener());
----
However, this results in only a partially functional integration and the
following warning:
However, this results in only a partially functional integration and the following warning:
----
INFO: WELD-ENV-001201: Jetty 7.2+ detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported.
----

Jetty can also be initialized by adding the `org.eclipse.jetty.webapp.DecoratingListener` listener instead
of the `org.eclipse.jetty.cdi.CdiDecoratingListener`. However, this introduces a needless
dependency on `jetty-webapp` and is not the preferred method.
Jetty can also be initialized by adding the `org.eclipse.jetty.webapp.DecoratingListener` listener instead of the `org.eclipse.jetty.cdi.CdiDecoratingListener`.
However, this introduces a needless dependency on `jetty-webapp` and is not the preferred method.

====== Initialize Weld with `WebappContext`
Some embedded usage still makes use of the `WebappContext` class for the convention-over-configuration
benefits. The methods described for `ServletContextHandler` will work for `WebappContext`:
Some embedded usage still makes use of the `WebappContext` class for the convention-over-configuration benefits.
The methods described for `ServletContextHandler` will work for `WebappContext`:

[source.JAVA, java]
----
Expand Down

0 comments on commit e4d7712

Please sign in to comment.