Issue #3804 CDI integration
Rename attributes and classes to have a more regular pattern. The DecoratingListener is now extened by the CdiDecoratingListener which is used by the cdi-decorate module Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
parent
dc939d753a
commit
70fcd3d145
|
@ -1,7 +1,5 @@
|
|||
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<!-- =============================================================== --><!-- Mixin the Weld / CDI classes to the class loader --><!-- =============================================================== -->
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Ref refid="DeploymentManager">
|
||||
<Call name="addLifeCycleBinding">
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[description]
|
||||
CDI SPI integration for CDI inside the webapp.
|
||||
This module does not provide CDI, but configures jetty to look for the CDI SPI within
|
||||
a webapp. If the CDI SPI is found, then a CdiDecorator will be registered to
|
||||
decorate Listeners, Filters and Servlets using the standard CDI SPI.
|
||||
The module indicates to the webapp that this mechanism is available by setting the
|
||||
"org.eclipse.jetty.cdi" context attribute to "CdiDecorator".
|
||||
This is the preferred integration for OWB.
|
||||
Configures Jetty to use the "CdiSpiDecorator" that calls the CDI SPI
|
||||
as the default CDI integration mode.
|
||||
|
||||
[tag]
|
||||
cdi
|
||||
|
||||
[depend]
|
||||
deploy
|
||||
[provides]
|
||||
cdi-mode
|
||||
|
||||
[lib]
|
||||
lib/jetty-cdi-${jetty.version}.jar
|
||||
lib/apache-jsp/org.mortbay.jasper.apache-el-*.jar
|
||||
[depend]
|
||||
cdi
|
||||
|
||||
[ini]
|
||||
jetty.webapp.addSystemClasses+=,org.eclipse.jetty.cdi.CdiServletContainerInitializer
|
||||
jetty.webapp.addServerClasses+=,-org.eclipse.jetty.cdi.CdiServletContainerInitializer
|
||||
jetty.cdi.mode=CdiSpiDecorator
|
||||
|
|
|
@ -1,10 +1,33 @@
|
|||
# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[description]
|
||||
Deprecated CDI module. Current depends on cdi-spi.
|
||||
Support for CDI inside the webapp.
|
||||
This module does not provide CDI, but configures jetty to support various
|
||||
integration modes with a CDI implementation on the webapp classpath.
|
||||
CDI integration modes can be selected per webapp with the "jetty.cdi.mode"
|
||||
init parameter or default to the mode set by the "jetty.cdi.mode" server attribute.
|
||||
Supported modes are:
|
||||
CdiDecorator - Jetty will call the CDI SPI within the webapp to decorate
|
||||
objects (default).
|
||||
DecoratingLister - The webapp may register a decorator on the context attribute
|
||||
"org.eclipse.jetty.cdi.decorator".
|
||||
|
||||
[tag]
|
||||
cdi
|
||||
|
||||
[provides]
|
||||
cdi
|
||||
|
||||
[depend]
|
||||
cdi-spi
|
||||
deploy
|
||||
|
||||
[xml]
|
||||
etc/cdi/jetty-cdi.xml
|
||||
|
||||
[lib]
|
||||
lib/jetty-cdi-${jetty.version}.jar
|
||||
lib/apache-jsp/org.mortbay.jasper.apache-el-*.jar
|
||||
|
||||
[ini]
|
||||
jetty.webapp.addSystemClasses+=,org.eclipse.jetty.cdi.CdiServletContainerInitializer
|
||||
jetty.webapp.addServerClasses+=,-org.eclipse.jetty.cdi.CdiServletContainerInitializer
|
|
@ -10,6 +10,9 @@ implementation in the webapp.
|
|||
[tag]
|
||||
cdi
|
||||
|
||||
[provides]
|
||||
cdi-mode
|
||||
|
||||
[depend]
|
||||
deploy
|
||||
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 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.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.cdi;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.Decorator;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* A Decorator invokes a CDI provider within
|
||||
* a webapplication to decorate objects created by the contexts {@link org.eclipse.jetty.util.DecoratedObjectFactory}
|
||||
* (typically Listeners, Filters and Servlets).
|
||||
* The CDI provide is invoked using {@link MethodHandle}s to avoid any CDI instance or dependencies within the server scope.
|
||||
* The code invoked is equivalent to:
|
||||
* <pre>
|
||||
* public <T> T decorate(T o)
|
||||
* {
|
||||
* BeanManager manager = CDI.current().getBeanManager();
|
||||
* manager.createInjectionTarget(manager.createAnnotatedType((Class<T>)o.getClass()))
|
||||
* .inject(o,manager.createCreationalContext(null));
|
||||
* return o;
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public class CdiDecorator implements Decorator
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(CdiServletContainerInitializer.class);
|
||||
|
||||
private final ServletContextHandler _context;
|
||||
private final Map<Object, Decorated> _decorated = new HashMap<>();
|
||||
|
||||
private final MethodHandle _current;
|
||||
private final MethodHandle _getBeanManager;
|
||||
private final MethodHandle _createAnnotatedType;
|
||||
private final MethodHandle _createInjectionTarget;
|
||||
private final MethodHandle _createCreationalContext;
|
||||
private final MethodHandle _inject;
|
||||
private final MethodHandle _dispose;
|
||||
private final MethodHandle _release;
|
||||
|
||||
public CdiDecorator(ServletContextHandler context) throws UnsupportedOperationException
|
||||
{
|
||||
_context = context;
|
||||
ClassLoader classLoader = _context.getClassLoader();
|
||||
|
||||
try
|
||||
{
|
||||
Class<?> cdiClass = classLoader.loadClass("javax.enterprise.inject.spi.CDI");
|
||||
Class<?> beanManagerClass = classLoader.loadClass("javax.enterprise.inject.spi.BeanManager");
|
||||
Class<?> annotatedTypeClass = classLoader.loadClass("javax.enterprise.inject.spi.AnnotatedType");
|
||||
Class<?> injectionTargetClass = classLoader.loadClass("javax.enterprise.inject.spi.InjectionTarget");
|
||||
Class<?> creationalContextClass = classLoader.loadClass("javax.enterprise.context.spi.CreationalContext");
|
||||
Class<?> contextualClass = classLoader.loadClass("javax.enterprise.context.spi.Contextual");
|
||||
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
_current = lookup.findStatic(cdiClass, "current", MethodType.methodType(cdiClass));
|
||||
_getBeanManager = lookup.findVirtual(cdiClass, "getBeanManager", MethodType.methodType(beanManagerClass));
|
||||
_createAnnotatedType = lookup.findVirtual(beanManagerClass, "createAnnotatedType", MethodType.methodType(annotatedTypeClass, Class.class));
|
||||
_createInjectionTarget = lookup.findVirtual(beanManagerClass, "createInjectionTarget", MethodType.methodType(injectionTargetClass, annotatedTypeClass));
|
||||
_createCreationalContext = lookup.findVirtual(beanManagerClass, "createCreationalContext", MethodType.methodType(creationalContextClass, contextualClass));
|
||||
_inject = lookup.findVirtual(injectionTargetClass, "inject", MethodType.methodType(Void.TYPE, Object.class, creationalContextClass));
|
||||
_dispose = lookup.findVirtual(injectionTargetClass, "dispose", MethodType.methodType(Void.TYPE, Object.class));
|
||||
_release = lookup.findVirtual(creationalContextClass, "release", MethodType.methodType(Void.TYPE));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new UnsupportedOperationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decorate an object.
|
||||
* <p>The signature of this method must match what is introspected for by the
|
||||
* Jetty DecoratingListener class. It is invoked dynamically.</p>
|
||||
*
|
||||
* @param o The object to be decorated
|
||||
* @param <T> The type of the object to be decorated
|
||||
* @return The decorated object
|
||||
*/
|
||||
public <T> T decorate(T o)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("decorate {} in {}", o, _context);
|
||||
|
||||
_decorated.put(o, new Decorated(o));
|
||||
}
|
||||
catch (Throwable th)
|
||||
{
|
||||
LOG.warn("Unable to decorate " + o, th);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a decorated object.
|
||||
* <p>The signature of this method must match what is introspected for by the
|
||||
* Jetty DecoratingListener class. It is invoked dynamically.</p>
|
||||
*
|
||||
* @param o The object to be destroyed
|
||||
*/
|
||||
public void destroy(Object o)
|
||||
{
|
||||
try
|
||||
{
|
||||
Decorated decorated = _decorated.remove(o);
|
||||
if (decorated != null)
|
||||
decorated.destroy(o);
|
||||
}
|
||||
catch (Throwable th)
|
||||
{
|
||||
LOG.warn("Unable to destroy " + o, th);
|
||||
}
|
||||
}
|
||||
|
||||
private class Decorated
|
||||
{
|
||||
private final Object _injectionTarget;
|
||||
private final Object _creationalContext;
|
||||
|
||||
Decorated(Object o) throws Throwable
|
||||
{
|
||||
// BeanManager manager = CDI.current().getBeanManager();
|
||||
Object manager = _getBeanManager.invoke(_current.invoke());
|
||||
// AnnotatedType annotatedType = manager.createAnnotatedType((Class<T>)o.getClass());
|
||||
Object annotatedType = _createAnnotatedType.invoke(manager, o.getClass());
|
||||
// CreationalContext creationalContext = manager.createCreationalContext(null);
|
||||
_creationalContext = _createCreationalContext.invoke(manager, null);
|
||||
// InjectionTarget injectionTarget = manager.createInjectionTarget();
|
||||
_injectionTarget = _createInjectionTarget.invoke(manager, annotatedType);
|
||||
// injectionTarget.inject(o, creationalContext);
|
||||
_inject.invoke(_injectionTarget, o, _creationalContext);
|
||||
}
|
||||
|
||||
public void destroy(Object o) throws Throwable
|
||||
{
|
||||
_dispose.invoke(_injectionTarget, o);
|
||||
_release.invoke(_creationalContext);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
/**
|
||||
* A {@link ServletContainerInitializer} that introspects for a CDI API
|
||||
* implementation within a web application. If the CDI API is found, then
|
||||
* a {@link CdiDecorator} is registered as a {@link org.eclipse.jetty.util.Decorator}
|
||||
* a {@link CdiSpiDecorator} is registered as a {@link org.eclipse.jetty.util.Decorator}
|
||||
* for the context.
|
||||
* @see AnnotationConfiguration.ServletContainerInitializerOrdering
|
||||
*/
|
||||
|
@ -47,9 +47,31 @@ public class CdiServletContainerInitializer implements ServletContainerInitializ
|
|||
{
|
||||
ServletContextHandler context = ServletContextHandler.getServletContextHandler(ctx);
|
||||
Objects.requireNonNull(context);
|
||||
context.getObjectFactory().addDecorator(new CdiDecorator(context));
|
||||
context.setAttribute(CDI_INTEGRATION_ATTRIBUTE, "CdiDecorator");
|
||||
LOG.info("CdiDecorator enabled in " + ctx);
|
||||
|
||||
String mode = ctx.getInitParameter(CDI_INTEGRATION_ATTRIBUTE);
|
||||
if (mode == null)
|
||||
{
|
||||
mode = (String)context.getServer().getAttribute(CDI_INTEGRATION_ATTRIBUTE);
|
||||
if (mode == null)
|
||||
mode = CdiSpiDecorator.MODE;
|
||||
}
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case CdiSpiDecorator.MODE:
|
||||
context.getObjectFactory().addDecorator(new CdiSpiDecorator(context));
|
||||
break;
|
||||
|
||||
case CdiDecoratingListener.MODE:
|
||||
context.addEventListener(new CdiDecoratingListener());
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException(mode);
|
||||
}
|
||||
|
||||
context.setAttribute(CDI_INTEGRATION_ATTRIBUTE, mode);
|
||||
LOG.info(mode + " enabled in " + ctx);
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
|
||||
|
||||
[description]
|
||||
Jetty setup to support Decoration of Listeners, Filters and Servlets within a deployed
|
||||
webapp (as used by some CDI integrations).
|
||||
Jetty setup to support Decoration of Listeners, Filters and Servlets within a deployed webapp.
|
||||
This module uses the DecoratingListener to register an object set as a context attribute
|
||||
as a dynamic decorator. This module sets the "org.eclipse.jetty.webapp.DecoratingListener"
|
||||
context attribute with the name of the context attribute that will be listened to.
|
||||
By default the attribute is "org.eclipse.jetty.webapp.decorator".
|
||||
This is the preferred integration for Weld >= 3.1.2
|
||||
|
||||
[tag]
|
||||
cdi
|
||||
|
||||
[depend]
|
||||
deploy
|
||||
|
|
|
@ -89,13 +89,13 @@ public class DecoratingListener implements ServletContextAttributeListener
|
|||
_context = context;
|
||||
Objects.requireNonNull(_context);
|
||||
_attributeName = attributeName == null ? DECORATOR_ATTRIBUTE : attributeName;
|
||||
checkAndSetAttribute();
|
||||
checkAndSetAttributeName();
|
||||
Object decorator = _context.getAttribute(_attributeName);
|
||||
if (decorator != null)
|
||||
_context.getObjectFactory().addDecorator(asDecorator(decorator));
|
||||
}
|
||||
|
||||
protected void checkAndSetAttribute()
|
||||
protected void checkAndSetAttributeName()
|
||||
{
|
||||
// If not set (by another DecoratingListener), flag the attribute that are
|
||||
// listening for. If more than one DecoratingListener is used then this
|
||||
|
|
|
@ -59,12 +59,14 @@ public class CDITests extends AbstractDistributionTest
|
|||
|
||||
List<Object[]> tests = new ArrayList<>();
|
||||
|
||||
tests.add(new Object[]{"weld", "cdi-spi", null}); // Requires Weld >= 3.1.2
|
||||
tests.add(new Object[]{"weld", "cdi-spi", null}); // Weld >= 3.1.2
|
||||
tests.add(new Object[]{"weld", "cdi2", null});
|
||||
tests.add(new Object[]{"weld", "decorate", null}); // Requires Weld >= 3.1.2
|
||||
tests.add(new Object[]{"weld", "decorate", null}); // Weld == 3.1.2
|
||||
// TODO tests.add(new Object[]{"weld", "cdi-decorate", null}); // Weld > 3.1.2
|
||||
tests.add(new Object[]{"owb", "cdi-spi", removeJettyWebXml});
|
||||
tests.add(new Object[]{"owb", "cdi2", null});
|
||||
// tests.add(new Object[]{"owb", "decorate", null}); // Will not be supported
|
||||
// tests.add(new Object[]{"owb", "cdi-decorate", null}); // Will not be supported
|
||||
return tests.stream().map(Arguments::of);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue