Usage of mule-module-jpa 1.2.0 with Hibernate in 3

2019-07-29 20:04发布

问题:

Could anyone point me to a working example of the mule-module-jpa suitable for Mule 3.4 CE?

I have looked high and low and spent the better part of a day trying to get a test running and am stuck trying to get a properly defined entityManagerFactory set inside a mule app.

I got excited when I saw the article here describing the modules features. http://blogs.mulesoft.org/getting-started-with-jpa-and-mule/ Unfortunately that article lacks any details about configuration of the module.

I next found the github repo for the module (https://github.com/mulesoft/mule-module-jpa) and followed the link to the "documentation" at https://github.com/mulesoft/mule-module-jpa. Again no details on the entityManager config. Also noticed that the maven info there seems to be out of date with what Studio will put in maven-mule-plugin for the 1.2.0 version of the mule-module-jpa that Studio will install via the mule update site.

I next looked at the test in the source for the mule-module-jpa at https://github.com/mulesoft/mule-module-jpa/tree/master/src/test/resources to see if I could cobble a solution.

Using that I have gotten Studio and/or maven to compile a small mule app using the module but it wont start giving a Caused by: java.lang.ClassNotFoundException: org.hibernate.ejb.HibernatePersistence with a root cause of Caused by: java.lang.NoClassDefFoundError: org/hibernate/ejb/HibernatePersistence

My maven deps do include the relevant Hibernate stuff and I do see the jars are included in the output dir when running under studio. But mule classloader doesnt seem to be able to find them...or I'm clueless about what's needed.

I have tried several combinations of Hibernate and Spring-orm versions and currently am using latest of each:

<spring.version>4.0.0.RELEASE</spring.version>
<hibernate.version>4.2.2.Final</hibernate.version>

The relevant parts of my pom look like:

<dependencies>
...
      <dependency>
        <groupId>org.mule.modules</groupId>
        <artifactId>mule-module-jpa</artifactId>
        <version>1.2.0</version>
    </dependency>
     <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>${hibernate.version}</version> 
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.version}</version>    
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator-annotation-processor</artifactId>
        <version>4.1.0.Final</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.26</version>
    </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
</dependencies>


<plugins>
...
<plugin>
                <groupId>org.mule.tools</groupId>
                <artifactId>maven-mule-plugin</artifactId>
                <version>1.9</version>
                <extensions>true</extensions>
                <configuration>
                    <copyToAppsDirectory>true</copyToAppsDirectory>
                <inclusions>
                        <inclusion>
                            <groupId>org.mule.modules</groupId>
                            <artifactId>mule-module-jpa</artifactId>
                        </inclusion>
                    </inclusions>
                </configuration>
            </plugin>
</plugins>

And my simple mule config looks like:

<?xml version="1.0" encoding="UTF-8"?>
<mule version="CE-3.4.0"
xmlns:http="http://www.mulesoft.org/schema/mule/http" 
xmlns:jpa="http://www.mulesoft.org/schema/mule/jpa" 
xmlns="http://www.mulesoft.org/schema/mule/core" 
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" 
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/jpa http://www.mulesoft.org/schema/mule/jpa/1.0/mule-jpa.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
">

      <spring:beans>
      <spring:bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <spring:property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <spring:property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <spring:property name="username" value="XXXX"/>
        <spring:property name="password" value="XXXX"/>
    </spring:bean>

    <spring:bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <spring:property name="dataSource" ref="datasource"/>
        <spring:property name="jpaVendorAdapter">
            <spring:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <spring:property name="showSql" value="true"/>
                <spring:property name="generateDdl" value="false"/>
                <spring:property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
            </spring:bean>
        </spring:property>
    </spring:bean>
    </spring:beans>

    <jpa:config name="Java_Persistence_API" entityManagerFactory-ref="entityManagerFactory" doc:name="Java Persistence API"/>

    <flow name="jpa_test2Flow1" doc:name="jpa_test2Flow1">
        <http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="query" doc:name="HTTP"/>
        <logger level="INFO" doc:name="Logger"/>
        <jpa:find config-ref="Java_Persistence_API" entityClass="domain.Dog" id-ref="#[message.payload.name]" doc:name="Java Persistence API"/>
    </flow>
</mule>

The complete exception I get is:

