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:
+ *
+ * - if a value for configuration constant
struts.objectFactory.cdi.jndiKey
is given, this key will be looked up
+ * - if no BeanManager found so far, look under {@link #CDI_JNDIKEY_BEANMANAGER_COMP}
+ * - if no BeanManager found so far, look under {@link #CDI_JNDIKEY_BEANMANAGER_APP}
+ * - if no BeanManager found so far, look under {@link #CDI_JNDIKEY_BEANMANAGER_COMP_ENV}
+ *
*/
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 {