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