com.miserablemind.butter.bootstrap.RootContext.java Source code

Java tutorial

Introduction

Here is the source code for com.miserablemind.butter.bootstrap.RootContext.java

Source

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;
    }

}