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}