Java tutorial
package com.miserablemind.butter.bootstrap; import com.miserablemind.butter.bootstrap.config.ConfigJDBC; import com.miserablemind.butter.bootstrap.config.ConfigMail; import com.miserablemind.butter.bootstrap.config.ConfigSystem; import org.apache.commons.dbcp.BasicDataSource; import org.apache.velocity.app.VelocityEngine; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.cache.ehcache.EhCacheManagerFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Controller; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.ui.velocity.VelocityEngineFactory; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import java.io.IOException; import java.util.Properties; /* * Miserable Mind * http://www.butter.miserablemind.com * The MIT License (MIT) */ /** * Root System Context that oversees all Root Context Beans such as data source, * e-mail sender, caching, transactions and all the service layer. * * @author <a href="http://www.miserablemind.com" target="_blank">miserablemind</a> */ @Configuration @EnableTransactionManagement @EnableCaching @EnableAsync // use @Async to execute method in a different thread @ComponentScan(basePackages = { "com.miserablemind.butter" }, excludeFilters = @ComponentScan.Filter(value = { Controller.class, EnableWebMvc.class }, type = FilterType.ANNOTATION)) public class RootContext { @Autowired private ConfigSystem configSystem; /** * Data Source Bean that is configured for JDBC connection using {@link ConfigJDBC}. * * @return {@link BasicDataSource} bean with a name {@code dataSource}. */ @Bean(name = "dataSource") public BasicDataSource dataSource() { ConfigJDBC configJDBC = this.configSystem.getConfigJDBC(); BasicDataSource dataSource = new BasicDataSource(); dataSource.setUsername(configJDBC.getJdbcUsername()); dataSource.setPassword(configJDBC.getJdbcPassword()); dataSource.setUrl(configJDBC.getJdbcUrl()); dataSource.setDriverClassName(configJDBC.getJdbcDriverClassName()); return dataSource; } /** * Password Encoder bean that can be wired to any other bean to encode or compare encoded passwords. * * @return {@link BCryptPasswordEncoder} instance. */ @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } /** * E-mail Sender configured using {@link ConfigMail}. * * @return {@link JavaMailSender} bean. */ @Bean public JavaMailSender emailSender() { ConfigMail configMail = configSystem.getConfigMail(); JavaMailSenderImpl emailSender = new JavaMailSenderImpl(); emailSender.setHost(configMail.getHost()); emailSender.setUsername(configMail.getUsername()); emailSender.setPassword(configMail.getPassword()); emailSender.setPort(configMail.getPort()); Properties props = new Properties(); props.put("mail.smtp.auth", configMail.isSmtpAuth()); props.put("mail.smtp.starttls.enable", configMail.isStartTls()); props.put("mail.transport.protocol", configMail.getProtocol()); props.put("mail.smtp.socketFactory.class", configMail.getSocketFactoryClass()); props.put("mail.smtp.socketFactory.fallback", configMail.isSocketFactoryFallback()); emailSender.setJavaMailProperties(props); return emailSender; } /** * Velocity template engine bean for e-mail templates. * * @return {@link VelocityEngine} bean. */ @Bean public VelocityEngine velocityEngine() throws IOException { VelocityEngineFactory factory = new VelocityEngineFactory(); Properties props = new Properties(); props.put("resource.loader", "file"); props.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader"); props.put("file.resource.loader.path", this.configSystem.getWebAppRoot() + "/WEB-INF/emailTemplates"); factory.setVelocityProperties(props); return factory.createVelocityEngine(); } /** * Transaction Manager bean. * In order to use transactions in {@link BasicDataSource}, the methods have to be annotated @Transactional. * The annotation should be used on implementations of service layer methods rather than interfaces. * For MySQL transactions to work database tables have to use InnoDB engine. * * @return {@link DataSourceTransactionManager} bean. */ @Bean public PlatformTransactionManager txManager() { return new DataSourceTransactionManager(dataSource()); } /** * PropertyPlaceholderConfigurer is required to make {@code @Value} annotations work. * {@code @Value} annotations are used to wire data from .properties files. * * @return {@link PropertyPlaceholderConfigurer}. */ @Bean public static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() { PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer(); Resource[] propertiesFiles = new Resource[] { new ClassPathResource("system.properties"), new ClassPathResource("butterApp/butterApp.properties") }; configurer.setLocations(propertiesFiles); return configurer; } /** * Cache Manager Factory Bean that is used to initialise {@link CacheManager} bean. * In this case it is {@link EhCacheManagerFactoryBean}. * It wires configuration from ehcache.xml that resides in resources directory. * * @return {@link EhCacheManagerFactoryBean}. */ @Bean public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() { EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean(); ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); return ehCacheManagerFactoryBean; } /** * Cache Manager Bean. In this case it is EHCache. * {@code @Cacheable} annotations should be used on DAO or Manager Implementation Beans (not interfaces). * * @return CacheManager bean. */ @Bean public CacheManager cacheManager() { EhCacheCacheManager cacheManager = new EhCacheCacheManager(); cacheManager.setCacheManager(this.ehCacheManagerFactoryBean().getObject()); return cacheManager; } }