Exception in thread "main" org.mule.module.launcher.DeploymentInitException: ClassNotFoundException: org.hibernate.ejb.HibernatePersistence at org.mule.module.launcher.application.DefaultMuleApplication.init(DefaultMuleApplication.java:219) at org.mule.module.launcher.application.ApplicationWrapper.init(ApplicationWrapper.java:64) at org.mule.module.launcher.DefaultMuleDeployer.deploy(DefaultMuleDeployer.java:47) at org.mule.tooling.server.application.ApplicationDeployer.run(ApplicationDeployer.java:58) at org.mule.tooling.server.application.ApplicationDeployer.main(ApplicationDeployer.java:91) Caused by: org.mule.api.config.ConfigurationException: Error creating bean with name 'entityManagerFactory' defined in URL [file:/home/matthew/MuleStudio/workspace/.mule/apps/jpa_test2/jpa_test2.xml]: Cannot create inner bean 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#495b317b' of type [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter] while setting bean property 'jpaVendorAdapter'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#495b317b' defined in URL [file:/home/matthew/MuleStudio/workspace/.mule/apps/jpa_test2/jpa_test2.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/hibernate/ejb/HibernatePersistence (org.mule.api.lifecycle.InitialisationException) (org.mule.api.config.ConfigurationException) at org.mule.config.builders.AbstractConfigurationBuilder.configure(AbstractConfigurationBuilder.java:52) at org.mule.config.builders.AbstractResourceConfigurationBuilder.configure(AbstractResourceConfigurationBuilder.java:78) at org.mule.context.DefaultMuleContextFactory.createMuleContext(DefaultMuleContextFactory.java:84) at org.mule.module.launcher.application.DefaultMuleApplication.init(DefaultMuleApplication.java:207) ... 4 more Caused by: org.mule.api.config.ConfigurationException: Error creating bean with name 'entityManagerFactory' defined in URL [file:/home/matthew/MuleStudio/workspace/.mule/apps/jpa_test2/jpa_test2.xml]: Cannot create inner bean 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#495b317b' of type [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter] while setting bean property 'jpaVendorAdapter'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#495b317b' defined in URL [file:/home/matthew/MuleStudio/workspace/.mule/apps/jpa_test2/jpa_test2.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/hibernate/ejb/HibernatePersistence (org.mule.api.lifecycle.InitialisationException) at org.mule.config.builders.AbstractConfigurationBuilder.configure(AbstractConfigurationBuilder.java:52) at org.mule.config.builders.AbstractResourceConfigurationBuilder.configure(AbstractResourceConfigurationBuilder.java:78) at org.mule.config.builders.AutoConfigurationBuilder.autoConfigure(AutoConfigurationBuilder.java:101) at org.mule.config.builders.AutoConfigurationBuilder.doConfigure(AutoConfigurationBuilder.java:57) at org.mule.config.builders.AbstractConfigurationBuilder.configure(AbstractConfigurationBuilder.java:46) ... 7 more Caused by: org.mule.api.lifecycle.InitialisationException: Error creating bean with name 'entityManagerFactory' defined in URL [file:/home/matthew/MuleStudio/workspace/.mule/apps/jpa_test2/jpa_test2.xml]: Cannot create inner bean 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#495b317b' of type [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter] while setting bean property 'jpaVendorAdapter'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#495b317b' defined in URL [file:/home/matthew/MuleStudio/workspace/.mule/apps/jpa_test2/jpa_test2.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/hibernate/ejb/HibernatePersistence at org.mule.registry.AbstractRegistry.initialise(AbstractRegistry.java:117) at org.mule.config.spring.SpringXmlConfigurationBuilder.createSpringRegistry(SpringXmlConfigurationBuilder.java:119) at org.mule.config.spring.SpringXmlConfigurationBuilder.doConfigure(SpringXmlConfigurationBuilder.java:73) at org.mule.config.builders.AbstractConfigurationBuilder.configure(AbstractConfigurationBuilder.java:46) ... 11 more Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in URL [file:/home/matthew/MuleStudio/workspace/.mule/apps/jpa_test2/jpa_test2.xml]: Cannot create inner bean 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#495b317b' of type [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter] while setting bean property 'jpaVendorAdapter'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#495b317b' defined in URL [file:/home/matthew/MuleStudio/workspace/.mule/apps/jpa_test2/jpa_test2.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/hibernate/ejb/HibernatePersistence at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:282) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:121) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1391) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1132) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1117) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:922) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) at org.mule.config.spring.SpringRegistry.doInitialise(SpringRegistry.java:89) at org.mule.registry.AbstractRegistry.initialise(AbstractRegistry.java:109) ... 14 more Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#495b317b' defined in URL [file:/home/matthew/MuleStudio/workspace/.mule/apps/jpa_test2/jpa_test2.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/hibernate/ejb/HibernatePersistence at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1011) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:957) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461) at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:271) ... 28 more Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/hibernate/ejb/HibernatePersistence at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1004) ... 32 more Caused by: java.lang.NoClassDefFoundError: org/hibernate/ejb/HibernatePersistence at org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter.(HibernateJpaVendorAdapter.java:57) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:526) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148) ... 34 more Caused by: java.lang.ClassNotFoundException: org.hibernate.ejb.HibernatePersistence at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at org.mule.module.launcher.FineGrainedControlClassLoader.findClass(FineGrainedControlClassLoader.java:179) at org.mule.module.launcher.FineGrainedControlClassLoader.loadClass(FineGrainedControlClassLoader.java:123) at java.lang.ClassLoader.loadClass(ClassLoader.java:358) ... 40 more

