Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure TransactionManager programmatically

I'm having an application here based on Spring MVC. My workmate (btw he's not here) configured it programmatically and everything seems to work, except for the TransactionManager. I have never configured a Spring web application like this and I have no clue what to do and also can not find any documentation about how to configure a webapplication like this.

I'll just show you the 'AppInitializer' and the 'EntityManagerConfig'.

AppInitializer:

public class AppInitializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    AnnotationConfigWebApplicationContext context;
    ServletRegistration.Dynamic dispatcherServletRegistration;
    FilterRegistration.Dynamic encodingFilterRegistration, compressionFilterRegistration;
    Set<SessionTrackingMode> sessionTrackingModes = new HashSet<SessionTrackingMode>();

    sessionTrackingModes.add(SessionTrackingMode.SSL);

    context = new AnnotationConfigWebApplicationContext();
    context.setServletContext(servletContext);
    context.scan("de.devbliss.doc");

    servletContext.addListener(new ContextLoaderListener(context));
    servletContext.addListener(new Log4jConfigListener());

    dispatcherServletRegistration = servletContext.addServlet("main", new DispatcherServlet(context));
    dispatcherServletRegistration.setLoadOnStartup(1);
    dispatcherServletRegistration.addMapping("/*");

    encodingFilterRegistration = servletContext.addFilter("encodingFilter", CharacterEncodingFilter.class);
    encodingFilterRegistration.setInitParameter("encoding", "UTF-8");
    encodingFilterRegistration.setInitParameter("forceEncoding", "true");
    encodingFilterRegistration.addMappingForUrlPatterns(null, false, "/*");

    compressionFilterRegistration = servletContext.addFilter("compressionFilter", GzipFilter.class);
    compressionFilterRegistration.addMappingForUrlPatterns(null, false, "/*");

    compressionFilterRegistration = servletContext.addFilter("springSecurityFilterChain",
            DelegatingFilterProxy.class);
    compressionFilterRegistration.addMappingForUrlPatterns(null, false, "/*");

    servletContext.setSessionTrackingModes(sessionTrackingModes);
}
}

EntityManagerConfig:

@Configuration
@PropertySource("classpath:/db.properties")
public class EntityManagerConfig {

@Bean
public DataSource dataSource(Environment env) {
    BasicDataSource ds = new BasicDataSource();

    ds.setUrl(env.getProperty("url", "localhost"));
    ds.setUsername(env.getProperty("user", "blissdoc"));
    ds.setPassword(env.getProperty("password", "s3cret"));

    return ds;
}

@Bean
@Inject
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
    LocalSessionFactoryBean factory = new LocalSessionFactoryBean();

    factory.setDataSource(dataSource);

    return factory;
}

@Bean
public HibernateTransactionManager transactionManager(
        SessionFactory sessionFactory) {
    HibernateTransactionManager tm = new HibernateTransactionManager(
            sessionFactory);
    return tm;
}

@SuppressWarnings("unchecked")
@Bean
@Inject
public LocalContainerEntityManagerFactoryBean entityManager(
        DataSource dataSource, AbstractEnvironment env) {
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    HibernateJpaDialect jpaDialect = new HibernateJpaDialect();
    org.springframework.core.env.PropertySource<?> source;
    Iterator<org.springframework.core.env.PropertySource<?>> sources;

    // jpaVendorAdapter.setDatabase(Database.MYSQL);

    jpaVendorAdapter.setGenerateDdl(true);
    jpaVendorAdapter.setShowSql(true);

    Properties jpaProperties = new Properties();

    sources = env.getPropertySources().iterator();
    while (sources.hasNext()) {
        source = sources.next();
        if (source.getSource() instanceof Map) {
            for (Map.Entry<String, String> property : ((Map<String, String>) source
                    .getSource()).entrySet()) {
                jpaProperties.put(property.getKey(), property.getValue());
            }
        }
    }

    em.setJpaProperties(jpaProperties);

    em.setDataSource(dataSource);
    em.setPersistenceUnitName("blissdoc-unit");
    em.setPackagesToScan("de.devbliss.doc.model");
    em.setJpaDialect(jpaDialect);
    em.setJpaVendorAdapter(jpaVendorAdapter);

    return em;
}

// @Bean
// @Inject
// public JpaTransactionManager jpaTransactionManager(
// EntityManagerFactory entityManagerFactory) {
// JpaTransactionManager tm = new JpaTransactionManager(
// entityManagerFactory);
// return tm;
// }

@Bean
@Inject
public JpaRepositoryFactory jpaRepositoryFactory(
        EntityManagerFactory entityManagerFactory) {
    JpaRepositoryFactory factory = new JpaRepositoryFactory(
            entityManagerFactory.createEntityManager());
    return factory;
}

@Bean
@Inject
public UserRepository userRepository(
        JpaRepositoryFactory jpaRepositoryFactory) {
    return jpaRepositoryFactory.getRepository(UserRepository.class);
}

@Bean
@Inject
public ProjectRepository projectRepository(
        JpaRepositoryFactory jpaRepositoryFactory) {
    return jpaRepositoryFactory.getRepository(ProjectRepository.class);
}
}

--- Update PersistenceJPAConfig (former EntityManagerConfig):

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:/db.properties")
public class PersistenceJPAConfig {

@Inject
private Environment env;

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
    LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(dataSource());
    factoryBean.setPackagesToScan(new String[] { "de.devbliss.doc" });
    JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter() {
        {
            // JPA properties
        }
    };
    factoryBean.setJpaVendorAdapter(vendorAdapter);

    return factoryBean;
}

@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setUrl(env.getProperty("url", "localhost"));
    dataSource.setUsername(env.getProperty("user", "blissdoc"));
    dataSource.setPassword(env.getProperty("password", "s3cret"));
    return dataSource;
}

@Bean
public PlatformTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactoryBean()
            .getObject());

    return transactionManager;
}

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
}
}
like image 599
dwalldorf Avatar asked Oct 19 '12 09:10

dwalldorf


2 Answers

@Configuration-specific counterparts of custom XML elements such as <tx:annotation-driven> are @Enable... annotations.

In order to enable support for @Transactional you need to annotate your @Configuration class with @EnableTransactionManagement:

@Configuration 
@PropertySource("classpath:/db.properties") 
@EnableTransactionManagement
public class EntityManagerConfig { ... }

See also:

  • @EnableTransactionManagement
  • Spring 3.1 M2: Configuration Enhancements
like image 116
axtavt Avatar answered Nov 19 '22 10:11

axtavt


Have you tried to extend from TransactionManagementConfigurer?

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:/db.properties")
public class EntityManagerConfig implements TransactionManagementConfigurer {

    ...

    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return transactionManager();
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager(entityManagerFactory());
        transactionManager.setDataSource(dataSource);
        transactionManager.setJpaDialect(new HibernateJpaDialect());
        return transactionManager;
    }

    ...
}

And seems like you are using Spring Data JPA, so I recommend you to use also @EnableJpaRepositories("com.your.repositories.package") to automatically configure your Spring Data Repositories.

Hope this helps :)

like image 32
jelies Avatar answered Nov 19 '22 09:11

jelies