Announcement Announcement Module
Collapse
No announcement yet.
Inject Datasource to JPA Persistence DAO Layer Programmatically Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Inject Datasource to JPA Persistence DAO Layer Programmatically

    I am using a DAO class that extends JpaDaoSupport. The datasource from JNDI tree is injected to ContainerEntityManagerFactoryBean and this is in turn injected to DAO class. I will get to know the JNDI name of the data source only at runtime. Is there any approach/suggestions to handle this scenario and still utilize all the dependency injections and spring based-transactions.

    In this scenario, the DAO layer beans will be prototype and all the logic in the same except that i should be able to select the JNDI programmatically at run time. Any suggestions / approach is appreciated.

    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
          xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                              http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                                              http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
          <bean id="transactionManager"
                class="org.springframework.transaction.jta.JtaTransactionManager">
                <property name="transactionManagerName" value="${transaction.jndi}" />
                <property name="userTransactionName" value="UserTransaction" />
          </bean>
    
          <!--
                Creates a EntityManagerFactory for use with the Hibernate JPA provider
          -->
          <bean id="entityManagerFactory"
                class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
                <property name="dataSource" ref="dataSource" />
                <property name="persistenceUnitName" value="${persistentUnitName}" />
                <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
                <property name="jpaVendorAdapter">
                      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                            <property name="databasePlatform" value="${hibernate.dialect}" />
                            <property name="showSql" value="true" />
                            <property name="generateDdl" value="false" />
                      </bean>
                </property>
          </bean>
     
          <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                <property name="jndiName" value="${database.jndi}" />
          </bean>
    
          <bean id="genericDAO" class="com.sample.dao.GenericDAOImpl">  
                <property name="entityManagerFactory" ref="entityManagerFactory"/>  
          </bean>
    
          <tx:annotation-driven proxy-target-class="true"
                transaction-manager="transactionManager" />
    </beans>

  • #2
    Use the search as that question has been answered a couple of times. In short you could use a AbstractDynamicRoutingDataSource (if you know all datasources up-front) or you could use something like this which is a more flexible than the ADRDS.

    Comment


    • #3
      Thanks Marten for your reply. In our case, the data sources are not known up-front. The JNDI of the various data sources are configured in the database and can be changed if required. Currently we have written a look-up kind of class to create that dao class with the data sources injected manually.

      Below is the code snippet.

      Code:
      @Component
      public class GenericDAOLookup {
      	
      	private Map<String, GenericDAO> genericDAOMap = new HashMap<String, GenericDAO>();
      
      	public GenericDAO lookupGenericDAO(String jndi) throws NamingException {
      		GenericDAO genericDAO;
      		
      		if(genericDAOMap.containsKey(jndi)) {
      			genericDAO = genericDAOMap.get(jndi);
      		} else {
      			genericDAO = new GenericDAOImpl();
      			JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
      			jndiObjectFactoryBean.setJndiName("java:" + jndi);
      			jndiObjectFactoryBean.afterPropertiesSet();
      			
      			HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
      			hibernateJpaVendorAdapter.setDatabasePlatform("com.hibernate.dialect.Oracle9iDialect");
      			hibernateJpaVendorAdapter.setShowSql(true);
      			hibernateJpaVendorAdapter.setGenerateDdl(false);
      			
      			LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
      			entityManagerFactory.setDataSource((DataSource) jndiObjectFactoryBean.getObject());
      			entityManagerFactory.setPersistenceUnitName("Sample");
      			entityManagerFactory.setPersistenceXmlLocation("classpath:META-INF/persistence.xml");
      			entityManagerFactory.setJpaVendorAdapter(hibernateJpaVendorAdapter);
      			entityManagerFactory.afterPropertiesSet();
      			
      			((GenericDAOImpl)genericDAO).setEntityManagerFactory(entityManagerFactory.getObject());
      			genericDAOMap.put(jndi, genericDAO);
      		}
      		return genericDAO;
      	}
      }
      I am unable to understand the second approach using ContextSwappableTargetSource. Will surely try it out and let you know.

      Comment


      • #4
        We basically used that approach to be able to deploy new customers without restarting the server. We had a naming convention and we simply put the static files for the web somewhere and created a new datasource in jndi and that was all that was needed to deploy a new customer. The code is on github here, I recently updated it for spring 3.

        The beauty of this solution is you don't need multiple dao's, entitymanagers etc.

        Comment

        Working...
        X