Issue
I'm converting our webapp from an XML-based IoC, straight Hibernate webapp to one using annotations and JPA 2.1. Our app server is WebLogic 12.1.3, we're using Spring 3.2.13 and Hibernate 4.3.9. Our architecture is layered, with each layer ending up in its own JAR file. The layout of the EAR file is as follows:
|-EAR
|-- my-app.ear
|-- my-app.war
|-- lib
|-- my-web.jar
|-- my-services.jar
|-- my-jpa.jar
| |-- META-INF
| |-- persistence.xml
|-- someotherlib.jar
At the top of the IoC chain is our DelegateFactory, which is used by Struts1 actions (we'll upgrade that later).
@Configuration
@ComponentScan({"com.mycompany.myapp.dao.jpa"})
public class DelegateFactory
{
public static DelegateFactory getInstance()
{
if (singleton == null)
{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(DelegateFactory.class);
ctx.refresh();
singleton = ctx.getBean(DelegateFactory.class);
ctx.close();
}
return singleton;
}
}
The IoC works when finding the web, service and DAO beans, but fails when trying to find the persistence unit. Below is the base class for our JPA DAOs. It is a plain DAO, not a Spring DAO. In an effort to make it work, I tried having both the em and the emf be injected.
public abstract class AbstractMyProjectJpaDao extends AbstractJpaTypedDao
{
public static final String PERSISTENCE_UNIT_NAME = "myPU";
@PersistenceUnit(unitName = PERSISTENCE_UNIT_NAME, name = PERSISTENCE_UNIT_NAME)
@Override
public void setEntityManagerFactory(
EntityManagerFactory emf)
{
super.setEntityManagerFactory(emf);
}
@PersistenceContext(unitName = PERSISTENCE_UNIT_NAME, name = PERSISTENCE_UNIT_NAME, type = PersistenceContextType.TRANSACTION)
@Override
public void setEm(
EntityManager em)
{
super.setEm(em);
}
}
The only XML file we seem to need so far is the persistence.xml file, which is below.
<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="myPU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:/jdbc/myDS</jta-data-source>
(declaration of persistent entities here)
</persistence-unit>
</persistence>
Here's the failure:
Caused By: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myPU' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:575)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1111)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:276)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:110)
My guess is that it just can't find the persistence.xml file, but according to what I've read, it's in a valid location.
What am I missing?
Solution
The first part of the problem is that I was not inserting the EntityManagerFactory. I ended up creating a dao-beans.xml file with this:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myPU" />
</bean>
Then I had to add the @ImportResource annotation to my DelegateFactory so that the XML file could be found.
@Configuration
@ComponentScan({"com.mycompany.myapp.dao.jpa"})
@ImportResource("classpath:dao-beans.xml")
public class DelegateFactory
{
...
}
I also had to change the JNDI name of my data source in persistence.xml from "java:/jdbc/myDS" to just "jdbc/myDS". I think that's a WebLogic thing.
Answered By - Gary Kephart