    001// Copyright 2008-2013 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007//     http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.spring.modules;
    016
    017import org.apache.tapestry5.commons.MappedConfiguration;
    018import org.apache.tapestry5.commons.OrderedConfiguration;
    019import org.apache.tapestry5.http.services.ApplicationInitializer;
    020import org.apache.tapestry5.http.services.ApplicationInitializerFilter;
    021import org.apache.tapestry5.http.services.Context;
    022import org.apache.tapestry5.internal.spring.SymbolBeanFactoryPostProcessor;
    023import org.apache.tapestry5.ioc.annotations.Contribute;
    024import org.apache.tapestry5.ioc.annotations.ImportModule;
    025import org.apache.tapestry5.ioc.annotations.Marker;
    026import org.apache.tapestry5.ioc.annotations.Primary;
    027import org.apache.tapestry5.ioc.services.ChainBuilder;
    028import org.apache.tapestry5.ioc.services.FactoryDefaults;
    029import org.apache.tapestry5.ioc.services.SymbolProvider;
    030import org.apache.tapestry5.ioc.services.SymbolSource;
    031import org.apache.tapestry5.modules.TapestryModule;
    032import org.apache.tapestry5.spring.ApplicationContextCustomizer;
    033import org.apache.tapestry5.spring.SpringConstants;
    034import org.slf4j.Logger;
    035import org.springframework.context.ApplicationContext;
    036import org.springframework.core.SpringVersion;
    037import org.springframework.web.context.ConfigurableWebApplicationContext;
    038
    039import javax.servlet.ServletContext;
    040import java.util.List;
    041
    042/**
    043 * Module for Tapestry/Spring Integration. This module exists to force the load of the Spring ApplicationContext as part
    044 * of Tapestry application initialization.
    045 *
    046 * @since 5.1.0.0
    047 */
    048@ImportModule(TapestryModule.class)
    049public class SpringModule
    050{
    051    private final Logger logger;
    052
    053    public SpringModule(Logger logger)
    054    {
    055        this.logger = logger;
    056    }
    057
    058    @Contribute(ApplicationInitializer.class)
    059    @Primary
    060    public void reportSpringContextDetailsAtStartup(
    061            OrderedConfiguration<ApplicationInitializerFilter> configuration, final ApplicationContext springContext)
    062    {
    063        ApplicationInitializerFilter filter = new ApplicationInitializerFilter()
    064        {
    065            @Override
    066            public void initializeApplication(Context context, ApplicationInitializer initializer)
    067            {
    068                logger.info(String.format("Spring version %s with %,d defined beans.",
    069                        SpringVersion.getVersion(),
    070                        springContext.getBeanDefinitionCount()));
    071
    072                initializer.initializeApplication(context);
    073            }
    074        };
    075
    076        configuration.add("SpringContextInitialization", filter);
    077    }
    078
    079    @Contribute(SymbolProvider.class)
    080    @FactoryDefaults
    081    public static void defaultExternalSpringContextOff(MappedConfiguration<String, Object> configuration)
    082    {
    083        configuration.add(SpringConstants.USE_EXTERNAL_SPRING_CONTEXT, false);
    084    }
    085
    086    /**
    087     * Defines a chain-of-command for handling application context customization. This allows the Spring context to be
    088     * configured before it is initially {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
    089     * refreshed}.
    090     */
    091    @Marker(Primary.class)
    092    public static ApplicationContextCustomizer buildApplicationContextCustomizer(
    093            List<ApplicationContextCustomizer> configuration,
    094            ChainBuilder builder)
    095    {
    096        return builder.build(ApplicationContextCustomizer.class, configuration);
    097    }
    098
    099    @Contribute(ApplicationContextCustomizer.class)
    100    public static void addSymbolSourceAsPropertyCustomizerForSpringBeans(
    101            OrderedConfiguration<ApplicationContextCustomizer> configuration,
    102            final SymbolSource symbolSource)
    103    {
    104        ApplicationContextCustomizer beanFactoryPostProcessorCustomizer = new ApplicationContextCustomizer()
    105        {
    106
    107            @Override
    108            public void customizeApplicationContext(ServletContext servletContext,
    109                                                    ConfigurableWebApplicationContext applicationContext)
    110            {
    111                applicationContext.addBeanFactoryPostProcessor(new SymbolBeanFactoryPostProcessor(symbolSource));
    112
    113            }
    114        };
    115
    116        configuration.add("BeanFactoryPostProcessorCustomizer", beanFactoryPostProcessorCustomizer);
    117    }
    118}