Doubt regarding JPA management with Spring on JEE server

3

I'm starting in Spring MVC and in the book I'm reading the configuration and management of connections is all done by Spring, that is, Spring opens and manages the connections with the bank and makes this available as if I had a JEE server (% with% and% with%).

The question is that this is all done in a web container like tomcat or jetty, my question is how to manage this issue on a full JEE server like Wildfly, because I want the connection to be created by Wildfly ( Datasource created in wildfly) and not by Spring

How does this integration work, I do not do any Spring connection setup and leave it to the server alone, or do I have to set something up in Spring so that it can get the datasource created by wildfly and it (spring) do the management? My doubt is also because there is a Spring filter that keeps the connections open throughout the request ( @PersistenceContext ) and how will it handle this if the connections are managed by the JEE (wildfly) server?

I'm using Spring 4.2 and configuring everything via annotations, here is an excerpt from the current configuration that works in a web container:

import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class JPAConfiguration {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan(new String[] { "br.com.casadocodigo.loja.models" });

        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());

        return em;
    }

    @Bean   
    public DataSource dataSource(Environment environment){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://192.168.56.200:3306/casadocodigo");
        dataSource.setUsername( "root" );
        dataSource.setPassword( "123456" );
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);     
        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
        return new PersistenceExceptionTranslationPostProcessor();
    }

    Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.show_sql", "true");
        return properties;
    }

}
    
asked by anonymous 13.12.2015 / 23:54

2 answers

1

It is possible to do the DataSource lookup with JNDI.

There are two ways to do it programatically.

public DataSource dataSource() {
    JndiDataSourceLookup lookup = new JndiDataSourceLookup();
    return lookup.getDataSource("jdni");
}

or

public DataSource dataSource() {
    DataSource ds = null;
    try {
        Context ctx = new InitialContext();
        ds = (DataSource) ctx.lookup("jdbc/nomeBanco");
    } catch (NamingException e) {
        e.printStackTrace();
    }
    return ds;
}

If you use JndiDataSourceLookup , take a look at the setResourceRef method, since the container is Java EE.

    
14.12.2015 / 00:26
1

If the container is managed by you data source , just change the way you retrieve data source .

Unlike using DriverManagerDataSource , which is a basic implementation of DataSource , you can retrieve the resource through the JNDI feature published by the container.

From your configuration, just change the implementation from JPAConfiguration#dataSource to something like this:

@Bean
public DataSource dataSource() throws NamingException {
    final JndiTemplate jndi = new JndiTemplate();
    return jndi.lookup("${jndi.ds.name}", DataSource.class);
}

Or so:

@Bean
public DataSource dataSource() throws DataSourceLookupFailureException {
    return new JndiDataSourceLookup().getDataSource("${jndi.ds.name}");
}

This second way is more elegant, since it encapsulates JndiTemplate for you, in addition to doing other discussions, such as trying other addresses in JNDI.

In XML it would look something like this:

<jee:jndi-lookup id="dataSource" jndi-name="${jndi.ds.name}" expected-type="javax.sql.DataSource" />

It's worth noting that your EntityManagerFactory can also be managed by Java EE container and not Spring, replacing LocalContainerEntityManagerFactoryBean .

In this case the setting will be slightly different from the one commonly used. Using configuration in Java, it would look like this:

@Bean
public EntityManagerFactory entityManagerFactory() throws NamingException {
    final JndiTemplate jndi = new JndiTemplate();
    return jndi.lookup("${jta.emf.jndi}", EntityManagerFactory.class);
}

@Bean
public TransactionFactory transactionManager(){
    return new JtaTransactionManager();
}

In XML it would look something like this:

<!-- referência da EMF na JNDI -->
<jee:jndi-lookup id="entityManagerFactory" jndi-name="${jta.emf.jndi}" expected-type="javax.persistence.EntityManagerFactory" />

<!-- você deve falar que agora é JTA -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

In the latter case, additional configuration may be required on the persistence unit and may break the servlet container / full jee container .

As for the OpenEntityManagerInViewFilter regardless of how spring gets a connection or if it is the one who manages the connections, this filter is not aware of this, if there is a bean in the context of Spring for EntityManagerFactory (default name of bean is entityManagerFactory ) - and this can be both managed by JNDI and managed by the container.

Lastly, if you configure your application to run in a container , you'll also be able to run it at any time in a jee container .

    
14.12.2015 / 00:34