You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@struts.apache.org by "Dave Newton (JIRA)" <ji...@apache.org> on 2009/06/07 21:43:43 UTC

[jira] Issue Comment Edited: (WW-3153) xwork com.opensymphony.xwork2.config.ConfigurationManager needs better error handling for missing plugin config,class

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

Dave Newton edited comment on WW-3153 at 6/7/09 12:42 PM:
----------------------------------------------------------

Please devise a more legible means to communicate your concerns. Perhaps simply providing pointers to source code rather than embedding Java comments in a swatch of extracted code.

Also note that S2.1.6 has a dependency on XW2.1.2, so reporting an XW2.0-SNAPSHOT environment is misleading.

      was (Author: newton_dave):
    Please devise a more legible means with which to communicate your concerns.
  
> xwork com.opensymphony.xwork2.config.ConfigurationManager needs better error handling for missing plugin config,class
> ---------------------------------------------------------------------------------------------------------------------
>
>                 Key: WW-3153
>                 URL: https://issues.apache.org/struts/browse/WW-3153
>             Project: Struts 2
>          Issue Type: Bug
>         Environment: Struts 2.1.6
> xwork 2.0-SNAPSHOT
> J2SE 1.6.0.10
> TC 1.6
>            Reporter: Martin Gainty
>
> xwork com.opensymphony.xwork2.config.ConfigurationManager code
>   /*** Get the current XWork configuration object.  By default an instance of     
>           DefaultConfiguration will be returned
>      * @see com.opensymphony.xwork2.config.impl.DefaultConfiguration
>      */
>     public synchronized Configuration getConfiguration() {
>         if (configuration == null) {
>             setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
>             try {
>                 configuration.reload(getConfigurationProviders());
>             } catch (ConfigurationException e) {
>                 setConfiguration(null);
> /******   xwork  getConfigurationProviders code inlined so we can see whats going on ***
>      * Get the current list of ConfigurationProviders. If no custom ConfigurationProviders have been added, this method
>      * will return a list containing only the default ConfigurationProvider, XMLConfigurationProvider.  if a custom
>      * ConfigurationProvider has been added, then the XmlConfigurationProvider must be added by hand.
>      * </p>
>      * <p/>
>      * TODO: the lazy instantiation of XmlConfigurationProvider should be refactored to be elsewhere.  the behavior described above seems unintuitive.
>      *
>      * @return the list of registered ConfigurationProvider objects
>      * @see ConfigurationProvider
>      */
>     public List<ConfigurationProvider> getConfigurationProviders() {
>         providerLock.lock();
>         try {
>             if (configurationProviders.size() == 0) {
>                 configurationProviders.add(new XmlConfigurationProvider("xwork.xml", true));
>             }
>             return configurationProviders;
>         } finally {
>             providerLock.unlock();
>         }
>     }
> ***********/
>                 throw e;
>             }
>         } else {
>             conditionalReload();
>         }
>         return configuration;
>     }
> //end configurationManager
> //Here is com.opensymphony.xwork2.config.impl.DefaultConfigurationProvider
> public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
>         ContainerProperties props = new ContainerProperties();
>         ContainerBuilder builder = new ContainerBuilder();
>         for (final ContainerProvider containerProvider : providers)
>         {
>             containerProvider.init(this);
>             containerProvider.register(builder, props);
>         }
>         props.setConstants(builder);
> //a quick recap of setConstants
> /*public void setConstants(ContainerBuilder builder) {
> //keySet appears to be empty so the iterator to key wont work here
>             for (Object keyobj : keySet()) {
>                 String key = (String)keyobj;
>                 builder.factory(String.class, key,
>                         new LocatableConstantFactory<String>(getProperty(key), getPropertyLocation(key)));
>             }
>         }
> */
>         container = builder.create(false);
> /*start code com.opensymphony.xwork2.inject.ConfigurationBuilder.create()
> public Container create(boolean loadSingletons) {
>     ensureNotCreated();
>     created = true;
>     final ContainerImpl container = new ContainerImpl(
>         new HashMap<Key<?>, InternalFactory<?>>(factories));
>     if (loadSingletons) {                 //wont happen as this is always false
>       container.callInContext(new ContainerImpl.ContextualCallable<Void>() {
>         public Void call(InternalContext context) {
>           for (InternalFactory<?> factory : singletonFactories) {
>             factory.create(context);
>           }
>           return null;
>         }
>       });
>     }
> //final List<Class<?>> staticInjections = new ArrayList<Class<?>>();
> //no effect as staticInjections are null at this point
>     container.injectStatics(staticInjections);
>     return container;
>   }
> //end com.opensymphony.xwork2.inject.ConfigurationBuilder.create()
> */
>             setContext(container);
> /******* setContext code inlined so we can see whats going on
>     protected ActionContext setContext(Container cont) {
>         ValueStack vs = cont.getInstance(ValueStackFactory.class).createValueStack();
>         ActionContext context = new ActionContext(vs.getContext());
>         ActionContext.setContext(context);
>         return context; //returns the context of the VS from the supplied container
>     }
> ********/
> //  Set<String> getInstanceNames(Class<?> type);
>             objectFactory = container.getInstance(ObjectFactory.class);
> //a not null objectFactory with no contained objects
>             // Process the configuration providers first (WARNING providers could be null!)
>             for (final ContainerProvider containerProvider : providers)
>             {
>                 if (containerProvider instanceof PackageProvider) {
>                     container.inject(containerProvider);
>                     ((PackageProvider)containerProvider).loadPackages();
>                     packageProviders.add((PackageProvider)containerProvider);
>                 }
>             }
>            
>             // Then process any package providers from the plugins
> //Container.getInstanceNames     Set<String> getInstanceNames(Class<?> type);
> /*com.opensymphony.xwork2.inject.ContainerImpl has getInstanceNames we can use
>   public Set<String> getInstanceNames(final Class<?> type) {
>     return factoryNamesByType.get(type);
> //FYI this.factoryNamesByType = Collections.unmodifiableMap(map);
> //now a simple get on the key should return the Factory for PackageProvider
>   }
> */
>             Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
>             if (packageProviderNames != null) {
>                 for (String name : packageProviderNames) {
>                     PackageProvider provider = container.getInstance(PackageProvider.class, name);
>                     provider.init(this);
>                     provider.loadPackages();
>                     packageProviders.add(provider);
>                 }
>             }
>    
>             rebuildRuntimeConfiguration();
>         } finally {
>             ActionContext.setContext(null);
>         }
>         return packageProviders;
> //how does a factory for PackageProvider get created?
> /* CAUTION members needs to contain the classnames for factory to create
>   <M extends Member & AnnotatedElement> void addInjectorsForMembers(
>       List<M> members, boolean statics, List<Injector> injectors,
>       InjectorFactory<M> injectorFactory) {
>     for (M member : members) {
>       if (isStatic(member) == statics) {
>         Inject inject = member.getAnnotation(Inject.class);
>         if (inject != null) {
>           try {
>             injectors.add(injectorFactory.create(this, member, inject.value()));
>           } catch (MissingDependencyException e) {
>             if (inject.required()) {
>               throw new DependencyException(e);
>             }
>           }
>         }
>       }
>     }
>   }
> */
> //where is addInjectorsForMembers called?
> /*addInjectorsForMembers is called as Injector parameter to method
>   void addInjectorsForMethods(Method[] methods, boolean statics,
>       List<Injector> injectors) {
>     addInjectorsForMembers(Arrays.asList(methods), statics, injectors,
>         new InjectorFactory<Method>() {
>           public Injector create(ContainerImpl container, Method method,
>               String name) throws MissingDependencyException {
>             return new MethodInjector(container, method, name);
>           }
>         });
>   }
> */
> OR addInjectorsForMember is called as parameter to Field
>   void addInjectorsForFields(Field[] fields, boolean statics,
>       List<Injector> injectors) {
>     addInjectorsForMembers(Arrays.asList(fields), statics, injectors,
>         new InjectorFactory<Field>() {
>           public Injector create(ContainerImpl container, Field field,
>               String name) throws MissingDependencyException {
>             return new FieldInjector(container, field, name);
>           }
>         });
>   }
> //where do the injectors come from
> //they are called as a parameter to injectStatics here is the code:
>   void injectStatics(List<Class<?>> staticInjections) {
>     final List<Injector> injectors = new ArrayList<Injector>();
>     for (Class<?> clazz : staticInjections) {
>       addInjectorsForFields(clazz.getDeclaredFields(), true, injectors);
>       addInjectorsForMethods(clazz.getDeclaredMethods(), true, injectors);
>     }
>     callInContext(new ContextualCallable<Void>() {
>       public Void call(InternalContext context) {
>         for (Injector injector : injectors) {
>           injector.inject(context, null);
>         }
>         return null;
>       }
>     });
>   }
> //the solution comes provided with test samples for xwork2
> //com.opensymphony.xwork2.conf.XmlConfigurationProvider.java
>                           String impl=java.util.Properties.getProperty("struts.convention.actionConfigBuilder");
>                           Class clazz = new Class(impl);
> //quick sanity check
>                           if (clazz==null)
> { log.debug(impl+"class is not on classpath please put actionConfigBuilder class on classpath"); }
> //if the instantiated class is null because of wrong name or not on classpath we should log the error!
>                             Class cimpl = ClassLoaderUtil.loadClass(impl, clazz);
>                           if (cimpl==null)
> { log.debug(impl+"class is not on classpath please put actionConfigBuilder class on classpath"); }
> //if the instantiated class is null because of wrong name or not on classpath or CL couldnt find we should log the error!
> /*the resourceName HAS TO BE PRECONFIGURED in context otherwise call to getResource on impl will fail
>     public static URL getResource(String resourceName, Class callingClass) {
>         URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
>         if (url == null) {
>             url = ClassLoaderUtil.class.getClassLoader().getResource(resourceName);
>         }
>         if (url == null) {
>             ClassLoader cl = callingClass.getClassLoader();
>             if (cl != null) {
>                 url = cl.getResource(resourceName);
>             }
>         }
> */
>                           // Force loading of class to detect no class def found exceptions
>                            try
>                            {
>                             cimpl.getDeclaredClasses();
>                              }
>                            catch(ClassNotFoundException cnfe)
>                           {
>                            log.debug("current CL cant locate class "+cimpl+"place class on CLASSPATH or configuration for plugin class is missing please try again");
>                           }
>        //now that you have the actionConfigBuilder Class built and the configuration is verified go ahead and inject
>                     containerBuilder.injectStatics(cimpl);
> HTH
> Martin Gainty

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.