001 // Copyright 2008, 2009, 2011 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 015 package org.apache.tapestry5.spring; 016 017 import org.apache.tapestry5.internal.spring.SymbolBeanFactoryPostProcessor; 018 import org.apache.tapestry5.ioc.MappedConfiguration; 019 import org.apache.tapestry5.ioc.OrderedConfiguration; 020 import org.apache.tapestry5.ioc.annotations.Contribute; 021 import org.apache.tapestry5.ioc.annotations.Marker; 022 import org.apache.tapestry5.ioc.annotations.Primary; 023 import org.apache.tapestry5.ioc.services.ChainBuilder; 024 import org.apache.tapestry5.ioc.services.FactoryDefaults; 025 import org.apache.tapestry5.ioc.services.SymbolProvider; 026 import org.apache.tapestry5.ioc.services.SymbolSource; 027 import org.apache.tapestry5.services.ApplicationInitializer; 028 import org.apache.tapestry5.services.ApplicationInitializerFilter; 029 import org.apache.tapestry5.services.Context; 030 import org.slf4j.Logger; 031 import org.springframework.context.ApplicationContext; 032 import org.springframework.core.SpringVersion; 033 import org.springframework.web.context.ConfigurableWebApplicationContext; 034 035 import javax.servlet.ServletContext; 036 import java.util.List; 037 038 /** 039 * Module for Tapestry/Spring Integration. This module exists to force the load of the Spring ApplicationContext as part 040 * of Tapestry application initialization. 041 * 042 * @since 5.1.0.0 043 */ 044 public class SpringModule 045 { 046 private final Logger logger; 047 048 public SpringModule(Logger logger) 049 { 050 this.logger = logger; 051 } 052 053 @Contribute(ApplicationInitializer.class) 054 public void reportSpringContextDetailsAtStartup( 055 OrderedConfiguration<ApplicationInitializerFilter> configuration, final ApplicationContext springContext) 056 { 057 ApplicationInitializerFilter filter = new ApplicationInitializerFilter() 058 { 059 public void initializeApplication(Context context, ApplicationInitializer initializer) 060 { 061 logger.info(String.format("Spring version %s with %,d defined beans.", 062 SpringVersion.getVersion(), 063 springContext.getBeanDefinitionCount())); 064 065 initializer.initializeApplication(context); 066 } 067 }; 068 069 configuration.add("SpringContextInitialization", filter); 070 } 071 072 @Contribute(SymbolProvider.class) 073 @FactoryDefaults 074 public static void defaultExternalSpringContextOff(MappedConfiguration<String, Object> configuration) 075 { 076 configuration.add(SpringConstants.USE_EXTERNAL_SPRING_CONTEXT, false); 077 } 078 079 /** 080 * Defines a chain-of-command for handling application context customization. This allows the Spring context to be 081 * configured before it is initially {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh() 082 * refreshed}. 083 */ 084 @Marker(Primary.class) 085 public static ApplicationContextCustomizer buildApplicationContextCustomizer( 086 List<ApplicationContextCustomizer> configuration, 087 ChainBuilder builder) 088 { 089 return builder.build(ApplicationContextCustomizer.class, configuration); 090 } 091 092 @Contribute(ApplicationContextCustomizer.class) 093 public static void addSymbolSourceAsPropertyCustomizerForSpringBeans( 094 OrderedConfiguration<ApplicationContextCustomizer> configuration, 095 final SymbolSource symbolSource) 096 { 097 ApplicationContextCustomizer beanFactoryPostProcessorCustomizer = new ApplicationContextCustomizer() 098 { 099 100 public void customizeApplicationContext(ServletContext servletContext, 101 ConfigurableWebApplicationContext applicationContext) 102 { 103 applicationContext.addBeanFactoryPostProcessor(new SymbolBeanFactoryPostProcessor(symbolSource)); 104 105 } 106 }; 107 108 configuration.add("BeanFactoryPostProcessorCustomizer", beanFactoryPostProcessorCustomizer); 109 } 110 }