diff --git a/plugins/cdi/src/main/java/org/apache/struts2/cdi/CdiObjectFactory.java b/plugins/cdi/src/main/java/org/apache/struts2/cdi/CdiObjectFactory.java index af86f1395e..22c81d8e5f 100644 --- a/plugins/cdi/src/main/java/org/apache/struts2/cdi/CdiObjectFactory.java +++ b/plugins/cdi/src/main/java/org/apache/struts2/cdi/CdiObjectFactory.java @@ -20,6 +20,7 @@ package org.apache.struts2.cdi; import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.util.logging.Logger; import com.opensymphony.xwork2.util.logging.LoggerFactory; @@ -35,6 +36,13 @@ /** * CdiObjectFactory allows Struts 2 managed objects, like Actions, Interceptors or Results, to be injected by a Contexts * and Dependency Injection container (JSR299 / WebBeans). + * The BeanManager instance will be searched in the container's JNDI context, according to following algorithm: + * */ public class CdiObjectFactory extends ObjectFactory { @@ -48,8 +56,20 @@ public class CdiObjectFactory extends ObjectFactory { * The key under which the BeanManager can be found according to JBoss Weld docs */ public static final String CDI_JNDIKEY_BEANMANAGER_APP = "java:app/BeanManager"; + /** + * The key under which the BeanManager can be found in pure Servlet containers according to JBoss Weld docs. + */ + public static final String CDI_JNDIKEY_BEANMANAGER_COMP_ENV = "java:comp/env/BeanManager"; - protected BeanManager beanManager; + + private String jndiKey; + + @Inject(value = "struts.objectFactory.cdi.jndiKey", required = false) + public void setJndiKey( String jndiKey ) { + this.jndiKey = jndiKey; + } + + protected BeanManager beanManager; protected CreationalContext ctx; Map, InjectionTarget> injectionTargetCache = new ConcurrentHashMap, InjectionTarget>(); @@ -66,33 +86,72 @@ public CdiObjectFactory() { } } - /** - * Try to find the CDI BeanManager from JNDI context. First the key {@link #CDI_JNDIKEY_BEANMANAGER_COMP} will be - * tested. If nothing is found there, the key {@link #CDI_JNDIKEY_BEANMANAGER_APP} will be checked. - * - * @return the BeanManager, if found. null otherwise. - */ - protected BeanManager findBeanManager() { - BeanManager bm; - try { - Context initialContext = new InitialContext(); - LOG.info("[findBeanManager]: Checking for BeanManager under JNDI key " + CDI_JNDIKEY_BEANMANAGER_COMP); - try { - bm = (BeanManager) initialContext.lookup(CdiObjectFactory.CDI_JNDIKEY_BEANMANAGER_COMP); - } catch (NamingException e) { - LOG.warn("[findBeanManager]: Lookup failed.", e); - LOG.info("[findBeanManager]: Checking for BeanManager under JNDI key " + CDI_JNDIKEY_BEANMANAGER_APP); - bm = (BeanManager) initialContext.lookup(CdiObjectFactory.CDI_JNDIKEY_BEANMANAGER_APP); - } - LOG.info("[findBeanManager]: BeanManager found."); - return bm; - } catch (NamingException e) { - LOG.error("Could not get BeanManager from JNDI context", e); - } - return null; - } - - @Override + /** + * Try to find the CDI BeanManager from JNDI context. First, if provided, the key given by + * struts.objectFactory.cdi.jndiKey will be checked. Then, if nothing was found or no explicit configuration was + * given, the key {@link #CDI_JNDIKEY_BEANMANAGER_COMP} will be tested. If nothing is found there, the key {@link + * #CDI_JNDIKEY_BEANMANAGER_APP} will be checked. If still nothing is found there, the key {@link + * #CDI_JNDIKEY_BEANMANAGER_COMP_ENV} will be checked. + * + * @return the BeanManager, if found. null otherwise. + */ + protected BeanManager findBeanManager() { + BeanManager bm = null; + try { + Context initialContext = new InitialContext(); + if (jndiKey != null && jndiKey.trim().length() > 0) { + // Check explicit configuration first, if given + bm = lookup(initialContext, jndiKey); + } + if (bm == null) { + // Check CDI default + bm = lookup(initialContext, CDI_JNDIKEY_BEANMANAGER_COMP); + } + if (bm == null) { + // Check WELD default + bm = lookup(initialContext, CDI_JNDIKEY_BEANMANAGER_APP); + } + if (bm == null) { + // Check Tomcat / Jetty default + bm = lookup(initialContext, CDI_JNDIKEY_BEANMANAGER_COMP_ENV); + } + if (bm == null) { + if (LOG.isErrorEnabled()) { + LOG.error("[findBeanManager]: Could not find BeanManager instance for any given JNDI key, giving up"); + } + } + } catch ( NamingException e ) { + if (LOG.isErrorEnabled()) { + LOG.error("[findBeanManager]: Unable to get InitialContext for BeanManager lookup", e); + } + } + return bm; + } + + /** + * Lookup the given JNDI key in the given context. + * + * @param context the context to use for lookup. + * @param jndiKeyToCheck the key to lookup. + * + * @return the BeanManager, if found; null if not found or {@link javax.naming.NamingException} was thrown. + */ + protected BeanManager lookup( Context context, String jndiKeyToCheck ) { + if (LOG.isInfoEnabled()) { + LOG.info("[lookup]: Checking for BeanManager under JNDI key " + jndiKeyToCheck); + } + BeanManager result = null; + try { + result = (BeanManager) context.lookup(jndiKeyToCheck); + } catch ( NamingException e ) { + if (LOG.isDebugEnabled()) { + LOG.debug("[lookup]: BeanManager lookup failed for JNDI key " + jndiKeyToCheck, e); + } + } + return result; + } + + @Override @SuppressWarnings("unchecked") public Object buildBean(String className, Map extraContext, boolean injectInternal) throws Exception {