0

I am trying to have multiple persistence units with different databases in a Spring application, but without success so far. I have tried different scenarios, but no one has helped, so I will post some initial code that I think should work:

META/persistence.xml

<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence 
    http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/persistence/persistence_2_1.xsd">

     <persistence-unit name="DI-MAIN-PU" transaction-type="RESOURCE_LOCAL">
        <description>Persistence Unit for the MAIN DB (with Stores) </description>

        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <non-jta-data-source>java:comp/env/jdbc/diMainDb</non-jta-data-source>

        <class>com.mydomainimport.entity.main.CoreStore</class>
        <class>com.mydomainimport.entity.main.ImportResult</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <!-- <property name="javax.persistence.schema-generation.database.action" value="create"/> -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <!-- <property name="hibernate.hbm2ddl.auto" value="validate"/> -->
            <property name="hibernate.hbm2ddl.auto" value="update"/>

            <property name="hibernate.show_sql" value="true"/>


        </properties>
    </persistence-unit>



     <!-- jdbc/diStoreHvt -->
    <persistence-unit name="DI-storeHvt-PU" transaction-type="RESOURCE_LOCAL">
        <description>Persistence Unit for entities imported fromXML files</description>

        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <non-jta-data-source>java:comp/env/jdbc/diStoreHvt</non-jta-data-source>

        <class>com.mydomainimport.entity.ano.AnoCustomer</class>
        <class>com.mydomainimport.entity.CoreCustomer</class>
        <class>com.mydomainimport.entity.CoreState</class>
        <class>com.mydomainimport.entity.rev.RevInfo</class>

        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>

            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>

            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="true"/>

        </properties>
    </persistence-unit>

</persistence>

applicationContext.xml (spring-beans.xml)

<?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:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <!-- post-processors for all standard config annotations -->
    <context:annotation-config />
    <context:component-scan base-package="com.mydomain.import.service" />


    <bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
        <property name="defaultPersistenceUnitName" value="DI-MAIN-PU"/>

        <property name="persistenceXmlLocation" value="classpath*:META-INF/persistence*.xml"/>
    </bean>

    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="persistenceUnitManager" ref="pum"/>
    </bean>

    <bean id="importService" class="com.mydomain.import.service.ImportServiceImpl">
    </bean>


</beans>

ImportServiceImpl:

public class ImportServiceImpl implements ImportService {

    public static final String MAIN_PU_NAME = "DI-MAIN-PU";

    @PersistenceContext(unitName=MAIN_PU_NAME)
    private EntityManager mainEm;

    @Override
    public EntityManager getStoreEntityManager(Integer storeId) {

        String puName = "DI-storeHvt-PU";

        EntityManagerFactory emf = Persistence.createEntityManagerFactory(puName);
        return emf.createEntityManager();
    }

}

The exception that I get from the JUnit test is:

javax.persistence.PersistenceException: Unable to build entity manager factory
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:83)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
    ................................................ 
Caused by: org.hibernate.engine.jndi.JndiException: Error parsing JNDI name [java:comp/env/jdbc/diStoreHvt]     
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:141)
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:112)
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.configure(DatasourceConnectionProviderImpl.java:115)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(JdbcServicesImpl.java:260)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:94)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:397)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75)
    ... 35 more Caused by: 
javax.naming.OperationNotSupportedException: SimpleNamingContext does not support [javax.naming.Name]   
    at org.springframework.mock.jndi.SimpleNamingContext.getNameParser(SimpleNamingContext.java:259)
    at javax.naming.InitialContext.getNameParser(InitialContext.java:499)
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:135)
    ... 52 more

If I try to deploy the same code on Tomcat, I get the following:

javax.persistence.PersistenceException: Unable to build entity manager factory  
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:83)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
    at com.domain.import.service.store.StoreServiceImpl.getStoreEntityManager(StoreServiceImpl.java:35)
    at com.domain.import.service.ImportServiceImpl.processCustomerXmlFile(ImportServiceImpl.java:194)
    at com.domain.import.service.scheduler.SchedulerServiceImpl.updateFromAno(SchedulerServiceImpl.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)     
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)     
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745) Caused by:
org.hibernate.engine.jndi.JndiException: Unable to lookup JNDI name [java:comp/env/jdbc/diStoreHvt]     
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:117)
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.configure(DatasourceConnectionProviderImpl.java:115)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(JdbcServicesImpl.java:260)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:94)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:397)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75)
    ... 20 more Caused by: 
javax.naming.NameNotFoundException: Name [java:comp/env/jdbc/diStoreHvt] is not bound in this Context. Unable to find [java:comp].  
    at org.apache.naming.NamingContext.lookup(NamingContext.java:819)   
    at org.apache.naming.NamingContext.lookup(NamingContext.java:153)   
    at javax.naming.InitialContext.lookup(InitialContext.java:415)  
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:114)
    ... 36 more

I want a solution using JNDI (I do not want to save passwords in my code) and with persistence.xml, as this is the JPA standard. Also there will come more persistence units like the second one. I use Spring 3.2.3-Final.

Tuna
  • 2,937
  • 4
  • 37
  • 61
V G
  • 18,822
  • 6
  • 51
  • 89
  • Make sure that the datasource is available in JNDI under that name. For a unit test you will need to register them yourself, you can use the `SimpleNamingContextBuilder` to setup a JNDI tree for testing. – M. Deinum Jun 02 '14 at 10:43
  • @M.Deinum thanks for your comment. Exactly that is what I do: for my unit test I register two DataSources and when deploying in Tomcat the JNDI name is for sure there (otherwise another exception occurs earlier). Very strange is the part of the exception from Tomcat: `javax.naming.NameNotFoundException: Name [java:comp/env/jdbc/diStoreHvt] is not bound in this Context. Unable to find [java:comp]`, as `java:comp` is used also as prefix for the other EntityManager, that works. – V G Jun 02 '14 at 12:21
  • Post your test code. Also make sure that in yuor web.xml the jndi mappings are there (not sure if a global lookup works from within hibernate). – M. Deinum Jun 02 '14 at 12:22
  • Very interesting idea with `web.xml`: I will try it. I will post the test code later (do not have access to it). – V G Jun 02 '14 at 12:24

0 Answers0