Weld can be used to add support for CDI (Contexts and Dependency Injection) to Servlets, Listeners and Filters. It is easily configured with Jetty 9.
The easiest way to configure weld is within the Jetty distribution itself. This can be accomplished either by enabling one of the startup modules described in 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:
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:
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:
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
TipFor 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).
When starting embedded Jetty programmatically from the main
method it is necessary to:
-
enable a jetty CDI integration mode by registering a
Listener
orServletContainerInitializer
-
enable Weld by registering either its
Listener
orServletContainerInitializer
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:
public class Main {
public static void main(String[] args) throws Exception {
Server jetty = new Server(8080);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
server.setHandler(context);
context.addServlet(HelloWorldServlet.class, "/*");
/* CDI enabling goes here. See options below */
jetty.start();
jetty.join();
}
public static class HelloWorldServlet extends HttpServlet {
@Inject BeanManager manager;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/plain");
resp.getWriter().append("Hello from " + manager);
}
}
}
The best way to initialize both Jetty Weld integration is to use their respective ServletContainerInitializers
:
import org.eclipse.jetty.cdi.CdiServletContainerInitializer;
import org.eclipse.jetty.cdi.CdiDecoratingListener;
import org.jboss.weld.environment.servlet.EnhancedListener;
// ...
context.setInitParameter(
CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
CdiDecoratingListener.MODE);
context.addBean(new ServletContextHandler.Initializer(context,
new EnhancedListener()));
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
.
Jetty Weld integration can also be initialized by directly adding the listeners required:
import org.eclipse.jetty.cdi.CdiDecoratingListener;
import org.jboss.weld.environment.servlet.Listener;
// ...
context.addEventListener(new CdiDecoratingListener(context));
context.addEventListener(new Listener());
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:
import org.jboss.weld.environment.servlet.Listener;
// ...
context.addEventListener(new Listener());
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.
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
:
import org.eclipse.jetty.cdi.CdiServletContainerInitializer;
import org.eclipse.jetty.cdi.CdiDecoratingListener;
import org.jboss.weld.environment.servlet.EnhancedListener;
// ...
Server server = new Server(8080);
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
server.setHandler(webapp);
webapp.setInitParameter(
CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
CdiDecoratingListener.MODE);
webapp.addBean(new ServletContextHandler.Initializer(webapp,
new CdiServletContainerInitializer()));
webapp.addBean(new ServletContextHandler.Initializer(webapp,
new EnhancedListener()));
// ...
Alternately the webapp can be configured to discover the SCIs:
Server server = new Server(8080);
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
server.setHandler(webapp);
webapp.setInitParameter(
CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
CdiDecoratingListener.MODE);
// Need the AnnotationConfiguration to detect SCIs
Configuration.ClassList.setServerDefault(server).addBefore(
JettyWebXmlConfiguration.class.getName(),
AnnotationConfiguration.class.getName());
// Need to expose our SCI class.
webapp.getServerClasspathPattern().add("-" + CdiServletContainerInitializer.class.getName());
webapp.getSystemClasspathPattern().add(CdiServletContainerInitializer.class.getName());
// ...