struts-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "ASF GitHub Bot (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (WW-4905) Allow using of Initializable interface on an implementation level
Date Wed, 10 Jan 2018 08:40:00 GMT

    [ https://issues.apache.org/jira/browse/WW-4905?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16319900#comment-16319900
] 

ASF GitHub Bot commented on WW-4905:
------------------------------------

yasserzamani closed pull request #196: WW-4905: Allows Initializable interface on implementing
class instead of interface
URL: https://github.com/apache/struts/pull/196
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/core/pom.xml b/core/pom.xml
index 0c97b0958..66519f0b2 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -65,7 +65,6 @@
                         <exclude>**/TestBean2.java</exclude>
                         <exclude>**/TestInterceptor.java</exclude>
                         <exclude>**/AnnotatedTestBean.java</exclude>
-                        <exclude>**/ContainerImplTest.java</exclude>
                         <exclude>**/DefaultFileManagerTest.java</exclude>
                     </excludes>
                 </configuration>
diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java b/core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java
index 8b8979a0a..ebec23fa2 100644
--- a/core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java
+++ b/core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java
@@ -74,6 +74,10 @@ public Object create(Context context) throws Exception {
                         return impl;
                     }
 
+                    @Override
+                    public Class type() {
+                        return impl.getClass();
+                    }
                 }, Scope.SINGLETON);
             }
         });
diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java b/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java
index e6dfd6953..21442dabc 100644
--- a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java
+++ b/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java
@@ -82,7 +82,11 @@ public void register(ContainerBuilder builder,
                     public Object create(Context context) throws Exception {
                         return impl;
                     }
-                    
+
+                    @Override
+                    public Class type() {
+                        return impl.getClass();
+                    }
                 }, Scope.SINGLETON);
             }
         });
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
index c8f98b82e..44746771c 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
@@ -172,6 +172,11 @@ public void rebuildRuntimeConfiguration() {
             public Configuration create(Context context) throws Exception {
                 return DefaultConfiguration.this;
             }
+
+            @Override
+            public Class<? extends Configuration> type() {
+                return DefaultConfiguration.this.getClass();
+            }
         });
 
         ActionContext oldContext = ActionContext.getContext();
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java
b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java
index 334e72676..1d36e6245 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java
@@ -36,7 +36,12 @@ public LocatableConstantFactory(T constant, Object location) {
     public T create(Context ignored) {
         return constant;
     }
-    
+
+    @Override
+    public Class type() {
+        return constant.getClass();
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java
b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java
index 05e447c6f..712809487 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java
@@ -51,6 +51,11 @@ public T create(Context context) {
         return (T) obj;
     }
 
+    @Override
+    public Class<? extends T> type() {
+        return implementation;
+    }
+
     @Override
     public String toString() {
         String fields = new LinkedHashMap<String, Object>() {
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java
b/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java
index 04597e1cd..94c766cac 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java
@@ -113,6 +113,7 @@
 import org.apache.struts2.StrutsConstants;
 import org.apache.struts2.dispatcher.HttpParameters;
 import org.apache.struts2.dispatcher.Parameter;
+import org.apache.struts2.factory.PrefixBasedActionProxyFactory;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionPropertiesProcessor.java
b/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionPropertiesProcessor.java
index d9e96fc5b..5fc6dd206 100644
--- a/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionPropertiesProcessor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionPropertiesProcessor.java
@@ -18,12 +18,10 @@
  */
 package com.opensymphony.xwork2.conversion;
 
-import com.opensymphony.xwork2.inject.Initializable;
-
 /**
  * Used to read converters from Properties file
  */
-public interface ConversionPropertiesProcessor extends Initializable {
+public interface ConversionPropertiesProcessor {
 
     /**
      * Process given property to load converters as not required (Properties file doesn't
have to exist)
diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionPropertiesProcessor.java
b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionPropertiesProcessor.java
index a76394c68..7336db1ec 100644
--- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionPropertiesProcessor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionPropertiesProcessor.java
@@ -23,6 +23,8 @@
 import com.opensymphony.xwork2.conversion.TypeConverter;
 import com.opensymphony.xwork2.conversion.TypeConverterCreator;
 import com.opensymphony.xwork2.conversion.TypeConverterHolder;
+import com.opensymphony.xwork2.inject.EarlyInitializable;
+import com.opensymphony.xwork2.inject.Initializable;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.util.ClassLoaderUtil;
 import org.apache.logging.log4j.Logger;
@@ -34,7 +36,7 @@
 import java.util.Map;
 import java.util.Properties;
 
-public class DefaultConversionPropertiesProcessor implements ConversionPropertiesProcessor
{
+public class DefaultConversionPropertiesProcessor implements ConversionPropertiesProcessor,
EarlyInitializable {
 
     private static final Logger LOG = LogManager.getLogger(DefaultConversionPropertiesProcessor.class);
 
diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerBuilder.java b/core/src/main/java/com/opensymphony/xwork2/inject/ContainerBuilder.java
index 4fbae8ee2..77c21cee1 100644
--- a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerBuilder.java
+++ b/core/src/main/java/com/opensymphony/xwork2/inject/ContainerBuilder.java
@@ -47,7 +47,7 @@
 
     final Map<Key<?>, InternalFactory<?>> factories = new HashMap<>();
     final List<InternalFactory<?>> singletonFactories = new ArrayList<>();
-    final List<InternalFactory<?>> initializableFactories = new ArrayList<>();
+    final List<InternalFactory<?>> earlyInitializableFactories = new ArrayList<>();
     final List<Class<?>> staticInjections = new ArrayList<>();
     boolean created;
     boolean allowDuplicates = false;
@@ -57,6 +57,11 @@
                 public Container create(InternalContext context) {
                     return context.getContainer();
                 }
+
+                @Override
+                public Class<? extends Container> type() {
+                    return Container.class;
+                }
             };
 
     private static final InternalFactory<Logger> LOGGER_FACTORY =
@@ -66,6 +71,11 @@ public Logger create(InternalContext context) {
                     return member == null ? Logger.getAnonymousLogger()
                             : Logger.getLogger(member.getDeclaringClass().getName());
                 }
+
+                @Override
+                public Class<? extends Logger> type() {
+                    return Logger.class;
+                }
             };
 
     /**
@@ -89,12 +99,14 @@ public ContainerBuilder() {
         checkKey(key);
         final InternalFactory<? extends T> scopedFactory = scope.scopeFactory(key.getType(),
key.getName(), factory);
         factories.put(key, scopedFactory);
-        if (scope == Scope.SINGLETON) {
-            singletonFactories.add(createCallableFactory(key, scopedFactory));
-        }
-        if (Initializable.class.isAssignableFrom(key.getType())) {
-            initializableFactories.add(createCallableFactory(key, scopedFactory));
+
+        InternalFactory<T> callableFactory = createCallableFactory(key, scopedFactory);
+        if (EarlyInitializable.class.isAssignableFrom(factory.type())) {
+            earlyInitializableFactories.add(callableFactory);
+        } else if (scope == Scope.SINGLETON) {
+            singletonFactories.add(callableFactory);
         }
+
         return this;
     }
 
@@ -108,6 +120,11 @@ public T create(InternalContext context) {
                     context.setExternalContext(null);
                 }
             }
+
+            @Override
+            public Class<? extends T> type() {
+                return scopedFactory.type();
+            }
         };
     }
 
@@ -145,6 +162,11 @@ public T create(InternalContext context) {
                 }
             }
 
+            @Override
+            public Class<? extends T> type() {
+                return factory.type();
+            }
+
             @Override
             public String toString() {
                 return new LinkedHashMap<String, Object>() {{
@@ -231,6 +253,11 @@ public T create(InternalContext context) {
                 return (T) constructor.construct(context, type);
             }
 
+            @Override
+            public Class<? extends T> type() {
+                return implementation;
+            }
+
             @Override
             public String toString() {
                 return new LinkedHashMap<String, Object>() {{
@@ -515,6 +542,11 @@ public T create(InternalContext ignored) {
                 return value;
             }
 
+            @Override
+            public Class<? extends T> type() {
+                return (Class<? extends T>) value.getClass();
+            }
+
             @Override
             public String toString() {
                 return new LinkedHashMap<String, Object>() {
@@ -587,13 +619,13 @@ public Void call(InternalContext context) {
                 }
             });
         }
+
         container.callInContext(new ContainerImpl.ContextualCallable<Void>() {
             public Void call(InternalContext context) {
-            for (InternalFactory<?> factory : initializableFactories) {
-                Initializable instance = (Initializable) factory.create(context);
-                instance.init();
-            }
-            return null;
+                for (InternalFactory<?> factory : earlyInitializableFactories) {
+                    factory.create(context);
+                }
+                return null;
             }
         });
 
diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java b/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
index 43db07f04..9505c64ef 100644
--- a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
+++ b/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
@@ -1,23 +1,18 @@
-/**
+/*
  * Copyright (C) 2006 Google Inc.
  *
- * <p>
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * </p>
  *
  *  http://www.apache.org/licenses/LICENSE-2.0
  *
- * <p>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- * </p>
  */
-
 package com.opensymphony.xwork2.inject;
 
 import com.opensymphony.xwork2.inject.util.ReferenceCache;
diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/EarlyInitializable.java b/core/src/main/java/com/opensymphony/xwork2/inject/EarlyInitializable.java
new file mode 100644
index 000000000..bf5d5f412
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/inject/EarlyInitializable.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.inject;
+
+/**
+ * A marking interface that will tell CI to initialise the bean when instating the whole
objects' graph
+ */
+public interface EarlyInitializable extends Initializable {
+}
diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/Factory.java b/core/src/main/java/com/opensymphony/xwork2/inject/Factory.java
index 8ef85fb2c..8287af65e 100644
--- a/core/src/main/java/com/opensymphony/xwork2/inject/Factory.java
+++ b/core/src/main/java/com/opensymphony/xwork2/inject/Factory.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2006 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.opensymphony.xwork2.inject;
 
 /**
@@ -23,12 +22,20 @@
  */
 public interface Factory<T> {
 
-  /**
-   * Creates an object to be injected.
-   *
-   * @param context of this injection
-   * @return instance to be injected
-   * @throws Exception if unable to create object
-   */
-  T create(Context context) throws Exception;
+    /**
+     * Creates an object to be injected.
+     *
+     * @param context of this injection
+     * @return instance to be injected
+     * @throws Exception if unable to create object
+     */
+    T create(Context context) throws Exception;
+
+    /**
+     * Returns a class of <T>
+     *
+     * @return class of the object
+     */
+    Class<? extends T> type();
+
 }
diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/InitializableFactory.java b/core/src/main/java/com/opensymphony/xwork2/inject/InitializableFactory.java
new file mode 100644
index 000000000..9859937bd
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/inject/InitializableFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.opensymphony.xwork2.inject;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+class InitializableFactory<T> implements InternalFactory<T> {
+
+    private static final Logger LOG = LogManager.getLogger(InitializableFactory.class);
+
+    private InternalFactory<T> internalFactory;
+
+    private InitializableFactory(InternalFactory<T> internalFactory) {
+        this.internalFactory = internalFactory;
+    }
+
+    public static <T> InternalFactory<T> wrapIfNeeded(InternalFactory<T>
internalFactory) {
+        if (Initializable.class.isAssignableFrom(internalFactory.type())) {
+            return new InitializableFactory<>(internalFactory);
+        }
+        return internalFactory;
+    }
+
+    @Override
+    public T create(InternalContext context) {
+        T instance = internalFactory.create(context);
+        if (Initializable.class.isAssignableFrom(instance.getClass())) {
+            Initializable.class.cast(instance).init();
+        } else {
+            LOG.error("Class {} is not marked as {}!", internalFactory.getClass().getName(),
Initializable.class.getName());
+        }
+        return instance;
+    }
+
+    @Override
+    public Class<? extends T> type() {
+        return internalFactory.type();
+    }
+}
diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java b/core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java
index 30391836b..4e61d255d 100644
--- a/core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java
+++ b/core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2006 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.opensymphony.xwork2.inject;
 
 import java.io.Serializable;
@@ -25,11 +24,19 @@
  */
 interface InternalFactory<T> extends Serializable {
 
-  /**
-   * Creates an object to be injected.
-   *
-   * @param context of this injection
-   * @return instance to be injected
-   */
-  T create(InternalContext context);
+    /**
+     * Creates an object to be injected.
+     *
+     * @param context of this injection
+     * @return instance to be injected
+     */
+    T create(InternalContext context);
+
+    /**
+     * Returns a class of <T>
+     *
+     * @return class of the object
+     */
+    Class<? extends T> type();
+
 }
diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/Scope.java b/core/src/main/java/com/opensymphony/xwork2/inject/Scope.java
index 73ca87bdb..86592bbe1 100644
--- a/core/src/main/java/com/opensymphony/xwork2/inject/Scope.java
+++ b/core/src/main/java/com/opensymphony/xwork2/inject/Scope.java
@@ -33,7 +33,7 @@
         @Override
         <T> InternalFactory<? extends T> scopeFactory(Class<T> type, String
name,
                                                       InternalFactory<? extends T>
factory) {
-            return factory;
+            return InitializableFactory.wrapIfNeeded(factory);
         }
     },
 
@@ -49,12 +49,17 @@
                 public T create(InternalContext context) {
                     synchronized (context.getContainer()) {
                         if (instance == null) {
-                            instance = factory.create(context);
+                            instance = InitializableFactory.wrapIfNeeded(factory).create(context);
                         }
                         return instance;
                     }
                 }
 
+                @Override
+                public Class<? extends T> type() {
+                    return factory.type();
+                }
+
                 @Override
                 public String toString() {
                     return factory.toString();
@@ -83,12 +88,17 @@ public String toString() {
                 public T create(final InternalContext context) {
                     T t = threadLocal.get();
                     if (t == null) {
-                        t = factory.create(context);
+                        t = InitializableFactory.wrapIfNeeded(factory).create(context);
                         threadLocal.set(t);
                     }
                     return t;
                 }
 
+                @Override
+                public Class<? extends T> type() {
+                    return factory.type();
+                }
+
                 @Override
                 public String toString() {
                     return factory.toString();
@@ -114,6 +124,11 @@ public T create(InternalContext context) {
                     }
                 }
 
+                @Override
+                public Class<? extends T> type() {
+                    return factory.type();
+                }
+
                 @Override
                 public String toString() {
                     return factory.toString();
@@ -139,6 +154,11 @@ public T create(InternalContext context) {
                     }
                 }
 
+                @Override
+                public Class<? extends T> type() {
+                    return factory.type();
+                }
+
                 @Override
                 public String toString() {
                     return factory.toString();
@@ -164,6 +184,11 @@ public T create(InternalContext context) {
                     }
                 }
 
+                @Override
+                public Class<? extends T> type() {
+                    return factory.type();
+                }
+
                 @Override
                 public String toString() {
                     return factory.toString();
@@ -176,7 +201,7 @@ public String toString() {
                                          final InternalFactory<? extends T> factory)
{
         return new Callable<T>() {
             public T call() throws Exception {
-                return factory.create(context);
+                return InitializableFactory.wrapIfNeeded(factory).create(context);
             }
         };
     }
diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/DefaultValidatorFactory.java
b/core/src/main/java/com/opensymphony/xwork2/validator/DefaultValidatorFactory.java
index d945e0a26..ca11235af 100644
--- a/core/src/main/java/com/opensymphony/xwork2/validator/DefaultValidatorFactory.java
+++ b/core/src/main/java/com/opensymphony/xwork2/validator/DefaultValidatorFactory.java
@@ -22,6 +22,7 @@
 import com.opensymphony.xwork2.ObjectFactory;
 import com.opensymphony.xwork2.XWorkException;
 import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.inject.Initializable;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.util.ClassLoaderUtil;
 import org.apache.logging.log4j.LogManager;
@@ -44,7 +45,7 @@
  * @author Jason Carreira
  * @author James House
  */
-public class DefaultValidatorFactory implements ValidatorFactory {
+public class DefaultValidatorFactory implements ValidatorFactory, Initializable {
 
     protected Map<String, String> validators = new HashMap<>();
     private static Logger LOG = LogManager.getLogger(DefaultValidatorFactory.class);
diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java b/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java
index 5c3ce7ed4..8510fe6bb 100644
--- a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java
+++ b/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java
@@ -18,8 +18,6 @@
  */
 package com.opensymphony.xwork2.validator;
 
-import com.opensymphony.xwork2.inject.Initializable;
-
 /**
  * ValidatorFactory
  *
@@ -227,7 +225,7 @@
  * @author Jason Carreira
  * @author James House
  */
-public interface ValidatorFactory extends Initializable {
+public interface ValidatorFactory {
 
     /**
      * Get a Validator that matches the given configuration.
diff --git a/core/src/main/java/org/apache/struts2/config/AbstractBeanSelectionProvider.java
b/core/src/main/java/org/apache/struts2/config/AbstractBeanSelectionProvider.java
index 1b5d7e42b..908a66ed9 100644
--- a/core/src/main/java/org/apache/struts2/config/AbstractBeanSelectionProvider.java
+++ b/core/src/main/java/org/apache/struts2/config/AbstractBeanSelectionProvider.java
@@ -113,5 +113,10 @@ public Object create(Context context) throws Exception {
                 throw new ConfigurationException("Unable to load bean "+type.getName()+"
("+name+")");
             }
         }
+
+        @Override
+        public Class type() {
+            return type;
+        }
     }
 }
diff --git a/core/src/main/java/org/apache/struts2/config/StrutsXmlConfigurationProvider.java
b/core/src/main/java/org/apache/struts2/config/StrutsXmlConfigurationProvider.java
index c4de24938..ef27b6ce5 100644
--- a/core/src/main/java/org/apache/struts2/config/StrutsXmlConfigurationProvider.java
+++ b/core/src/main/java/org/apache/struts2/config/StrutsXmlConfigurationProvider.java
@@ -90,6 +90,9 @@ public void register(ContainerBuilder containerBuilder, LocatableProperties
prop
                 public ServletContext create(Context context) throws Exception {
                     return servletContext;
                 }
+                public Class<? extends ServletContext> type() {
+                    return servletContext.getClass();
+                }
             });
         }
         super.register(containerBuilder, props);
diff --git a/core/src/main/java/org/apache/struts2/factory/PrefixBasedActionProxyFactory.java
b/core/src/main/java/org/apache/struts2/factory/PrefixBasedActionProxyFactory.java
index cf196a9b2..03052ec6a 100644
--- a/core/src/main/java/org/apache/struts2/factory/PrefixBasedActionProxyFactory.java
+++ b/core/src/main/java/org/apache/struts2/factory/PrefixBasedActionProxyFactory.java
@@ -59,11 +59,12 @@
  * </pre>
  * <!-- END SNIPPET: description -->
  */
-public class PrefixBasedActionProxyFactory extends StrutsActionProxyFactory {
+public class PrefixBasedActionProxyFactory extends StrutsActionProxyFactory implements Initializable
{
 
     private static final Logger LOG = LogManager.getLogger(PrefixBasedActionProxyFactory.class);
 
     private Map<String, ActionProxyFactory> actionProxyFactories = new HashMap<>();
+    private Set<String> prefixes = new HashSet<>();
 
     @Inject
     public void setContainer(Container container) {
@@ -73,18 +74,22 @@ public void setContainer(Container container) {
     @Inject(StrutsConstants.PREFIX_BASED_MAPPER_CONFIGURATION)
     public void setPrefixBasedActionProxyFactories(String list) {
         if (list != null) {
-            Set<String> prefixes = new HashSet<>(Arrays.asList(list.split(",")));
-            for (String factory : prefixes) {
-                String[] thisFactory = factory.split(":");
-                if (thisFactory.length == 2) {
-                    String factoryPrefix = thisFactory[0].trim();
-                    String factoryName = thisFactory[1].trim();
-                    ActionProxyFactory obj = container.getInstance(ActionProxyFactory.class,
factoryName);
-                    if (obj != null) {
-                        actionProxyFactories.put(factoryPrefix, obj);
-                    } else {
-                        LOG.warn("Invalid PrefixBasedActionProxyFactory config entry: [{}]",
factory);
-                    }
+            prefixes = new HashSet<>(Arrays.asList(list.split(",")));
+        }
+    }
+
+    @Override
+    public void init() {
+        for (String factory : prefixes) {
+            String[] thisFactory = factory.split(":");
+            if (thisFactory.length == 2) {
+                String factoryPrefix = thisFactory[0].trim();
+                String factoryName = thisFactory[1].trim();
+                ActionProxyFactory obj = container.getInstance(ActionProxyFactory.class,
factoryName);
+                if (obj != null) {
+                    actionProxyFactories.put(factoryPrefix, obj);
+                } else {
+                    LOG.warn("Invalid PrefixBasedActionProxyFactory config entry: [{}]",
factory);
                 }
             }
         }
diff --git a/core/src/test/java/com/opensymphony/xwork2/config/ConfigurationManagerTest.java
b/core/src/test/java/com/opensymphony/xwork2/config/ConfigurationManagerTest.java
index 62449ed36..864f790d5 100644
--- a/core/src/test/java/com/opensymphony/xwork2/config/ConfigurationManagerTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/config/ConfigurationManagerTest.java
@@ -23,6 +23,7 @@
 import com.opensymphony.xwork2.FileManagerFactory;
 import com.opensymphony.xwork2.XWorkTestCase;
 import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
+import com.opensymphony.xwork2.conversion.TypeConverterHolder;
 import com.opensymphony.xwork2.inject.Container;
 import com.opensymphony.xwork2.inject.ContainerBuilder;
 import com.opensymphony.xwork2.util.location.LocatableProperties;
@@ -152,6 +153,12 @@ public void testClearConfigurationProviders() throws Exception {
         configProviderMock.verify();
     }
 
+    public void testEarlyInitializable() throws Exception {
+        TypeConverterHolder converterHolder = container.getInstance(TypeConverterHolder.class);
+        assertTrue("java.io.File mapping should being putted by DefaultConversionPropertiesProcessor.init()",
+                converterHolder.containsDefaultMapping("java.io.File"));
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
diff --git a/core/src/test/java/com/opensymphony/xwork2/inject/ContainerImplTest.java b/core/src/test/java/com/opensymphony/xwork2/inject/ContainerImplTest.java
index 17f1b8037..338dc5968 100644
--- a/core/src/test/java/com/opensymphony/xwork2/inject/ContainerImplTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/inject/ContainerImplTest.java
@@ -20,6 +20,8 @@
 
 import junit.framework.TestCase;
 
+import java.security.Permission;
+
 /**
  * ContainerImpl Tester.
  *
@@ -33,11 +35,20 @@
 
     @Override
     protected void setUp() throws Exception {
+        System.setSecurityManager(null);
+
         super.setUp();
         ContainerBuilder cb = new ContainerBuilder();
         cb.constant("methodCheck.name", "Lukasz");
         cb.constant("fieldCheck.name", "Lukasz");
+        cb.factory(EarlyInitializable.class, EarlyInitializableBean.class, Scope.SINGLETON);
+        cb.factory(Initializable.class, InitializableBean.class, Scope.SINGLETON);
+        cb.factory(EarlyInitializable.class, "prototypeEarlyInitializable", EarlyInitializableBean.class,
Scope.PROTOTYPE);
+        cb.factory(Initializable.class, "prototypeInitializable", InitializableBean.class,
Scope.PROTOTYPE);
         c = cb.create(false);
+
+        Class.forName(FieldCheck.class.getName());
+        Class.forName(ContainerImpl.FieldInjector.class.getName());
     }
 
     /**
@@ -76,17 +87,15 @@ public void testMethodInjector() throws Exception {
      * Inject values into field under SecurityManager
      */
     public void testFieldInjectorWithSecurityEnabled() throws Exception {
-
-        System.setSecurityManager(new SecurityManager());
+        System.setSecurityManager(new TestSecurityManager());
 
         FieldCheck fieldCheck = new FieldCheck();
 
         try {
             c.inject(fieldCheck);
-            assertEquals(fieldCheck.getName(), "Lukasz");
             fail("Exception should be thrown!");
-        } catch (DependencyException expected) {
-            // that was expected
+        } catch (Error | DependencyException expected) {
+            assertTrue(true);
         }
     }
 
@@ -94,22 +103,48 @@ public void testFieldInjectorWithSecurityEnabled() throws Exception {
      * Inject values into method under SecurityManager
      */
     public void testMethodInjectorWithSecurityEnabled() throws Exception {
-
-        // not needed, already set
-        //System.setSecurityManager(new SecurityManager());
+        System.setSecurityManager(new TestSecurityManager());
 
         MethodCheck methodCheck = new MethodCheck();
 
         try {
             c.inject(methodCheck);
-            assertEquals(methodCheck.getName(), "Lukasz");
-            fail("Exception sould be thrown!");
-        } catch (DependencyException expected) {
-            // that was expected
+            fail("Exception should be thrown!");
+        } catch (DependencyException | Error expected) {
+            assertTrue(true);
         }
     }
 
-    class FieldCheck {
+    public void testEarlyInitializable() throws Exception {
+        assertTrue("should being initialized already", EarlyInitializableBean.initializedEarly);
+
+        EarlyInitializableCheck earlyInitializableCheck = new EarlyInitializableCheck();
+        c.inject(earlyInitializableCheck);
+        assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck.getEarlyInitializable()).getMessage());
+        assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck.getPrototypeEarlyInitializable()).getMessage());
+
+        EarlyInitializableCheck earlyInitializableCheck2 = new EarlyInitializableCheck();
+        c.inject(earlyInitializableCheck2);
+        assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck2.getEarlyInitializable()).getMessage());
+        assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck2.getPrototypeEarlyInitializable()).getMessage());
+    }
+
+    public void testInitializable() throws Exception {
+        assertFalse("should not being initialized already", InitializableBean.initialized);
+
+        InitializableCheck initializableCheck = new InitializableCheck();
+        c.inject(initializableCheck);
+        assertTrue("should being initialized here", InitializableBean.initialized);
+        assertEquals("initialized", ((InitializableBean) initializableCheck.getInitializable()).getMessage());
+        assertEquals("initialized", ((InitializableBean) initializableCheck.getPrototypeInitializable()).getMessage());
+
+        InitializableCheck initializableCheck2 = new InitializableCheck();
+        c.inject(initializableCheck2);
+        assertEquals("initialized", ((InitializableBean) initializableCheck2.getInitializable()).getMessage());
+        assertEquals("initialized", ((InitializableBean) initializableCheck2.getPrototypeInitializable()).getMessage());
+    }
+
+    public static class FieldCheck {
 
         @Inject("fieldCheck.name")
         private String name;
@@ -119,7 +154,7 @@ public String getName() {
         }
     }
 
-    class MethodCheck {
+    public static class MethodCheck {
 
         private String name;
 
@@ -134,4 +169,61 @@ public String getName() {
 
     }
 
+    class InitializableCheck {
+
+        private Initializable initializable;
+        private Initializable prototypeInitializable;
+
+        @Inject
+        public void setInitializable(Initializable initializable) {
+            this.initializable = initializable;
+        }
+
+        @Inject("prototypeInitializable")
+        public void setPrototypeInitializable(Initializable prototypeInitializable) {
+            this.prototypeInitializable = prototypeInitializable;
+        }
+
+        public Initializable getInitializable() {
+            return initializable;
+        }
+
+        public Initializable getPrototypeInitializable() {
+            return prototypeInitializable;
+        }
+    }
+
+    class EarlyInitializableCheck {
+
+        private EarlyInitializable earlyInitializable;
+        private EarlyInitializable prototypeEarlyInitializable;
+
+        @Inject
+        public void setEarlyInitializable(EarlyInitializable earlyInitializable) {
+            this.earlyInitializable = earlyInitializable;
+        }
+
+        @Inject("prototypeEarlyInitializable")
+        public void setPrototypeEarlyInitializable(EarlyInitializable prototypeEarlyInitializable)
{
+            this.prototypeEarlyInitializable = prototypeEarlyInitializable;
+        }
+
+        public EarlyInitializable getEarlyInitializable() {
+            return earlyInitializable;
+        }
+
+        public EarlyInitializable getPrototypeEarlyInitializable() {
+            return prototypeEarlyInitializable;
+        }
+    }
+
+    class TestSecurityManager extends SecurityManager {
+
+        @Override
+        public void checkPermission(Permission perm) {
+            if (!"setSecurityManager".equals(perm.getName())) {
+                super.checkPermission(perm);
+            }
+        }
+    }
 }
diff --git a/core/src/test/java/com/opensymphony/xwork2/inject/EarlyInitializableBean.java
b/core/src/test/java/com/opensymphony/xwork2/inject/EarlyInitializableBean.java
new file mode 100644
index 000000000..6b7752799
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/inject/EarlyInitializableBean.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.opensymphony.xwork2.inject;
+
+class EarlyInitializableBean implements EarlyInitializable {
+    private String message = "";
+    static boolean initializedEarly;
+
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public void init() {
+        message += "initialized early";
+        initializedEarly = true;
+    }
+}
diff --git a/core/src/test/java/com/opensymphony/xwork2/inject/InitializableBean.java b/core/src/test/java/com/opensymphony/xwork2/inject/InitializableBean.java
new file mode 100644
index 000000000..4fb7cd970
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/inject/InitializableBean.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.opensymphony.xwork2.inject;
+
+public class InitializableBean implements Initializable {
+    private String message = "";
+    static boolean initialized;
+
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public void init() {
+        message += "initialized";
+        initialized = true;
+    }
+}
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/SetPropertiesTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/SetPropertiesTest.java
index c19895ff7..363acf977 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/SetPropertiesTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/SetPropertiesTest.java
@@ -144,7 +144,11 @@ public void register(ContainerBuilder builder,
                     public Object create(Context context) throws Exception {
                         return new MockObjectTypeDeterminer(null,Cat.class,null,allowAdditions);
                     }
-                    
+
+                    @Override
+                    public Class type() {
+                        return Cat.class;
+                    }
                 });
             }
         });
@@ -290,7 +294,11 @@ public void register(ContainerBuilder builder,
                     public Object create(Context context) throws Exception {
                         return determiner;
                     }
-                    
+
+                    @Override
+                    public Class type() {
+                        return determiner.getClass();
+                    }
                 }, Scope.SINGLETON);
             }
         });
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java
b/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java
index d6cae3869..42075db5f 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/SimpleActionValidationTest.java
@@ -226,6 +226,12 @@ public void testSubPropertiesAreValidated() {
         }
     }
 
+    public void testInitializable() throws Exception {
+        ValidatorFactory validatorFactory = container.getInstance(ValidatorFactory.class);
+        assertEquals("com.opensymphony.xwork2.validator.validators.RequiredFieldValidator",
+                validatorFactory.lookupRegisteredValidatorType("requiredAnother"));
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
diff --git a/core/src/test/java/org/apache/struts2/factory/PrefixBasedActionProxyFactoryTest.java
b/core/src/test/java/org/apache/struts2/factory/PrefixBasedActionProxyFactoryTest.java
index 27e9d019c..109a61fec 100644
--- a/core/src/test/java/org/apache/struts2/factory/PrefixBasedActionProxyFactoryTest.java
+++ b/core/src/test/java/org/apache/struts2/factory/PrefixBasedActionProxyFactoryTest.java
@@ -41,7 +41,7 @@
     private PrefixBasedActionProxyFactory factory;
 
     public void testDifferentPrefixes() throws Exception {
-        factory.setPrefixBasedActionProxyFactories("/ns1:prefix1,/ns2:prefix2");
+        initFactory("/ns1:prefix1,/ns2:prefix2");
 
         ActionProxy proxy1 = factory.createActionProxy("/ns1", "", "", Collections.<String,
Object>emptyMap(), false, true);
         assertTrue(proxy1 instanceof Prefix1ActionProxy);
@@ -51,7 +51,7 @@ public void testDifferentPrefixes() throws Exception {
     }
 
     public void testFallbackToDefault() throws Exception {
-        factory.setPrefixBasedActionProxyFactories("/ns1:prefix1");
+        initFactory("/ns1:prefix1");
 
         ActionProxy proxy1 = factory.createActionProxy("/ns1", "", "", Collections.<String,
Object>emptyMap(), false, true);
         assertTrue(proxy1 instanceof Prefix1ActionProxy);
@@ -61,7 +61,7 @@ public void testFallbackToDefault() throws Exception {
     }
 
     public void testEmptyPrefix() throws Exception {
-        factory.setPrefixBasedActionProxyFactories(":prefix1");
+        initFactory(":prefix1");
 
         ActionProxy proxy1 = factory.createActionProxy("/ns1", "", "", Collections.<String,
Object>emptyMap(), false, true);
         assertTrue(proxy1 instanceof Prefix1ActionProxy);
@@ -81,7 +81,9 @@ public void register(ContainerBuilder builder, LocatableProperties props)
throws
                             public Object create(Context context) throws Exception {
                                 return new Prefix1Factory();
                             }
-
+                            public Class type() {
+                                return Prefix1Factory.class;
+                            }
                         }, Scope.SINGLETON);
                     }
                 },
@@ -92,7 +94,9 @@ public void register(ContainerBuilder builder, LocatableProperties props)
throws
                             public Object create(Context context) throws Exception {
                                 return new Prefix2Factory();
                             }
-
+                            public Class type() {
+                                return Prefix2Factory.class;
+                            }
                         }, Scope.SINGLETON);
                     }
                 }
@@ -104,6 +108,11 @@ public Object create(Context context) throws Exception {
         factory.setContainer(container);
     }
 
+    void initFactory(String list) {
+        factory.setPrefixBasedActionProxyFactories(list);
+        factory.init();
+    }
+
     @Override
     public void tearDown() throws Exception {
         super.tearDown();


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


> Allow using of Initializable interface on an implementation level
> -----------------------------------------------------------------
>
>                 Key: WW-4905
>                 URL: https://issues.apache.org/jira/browse/WW-4905
>             Project: Struts 2
>          Issue Type: Improvement
>          Components: Core
>    Affects Versions: 2.5.14
>            Reporter: Lukasz Lenart
>            Assignee: Lukasz Lenart
>             Fix For: 2.6
>
>
> It's a follow up on an issue discovered here [1] - basically it isn't possible to define
a {{Initializable}} interface in an implementing class as the current implementation of {{ContainerBuilder}}
doesn't support this. It must be defined on the type interface which is implemented by a bean.
> [1] https://github.com/apache/struts/pull/195#issuecomment-354642232



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)


Mime
View raw message