问题
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 useRESOURCE_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