2

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;
    }

}
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
user1493834
  • 756
  • 4
  • 11
  • 25
  • A couple of suggestions, since I don't know the exact answer. Are you using container or bean managed persistence? If CMT then have you tried injecting entityManagerFactory instead of entityManager? – Atul Nov 24 '14 at 06:08
  • I am not using EJBs. does it applicable for web components? – user1493834 Nov 24 '14 at 06:42
  • yes, it does. Just as an initial suggestion, try injecting entityManagerFactory instead of entityManager. You can google about how to do that. If you get a different answer, try their approach first as I am not very sure about the value add of entityManagerFactory. – Atul Nov 24 '14 at 07:37
  • tried injecting EMF but still same issue. It is something to do with struts2 famework..because I wrote simple servlet and tried injecting EM and it works fine. It does not works if I go through strut2 dispatcher or something.. – user1493834 Nov 24 '14 at 08:40

2 Answers2

3

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 */
}
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • great..but I have another issue. I tried saving the model using em.persit().. it says : JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context).. if I try to call em.getTransaction() is says EntityManager cannot use Transaction.. any suggestions? I have @PersistenceContext(unitName="primary",type=PersistenceContextType.TRANSACTION) in place already. – user1493834 Nov 24 '14 at 14:55
  • You need to either do this in an EJB (transaction is by default Container managed), or in a CDI component (by manually handling the transaction, or by using an @Interceptor), or if you want to do it in the view tier (Actions), you need to use the [OSIV (Open Session In View, with Hibernate) / OEMIV (Open Entity Manager In View, with JPA) *anti*-pattern](http://stackoverflow.com/a/26973725/1654265). I strongly suggest the EJB 3.1 way. – Andrea Ligios Nov 24 '14 at 15:00
  • I am writting a job portal for a company. I am thinking to switch to Tomcat7 -EclipseLink . I donot think I need EJBs and other services offered by Jboss for this.. what do you say? sorry this is off topic.. – user1493834 Nov 24 '14 at 15:08
  • You can install [**Weld** (reference CDI implementation) or **OpenWebBeans** (Apache CDI implementation)](http://balusc.blogspot.it/2013/10/how-to-install-cdi-in-tomcat.html) in Tomcat as described in BalusC's blog post, or simply use [TomEE (Tomcat on steroids)](http://tomee.apache.org/), I've never heard anyone talking bad of it, anywhere. If you want EclipseLink out of the box, you need [**TomEE PluME**](http://tomee.apache.org/comparison.html) – Andrea Ligios Nov 24 '14 at 15:21
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;
}
}
bavon
  • 151
  • 2
  • 14