Problems in injecting entity manager into stateless bean

有些话、适合烂在心里 提交于 2019-12-13 19:30:28

问题


I am developing an EJB3-app, where I use stateless beans. It seems like the EntityManager is not injected properly into my bean.

Here is code for the stateless bean:

@Stateless
@LocalBean
public class FirmEJB {

    @PersistenceContext(unitName = "Fr14_07_Nezdolij_lab3PU")
    private EntityManager em;

    @PersistenceUnit(unitName="Fr14_07_Nezdolij_lab3PU")
    private EntityManagerFactory emf;

    public FirmEJB() {
        emf = Persistence.createEntityManagerFactory("Fr14_07_Nezdolij_lab3PU");
        em = emf.createEntityManager();
    }

    public EntityManager getEm() {
        return em;
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }

    public Employee createEmployee(Employee e){
        em.persist(e);
        return e;
    }

    public Project createProject(Project p){
        em.persist(p);
        return p;
    }

    public Customer createProject(Customer c){
        em.persist(c);
        return c;
    }

    public Department createProject(Department d){
        em.persist(d);
        return d;
    }

    public ProjectManager createProjectManager(ProjectManager prjman){
        em.persist(prjman);
        return prjman;
    }

}

When I try to create an instance of FirmEJB I get the following exception:

Exception in thread "main" java.lang.NullPointerException
    at sttls.FirmEJB.createEmployee(FirmEJB.java:42)
    at entity.Main.main(Main.java:33)

persistence.xml:

<?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="Fr14_07_Nezdolij_lab3PU" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/fir</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="eclipselink.ddl-generation" value="create-tables"/>
            <property name="eclipselink.jdbc.url" value="jdbc:derby://localhost:1527/firmDB;create=true"/>
            <property name="eclipselink.jdbc.user" value="admin"/>
            <property name="eclipselink.jdbc.password" value="admin"/>
        </properties>
    </persistence-unit>
</persistence>

Client code:

public static void main(String[] args) throws ClassNotFoundException, Exception {

    Employee emp1 = new Employee("Alan", "Smith");

    FirmEJB firmejb = new FirmEJB();
    firmejb.createEmployee(emp1);
}

回答1:


You're using Java EE features in Java SE environment. That won't work.

The Java EE container responsible for dependency injection, so the PersisteneContext and PersistenceUnit make any sense only in the Java EE container environment (like Glassfish or JBoss).

If you define something like this:

@PersistenceContext(unitName = "Fr14_07_Nezdolij_lab3PU")
private EntityManager em;

@PersistenceUnit(unitName="Fr14_07_Nezdolij_lab3PU")
private EntityManagerFactory emf;

public FirmEJB() {
    emf = Persistence.createEntityManagerFactory("Fr14_07_Nezdolij_lab3PU");
    em = emf.createEntityManager();
}

you're defining dependency injection through annotations and at the same time you create the instances of EMF and EM by yourself. The annotations are meaningless in your case.

Moreover:

  • in persistence.xml you're defining to use RESOURCE_LOCAL transaction type and at the same time you're defining <jta-data-source> element (which means that you'll be using JTA transactions),
  • I assume that you're using EclipseLink so the <exclude-unlisted-classes>false</exclude-unlisted-classes> is working. Beware that this is not a portable solution - in order to be sure that in Java SE environment your entities will be visible to the JPA provider, you should define them using <class> element.

And last but not least, if you're executing your code in Java SE environment like this and don't start any Embedded EJB container than @Stateless is not needed because your class doesn't have any EJB nature. POJO annotated as a @Stateless or @Stateful gains EJB nature by being executed in EJB container. In this case, it acts like a plain Java class.

Beware - even if you'd use Embedded EJB container the code you've shown will not instantiate an EJB. You cannot use new FirmEJB() with EJBs. The container should be responsible for providing you an instance of the EJB.
That's the whole point of the abstraction - you depend upon abstraction rather than creation.

You might be interested in further reading like OpenJPA JPA Concepts or OpenEJB Documentation.




回答2:


yon need a change transaction-type="RESOURCE_LOCAL" to transaction-type="JTA"



来源:https://stackoverflow.com/questions/8544935/problems-in-injecting-entity-manager-into-stateless-bean

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!