I am starting to think that this module is not ready for usage despite it being available as a cloud connector from inside studio?

回答1:

just a thought, mule already includes some hibernate jars including hibernate-core and hibernate-jpa. the error may be caused due to a conflict. try to verify whether the class not found is already in one of these jars.

hth gabriel



回答2:

I have made some progress with this but dont yet have a suitable solution to use JPA in Mule.

The mule-module-jpa from Mulesoft (https://github.com/mulesoft/mule-module-jpa/) seems to assume some other version of Mule than 3.4.0 CE because the modules tests show dependencies on Hibernate 3.6.3 but Mule 3.4.0 already includes Hibernate Core 3.6.0. These two conflict.

I have found that it is possible to replace the Hibernate core in ../MuleStudio/plugins/org.mule.tooling.server.3.4.0_3.4.0.201311292125/mule/opt with Hibernate 4.2.8 and so long as it is run as via Maven build, Studio works fine with this module.

To make Studio stop complaining about missing deps on Hibernate 3.6.0, I also hacked the MANIFEST.MF and MULESOFT.SF files (at /MuleStudio/plugins/org.mule.tooling.server.3.4.0_3.4.0.201311292125/META-INF/) to reference Hibernate 4.2.8. The SHA-1 checksums therein are of no matter apparently as Studio and Mule CE run from it dont complain about the replacement.

After hacking my way around that I was excited to when I got some JPA queries running in Mule via annotated entities.

My elation was quickly crushed when I discovered that this mule-module-jpa 1.2.0 fails to commit JPA transactions on any flavor of persist or merge I threw at it and whether or not it was wrapped in a component.

I see that some other users have found this issue with EclipseLink as the provider as well. Configuring the Mule JPA module to use Eclipse Link and MySQL

It seems this module is not ready for use despite it being offered by Mulesoft as an available CloudConnector.

I really hope this project gets some attention from Mule. It seems so close to being ready.

There does seem to be an unofficial but identically named module from a 3rd party here: http://code.google.com/p/mule-transport-jpa/

I have confirmed that my exact same entityManager, persistenceProvider, and datasource setup works just fine with this 3rd party module. But this module seems to only support XA txns or none at all. That is, it wraps all of it's JPA transactions in it's own scope and doesnt seem to be able to Join any txn started by Mule's SingleResourceTransaction.

If you care about being able to use JPA in Mule please vote for this question and/or lobby Mulesoft for some fixes.



回答3:

Mule includes hibernate JARs at ${MULE_HOME}/lib/opt. It doesn't include hibernate-entitymanager.jar. So if you don't include it in your classpath, you will get ClassNotFound exception. If you do include it, it gives java.lang.IllegalAccessError because it conflicts with the mule provided hibernate core JARs.

So solution is to remove hibernate JARs at ${MULE_HOME}/lib/opt and add your own JAR versions. Do take a backup in case you make a mistake.

Update

You can try options like loader.override="comma-separated list of classes or packages" in mule-deploy.properties. If you mention a class or package, mule app classloader will override parent classloader. If you mention a class prepended with minus then this class/package will be blocked. Refer mule documentation for more details http://www.mulesoft.org/documentation/display/current/Classloader+Control+in+Mule#ClassloaderControlinMule-Fine-GrainedClassloadingControl