Announcement Announcement Module
Collapse
No announcement yet.
merging multiple persistence.xml is not working with JPA2.0 + Spring 3.0.5.RELEASE Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • merging multiple persistence.xml is not working with JPA2.0 + Spring 3.0.5.RELEASE

    Hello All,

    I have a requirement of using multiple persistence.xml file in more than one module (jars) inside a web application (war). I need to merge all the persistence.xml file with the same persistence context name and create and use the EntityManager out of them.

    I searched many places in google and found few links but couldn't found any working code example with JPA 2.0 + Spring 3.0.5.RELEASE + Hibernate 3.5.1.

    I am using below artifacts:
    All required spring dependencies with version 3.0.5.RELEASE

    Code:
      <dependency>
      			<groupId>org.hibernate.javax.persistence</groupId>
      			<artifactId>hibernate-jpa-2.0-api</artifactId>
     			<version>1.0.0.Final</version>
    		</dependency>
    		<dependency>
    			<groupId>org.hibernate</groupId>
    			<artifactId>hibernate-entitymanager</artifactId>
    			<version>3.6.7.Final</version>
    		</dependency>
    		<dependency>
    			<groupId>org.hibernate</groupId>
    			<artifactId>hibernate-core</artifactId>
    			<version>3.6.7.Final</version>
    		</dependency>
    		<dependency>
          		<groupId>org.hibernate</groupId>
          		<artifactId>hibernate-validator</artifactId>
          		<version>4.1.0.Final</version>
        	</dependency>
    		<dependency>
    			<groupId>org.hibernate</groupId>
    			<artifactId>hibernate-annotations</artifactId>
    			<version>3.5.6-Final</version>
    		</dependency>
    Below are the spring and java code details am using:

    spring applicationContext.xml

    Code:
    <bean id="entityManagerFactory"
    		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    		<property name="persistenceUnitManager" ref="mergedPersistenceUnitManager" />
                              <!-- other details are excluded-->... ... ...
    	</bean>
    	<bean id="mergedPersistenceUnitManager"
    		class="com.package.name.MergePersistenceUnitManager">
    		<property name="persistenceXmlLocations">
    			<list>
    				<value>classpath*:META-INF/persistence.xml</value>			</list>
    		</property>
    		<property name="defaultDataSource" ref="dataSource" />
    	</bean>
    MergePersistenceUnitManager.java
    from https://github.com/SpringSource/spri...itManager.java
    Code:
    public class MergePersistenceUnitManager  extends DefaultPersistenceUnitManager {
        @Override
        protected void postProcessPersistenceUnitInfo(final MutablePersistenceUnitInfo mutablePersistenceUnitInfo) {
            super.postProcessPersistenceUnitInfo(mutablePersistenceUnitInfo);
            final PersistenceUnitInfo oldPersistenceUnitInfo = 
            	getPersistenceUnitInfo(mutablePersistenceUnitInfo.getPersistenceUnitName());
            if (oldPersistenceUnitInfo != null) {
                for (URL url : oldPersistenceUnitInfo.getJarFileUrls()) {
                    if (!mutablePersistenceUnitInfo.getJarFileUrls().contains(url)) {
                    	mutablePersistenceUnitInfo.addJarFileUrl(url);
                    }
                }
                mutablePersistenceUnitInfo.addJarFileUrl(oldPersistenceUnitInfo.getPersistenceUnitRootUrl());
            }
        }
    }
    MergePersistenceUnitManager.java
    from https://dev.c-ware.de/confluence/dis...le+application

    Code:
    public class MergePersistenceUnitManager  extends DefaultPersistenceUnitManager {
        @Override
    	protected void postProcessPersistenceUnitInfo(final MutablePersistenceUnitInfo newPU) {
    		super.postProcessPersistenceUnitInfo(newPU);
    		final URL persistenceUnitRootUrl = newPU.getPersistenceUnitRootUrl();
    		newPU.addJarFileUrl(persistenceUnitRootUrl);
    		final String persistenceUnitName = newPU.getPersistenceUnitName();
    		final MutablePersistenceUnitInfo oldPU = getPersistenceUnitInfo(persistenceUnitName);
    		if (oldPU != null) {
    			final List<URL> urls = oldPU.getJarFileUrls();
    			for (URL url : urls){
    				newPU.addJarFileUrl(url);
    			}
    				
    			final List<String> managedClassNames = oldPU.getManagedClassNames();
    			for (String managedClassName : managedClassNames){
    				newPU.addManagedClassName(managedClassName);
    			}
    				
    			final List<String> mappingFileNames = oldPU.getMappingFileNames();
    			for (String mappingFileName : mappingFileNames){
    				newPU.addMappingFileName(mappingFileName);
    			}
    				
    			final Properties oldProperties = oldPU.getProperties();
    			final Properties newProperties = newPU.getProperties();
    			newProperties.putAll(oldProperties);
    			newPU.setProperties(newProperties);
    		}
    	}
    }
    persitence.xml in module one (JAR-1) inside META-INF
    Code:
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
    	<persistence-unit name="PUUnit" transaction-type="RESOURCE_LOCAL">				
    	<provider>org.hibernate.ejb.HibernatePersistence</provider>  
    		<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>		
    		<class>com.package.name.UserEntity</class>
    		 <exclude-unlisted-classes/> 
    		 <properties>
                                ... ... ... ....
             </properties>
    </persistence-unit>
    </persistence>
    persitence.xml in module one (JAR-2) inside META-INF
    Code:
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
    	<persistence-unit name="PUUnit" transaction-type="RESOURCE_LOCAL">				
    	<provider>org.hibernate.ejb.HibernatePersistence</provider>  
    		<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>	
    		<class>com.package.name.Employee</class>
    		<class>com.package.name.Department</class>
    		 <exclude-unlisted-classes/> 
    		 <properties>
                                ... ... ... ....
             </properties>
    	</persistence-unit>
    </persistence>
    When I am running this setup either from Junit or by deployement I am getting below error, it seems problem with Hibernate API while parsing multiple persistence.xml.
    Caused by: org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'entityManagerFactory' defined in class path resource [applicationContext-test.xml]: Invocation of init method failed; nested exception is java.lang.RuntimeException: error trying to scan <jar-file>: file:/D:/ProjectWorks/jpa_project/trunk/target/test-classes/
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.initializeBean(Abstract AutowireCapableBeanFactory.java:1420)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.doCreateBean
    ......
    Caused by: java.lang.RuntimeException: error trying to scan <jar-file>: file:/D:/ProjectWorks/DisneySvn/rti/framework/persistence/trunk/target/test-classes/
    at org.hibernate.ejb.Ejb3Configuration.scanForClasses (Ejb3Configuration.java:854)
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3 Configuration.java:594)
    at org.hibernate.ejb.HibernatePersistence.createConta inerEntityManagerFactory(HibernatePersistence.java :73)
    at org.springframework.orm.jpa.LocalContainerEntityMa nagerFactoryBean.createNativeEntityManagerFactory( LocalContainerEntityManagerFactoryBean.java:225)
    at org.springframework.orm.jpa.AbstractEntityManagerF actoryBean.afterPropertiesSet
    .....
    Could anyone please help me out on this with any working code examples. I am stuck with this issue and it's a show stopper for my project.

    Many thanks in advance.
    Last edited by ajitamitav; Nov 3rd, 2011, 02:58 AM.

  • #2
    stack trace details

    Placing full stack trace as again as I was unable to post it completely last time.

    Code:
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [applicationContext-test.xml]: Invocation of init method failed; nested exception is java.lang.RuntimeException: error trying to scan <jar-file>: file:/D:/ProjectWorks/jpa_project/trunk/target/test-classes/
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
    	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84)
    	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
    	at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
    	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
    	... 30 more
    Caused by: java.lang.RuntimeException: error trying to scan <jar-file>: file:/D:/ProjectWorks/jpa_project/trunk/target/test-classes/
    	at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:854)
    	at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:594)
    	at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73)
    	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225)
    	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:308)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
    	... 43 more
    Caused by: org.hibernate.AssertionFailure: Cannot read files twice on NativeScanner
    	at org.hibernate.ejb.packaging.NativeScanner.getFilesInJar(NativeScanner.java:168)
    	at org.hibernate.ejb.Ejb3Configuration.addScannedEntries(Ejb3Configuration.java:497)
    	at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:851)
    	... 49 more
    Root cause stack trace is as below:

    Code:
    2011-11-02 00:53:21.125 |ERROR| org.hibernate.AssertionFailure                                         | an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
    org.hibernate.AssertionFailure: Cannot read files twice on NativeScanner
    	at org.hibernate.ejb.packaging.NativeScanner.getFilesInJar(NativeScanner.java:168)
    	at org.hibernate.ejb.Ejb3Configuration.addScannedEntries(Ejb3Configuration.java:497)
    	at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:851)
    	at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:594)
    	at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73)
    	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225)
    	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:308)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
    	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84)
    	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
    	at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
    	at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
    	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
    	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
    	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
    	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
    	at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:59)
    	at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:120)
    	at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:103)
    	at org.apache.maven.surefire.Surefire.run(Surefire.java:169)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:597)
    	at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350)
    	at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021)
    Last edited by ajitamitav; Nov 3rd, 2011, 03:00 AM.

    Comment


    • #3
      I found a fix for this, I don't know in detail what it's doing behind the sceen, but anyway just by setting the persistenceUnitRootUrl to NULL it worked for me.

      Code:
      public class MergePersistenceUnitManager  extends DefaultPersistenceUnitManager {
          @Override
      	protected void postProcessPersistenceUnitInfo(final MutablePersistenceUnitInfo newPU) {
      		super.postProcessPersistenceUnitInfo(newPU);
      		final URL persistenceUnitRootUrl = newPU.getPersistenceUnitRootUrl();
      		newPU.addJarFileUrl(persistenceUnitRootUrl);
                                newPU.setPersistenceUnitRootUrl(null)
      		final String persistenceUnitName = newPU.getPersistenceUnitName();
      		final MutablePersistenceUnitInfo oldPU = getPersistenceUnitInfo(persistenceUnitName);
      		if (oldPU != null) {
      			final List<URL> urls = oldPU.getJarFileUrls();
      			for (URL url : urls){
      				newPU.addJarFileUrl(url);
      			}
      				
      			final List<String> managedClassNames = oldPU.getManagedClassNames();
      			for (String managedClassName : managedClassNames){
      				newPU.addManagedClassName(managedClassName);
      			}
      				
      			final List<String> mappingFileNames = oldPU.getMappingFileNames();
      			for (String mappingFileName : mappingFileNames){
      				newPU.addMappingFileName(mappingFileName);
      			}
      				
      			final Properties oldProperties = oldPU.getProperties();
      			final Properties newProperties = newPU.getProperties();
      			newProperties.putAll(oldProperties);
      			newPU.setProperties(newProperties);
      		}
      	}
      }
      Can anyone please help me understanding this.

      Comment


      • #4
        merging multiple persistence.xml is not working Spring 3.1

        I have same requirement of using multiple persistence.xml file in more than one module (jars) inside a web application (war). I need to merge all the persistence.xml file with the same persistence context name("default") and create and use the EntityManager out of them. I used 'MergePersistenceUnitManager.java' code. It was working for spring 2, but not working for spring 3.1

        It gives error - "Conflicting persistence unit definitions for name 'default'"

        This issue is caused because of code change for 'DefaultPersistenceUnitManager.java' in springframework 3.1 ie.

        if (!this.persistenceUnitInfoNames.add(name)) {
        StringBuilder msg = new StringBuilder();
        msg.append("Conflicting persistence unit definitions for name '").append(name).append("': ");
        msg.append(pui.getPersistenceUnitRootUrl()).append (", ");
        msg.append(this.persistenceUnitInfos.get(name).get PersistenceUnitRootUrl());
        throw new IllegalStateException(msg.toString());
        }


        Please help me to solve this issue.

        Comment


        • #5
          I tried to get this to work as well, and got past your issue by subclassing org.springframework.orm.jpa.persistenceunit.Defaul tPersistenceUnitManager:
          Code:
          /**
          	 * Return whether an override of a same-named persistence unit is allowed.
          	 * <p>Default is <code>false</code>. May be overridden to return <code>true</code>,
          	 * for example if {@link #postProcessPersistenceUnitInfo} is able to handle that case.
          	 */
          	protected boolean isPersistenceUnitOverrideAllowed() {
          		return false;
          	}
          Override the method above and make it return true. However, I still run into problems, so if anyone have a clue whether this is still possible, please give me a hint.

          Comment


          • #6
            Can you not use the MergingPersistenceUnitManager from the Spring-data-jpa project which will merge the persistence units?
            it is out of the box

            Comment

            Working...
            X