I have a simple Java EE application that uses a stateless EJB, and a persistence object to perform a lookup on a table. I can deploy my application successfully to WebLogic 10.3 with Hibernate 4.2 and EJB 3.0 but when I run it I am getting an UnknownServiceException in my code on the line where I try to use and EntityManagerFactory to create an EntityManager instance. (I first tried to simply inject an EntityManager which was throwing a NullPointerException).
Stateless EJB
@Stateless
public class OrderLocatorBean implements OrderLocator
{
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
public List<Order> getOrdersByDate(Date start, Date end)
{
EntityManager em = this.entityManagerFactory.createEntityManager();
TypedQuery<Order> queryByDate = em.createNamedQuery("findByDate", Order.class);
queryByDate.setParameter("startdate", start);
queryByDate.setParameter("enddate", end);
List<Order> results = queryByDate.getResultList();
em.close();
return results;
}
}
The EJB is packaged inside order.jar which is included in the ear file. Here is the ejb-jar.xml file for it.
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0"
>
<enterprise-beans>
<session>
<ejb-name>OrderLocatorBean</ejb-name>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
Here is my persistence.xml file packaged inside order.jar in the META-INF directory:
<?xml version="1.0"?>
<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="Order" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>contexte-datasource</jta-data-source>
<class>order.Order</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
</properties>
</persistence-unit>
</persistence>
And here is the exception (last part of it) being thrown by the EJB:
Caused by: org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.service.jdbc.connections.spi.ConnectionProvider]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:151)
at org.hibernate.internal.AbstractSessionImpl.getJdbcConnectionAccess(AbstractSessionImpl.java:262)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.<init>(JdbcCoordinatorImpl.java:106)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.<init>(TransactionCoordinatorImpl.java:90)
at org.hibernate.internal.SessionImpl.<init>(SessionImpl.java:254)
at org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1618)
at org.hibernate.ejb.EntityManagerImpl.getRawSession(EntityManagerImpl.java:121)
at org.hibernate.ejb.EntityManagerImpl.getSession(EntityManagerImpl.java:97)
at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1207)
at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:178)
at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.java:89)
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:193)
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:188)
at sun.reflect.GeneratedMethodAccessor589.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at weblogic.deployment.EntityManagerFactoryProxyImpl.invoke(EntityManagerFactoryProxyImpl.java:96)
at $Proxy238.createEntityManager(Unknown Source)
at order.OrderLocatorBean.getOrdersByDate(OrderLocatorBean.java:40)
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 com.bea.core.repackaged.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at com.oracle.pitchfork.spi.MethodInvocationVisitorImpl.visit(MethodInvocationVisitorImpl.java:34)
at weblogic.ejb.container.injection.EnvironmentInterceptorCallbackImpl.callback(EnvironmentInterceptorCallbackImpl.java:54)
at com.oracle.pitchfork.spi.EnvironmentInterceptor.invoke(EnvironmentInterceptor.java:42)
at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at com.bea.core.repackaged.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at com.bea.core.repackaged.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy244.getOrdersByDate(Unknown Source)
at order.OrderLocatorBean_43jnw0_OrderLocatorImpl.__WL_invoke(Unknown Source)
at weblogic.ejb.container.internal.SessionLocalMethodInvoker.invoke(SessionLocalMethodInvoker.java:39)
... 58 more
I was able to solve this problem by setting the hibernate configuration property hibernate.transaction.factory_class. See documentation here:
http://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html_single/#transactions-demarcation-jta http://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html_single/#configuration-optional-dialects
I looked through the hibernate source and while I couldn't quite pinpoint the exact reason, I could see some initialization was failing. It looks like with weblogic (and maybe others) servers hibernate needs to know how to create JTA transactions. My updated files are below.
persistence.xml
<?xml version="1.0"?>
<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="Order" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>contexte-datasource</jta-data-source>
<class>order.Order</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
</properties>
</persistence-unit>
</persistence>
Stateless EJB
@Stateless
public class OrderLocatorBean implements OrderLocator
{
@PersistenceContext
private EntityManager entityManager;
public List<Order> getOrdersByDate(Date start, Date end)
{
TypedQuery<Order> queryByDate = this.entityManager.createNamedQuery("findByDate", Order.class);
queryByDate.setParameter("startdate", start);
queryByDate.setParameter("enddate", end);
List<Order> results = queryByDate.getResultList();
return results;
}
}