Reputation: 3249
I'm developing a portlet which runs in WebSphere Application Server ( - I accept the same problem to appear if it was a servlet instead of a portlet). At the moment it depends on Hibernate. As WAS provides a JPA implementation itself, which is a modified version of OpenJPA 2.0, I want to get rid of Hibernate.
This is my setup. persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
>
<persistence-unit name="default" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/myDb</jta-data-source>
<properties>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect" />
</properties>
</persistence-unit>
</persistence>
myPortlet-portlet.xml
<!-- ... -->
<tx:jta-transaction-manager />
<jee:jndi-lookup jndi-name="jdbc/myDb" cache="true" id="dataSource" expected-type="javax.sql.DataSource" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="default" />
</bean>
In my DAO-classes I access the entityManager by using annotations:
@PersistenceContext(unitName = "default")
private EntityManager entityManager;
Everything works fine using Hibernate.
According to WebSphere Application Server docs, the default persistence provider is used if you don't specify it by using the <provider/>
-tag in persistence.xml. But after commenting out the provider specification, Spring throws an exception due not being able to find the provider-class:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in PortletContext resource [/WEB-INF/myPortlet-portlet.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No PersistenceProvider specified in EntityManagerFactory configuration, and chosen PersistenceUnitInfo does not specify a provider class name either
How can I use the provided JPA implementation together with Spring (Portlet) MVC?
Upvotes: 3
Views: 1228
Reputation: 3249
Short answer
You cannot use WebSphere's default provider by omitting the provider, if you want to use LocalContainerEntityManagerFactoryBean.
Long answer
Normally an entity manager is created by an entity manager factory provided by the container. You retrieve it by doing a context loopkup (EntityManager em = (EntityManager) ctx.lookup(...)
) manually or use Springs jndi-lookup capability:
<beans>
<jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/>
</beans>
In the question, a different approach is used, a LocalContainerEntityManagerFactoryBean, which creates an entity manager factory itself. This entity manager factory is a proxy that implements all the interfaces of the native entity manager factory. For creating such a proxy, Spring must know the class of the native entity manager factory. Spring uses three different ways to determine the class:
<provider/>
-entry in persistence.xmlAnd that's why you cannot completely omit the specification of your provider.
Upvotes: 2
Reputation: 16736
This is most likely happening because the Spring JAR(s) that you include with your application contains a different implementation of the Persistence
class, or other JPA classes, used to "bootstrap" JPA.
If you'd like to use WebSphere's default provider (or, more precisely, to use whichever JPA provide configured through WebSphere's administration screens), then you must ensure that the JPA "bootstrapping" code being called during runtime is WebSphere's, not yours.
You should look for a Spring distribution JAR that doesn't mess with JPA.
Upvotes: 0