问题
I am starting struts2 based application with Jboss provided JPA libraries. I have configured data-source in standalone.xml I can see from the jboss administration console that the datasource is created. and the presistence.xml files are read and processed. But if I check the EntityManager instance in Action Class. It always says null.
Here is my persistence.xml and Action class snippet
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
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">
<persistence-unit name="primary">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/mysqlDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<!-- Properties for Hibernate -->
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.use_sql_comments" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>
</persistence>
Struts2 Action Class:
public class RegistrationAction extends ActionSupport implements SessionAware,Preparable ,ModelDriven{
/**
*
*/
private static final long serialVersionUID = 1L;
@PersistenceContext(unitName="primary")
private EntityManager em;
@Override
public Object getModel() {
// TODO Auto-generated method stub
return null;
}
@Override
public void prepare() throws Exception {
if(em==null)
System.out.println(" EM is null still..");
//even Persistence.createEntityManagerFactory("primary"); returning NULL
}
@Override
public void setSession(Map<String, Object> arg0) {
// TODO Auto-generated method stub
}
public EntityManager getEm() {
return em;
}
public void setEm(EntityManager em) {
this.em = em;
}
}
回答1:
Actions are managed by the Struts Container.
EntityManager is managed by CDI Container. You can Inject it in CDI Managed objects (EJBs in EJB Container, CDI managed beans, servlets, ecc...), but not in Actions.
You need to either use the Struts2-CDI-Plugin or to perform a lookup to get it. You should not even inject it in Actions BTW, it would be better to use a business component (for examle an EJB) and perform a lookup on that.
If not using the CDI Plugin (for example because using the Spring Plugin), the CDIUtil.java by Rob Veldpaus is perfect for this.
Example EJB:
@Stateless
public class MyEjb{
@PersistenceContext(unitName="primary")
EntityManager em;
public Foo find(long id){
return em.find(Foo.class, id);
}
}
Example Action:
public class RegistrationAction extends ActionSupport
implements SessionAware,Preparable ,ModelDriven {
public String execute(){
MyEjb ejb = new CdiUtil().lookup(MyEjb.class);
System.out.println(ejb.find(1L));
return SUCCESS;
}
/* your other stuff here */
}
回答2:
CDI Plugin struts 2 plugin Worked for me.
pom.xml in included:
<!-- Import the CDI API -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-cdi-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.0-SP1</version><!--$NO-MVN-MAN-VER$-->
<scope>provided</scope>
</dependency>
Then in my Action class:
public class SampleAction extends BaseAction{
private static final long serialVersionUID = 1L;
@PersistenceUnit
private EntityManagerFactory emf;
@Action(value="add")
public String add(){
try{
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
........
em.merge(...);
em.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
}
return SUCCESS;
}
}
来源:https://stackoverflow.com/questions/27098228/jpa-entitymanager-not-initialized-in-struts2-and-jboss-7-1