Hello,

I tried to upgrade my cocoon based product to use spring 3.0 new features. One of those is @Value("${propertyName}") annotation.

This feature works for <context:property-placeholder/> but does not for cocoon's <configurator:settings/>. This is slightly weird as coocon configurator theoreticaly bases on PropertyPlaceholderConfigurer.

The issue lies in this code (I used :

cocoon-spring-configurator-1.0.2\src\main\java\org\apache\cocoon\spring\configurator\impl\AbstractSettingsBeanFactoryPostProcessor.java


    /**
     * @see 
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#processProperties(org.springframework.beans.factory.config.ConfigurableListableBeanFactory,
 java.util.Properties)
     */
    protected void processProperties(ConfigurableListableBeanFactory 
beanFactoryToProcess,
                                     Properties props)
    throws BeansException {
        final BeanDefinitionVisitor visitor = new 
CocoonSettingsResolvingBeanDefinitionVisitor(this.settings);
        String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
        for (int i = 0; i < beanNames.length; i++) {
            BeanDefinition bd = 
beanFactoryToProcess.getBeanDefinition(beanNames[i]);
            try {
                visitor.visitBeanDefinition(bd);
            } catch (BeanDefinitionStoreException e) {
                throw new 
BeanDefinitionStoreException(bd.getResourceDescription(), beanNames[i], e);
            }
        }
    }

        protected class CocoonSettingsResolvingBeanDefinitionVisitor extends 
BeanDefinitionVisitor {

                protected final Properties      props;
                protected final Set                     visitedPlaceholders     
= new HashSet();

                public CocoonSettingsResolvingBeanDefinitionVisitor( Settings 
settings ) {
                        this.props = new SettingsProperties( settings );
                }

                protected String resolveStringValue( String strVal ) {
                        return parseStringValue(        strVal,
                                                                                
this.props,
                                                                                
visitedPlaceholders );
                }
        }


This method completely rewrites the super method (from PropertyPlaceholderConfigurer) which looks like this:

        @Override
        protected void processProperties(ConfigurableListableBeanFactory 
beanFactoryToProcess, Properties props)
                        throws BeansException {

                StringValueResolver valueResolver = new 
PlaceholderResolvingStringValueResolver(props);
                BeanDefinitionVisitor visitor = new 
BeanDefinitionVisitor(valueResolver);

                String[] beanNames = 
beanFactoryToProcess.getBeanDefinitionNames();
                for (String curName : beanNames) {
                        // Check that we're not parsing our own bean definition,
                        // to avoid failing on unresolvable placeholders in 
properties file locations.
                        if (!(curName.equals(this.beanName) && 
beanFactoryToProcess.equals(this.beanFactory))) {
                                BeanDefinition bd = 
beanFactoryToProcess.getBeanDefinition(curName);
                                try {
                                        visitor.visitBeanDefinition(bd);
                                }
                                catch (Exception ex) {
                                        throw new 
BeanDefinitionStoreException(bd.getResourceDescription(), curName, 
ex.getMessage());
                                }
                        }
                }

                // New in Spring 2.5: resolve placeholders in alias target 
names and aliases as well.
                beanFactoryToProcess.resolveAliases(valueResolver);

                // New in Spring 3.0: resolve placeholders in embedded values 
such as annotation attributes.
                beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
        }

As you see new features completely got disabled.

What I actually did was the easiest solution of all:

        /**
         * @see 
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#processProperties(org.springframework.beans.factory.config.ConfigurableListableBeanFactory,
         *      java.util.Properties)
         */
        protected void processProperties( ConfigurableListableBeanFactory 
beanFactoryToProcess, Properties props ) throws BeansException {
                super.processProperties(        beanFactoryToProcess,
                                                                        new 
SettingsProperties( this.settings ) );
        }

and @Value works as expected. Still I am not aware if the original solution was a mistake or was thought out for some other use case.

If noone objects I'd like to commit my change.


--
Leszek Gawron                         http://www.mobilebox.pl/krs.html
CTO at MobileBox S.A.

Reply via email to