5

I'm trying to inject EntityManagerFactory using @PersistenceUnit, but it's always null.

I think my persistence.xml is OK, since I can get the EntityManager with this code:

EntityManager em = Persistence.createEntityManagerFactory("myPersistenceUnit").createEntityManager();

So, I would like to know if I'm doing something wrong, or if this is not possible when using Jersey (2.23) and Wildfly 10 (JBoss EAP 7).

Here is what I've done so far:

  • Created a jersey-quickstart-webapp maven project on eclipse;
  • Added the following dependencies to my pom.xml:

    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>7.0</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate.javax.persistence</groupId>
      <artifactId>hibernate-jpa-2.1-api</artifactId>
      <version>1.0.0.Final</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>5.2.2.Final</version>
    </dependency>
    <dependency>
      <groupId>com.hynnet</groupId>
      <artifactId>oracle-driver-ojdbc6</artifactId>
      <version>12.1.0.1</version>
    </dependency>
    
  • Created the persistence.xml:

    <persistence-unit name="myPersistenceUnit"
      transaction-type="RESOURCE_LOCAL">
      <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
      <!-- All persistence classes must be listed -->
      <class>com.mps.classes.TermosPesquisados</class>
      <properties>
        <!-- Provider-specific connection properties -->
        <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
        <property name="javax.persistence.jdbc.url" value="JDBC_URL" />
        <property name="javax.persistence.jdbc.user" value="USER" />
        <property name="javax.persistence.jdbc.password" value="PASSWORD" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
        <property name="hibernate.show_sql" value="false" />
        <property name="hibernate.connection.release_mode" value="after_transaction" />
        <property name="hibernate.connection.isolation" value="2" />
      </properties>
    </persistence-unit>
    
  • Modified the MyResource.java:

    @ManagedBean
    @Path("myresource")
    public class MyResource {
    
      @PersistenceUnit(unitName= "myPersistenceUnit")
      private EntityManagerFactory emf;
    
      @GET
      @Produces(MediaType.TEXT_PLAIN)
      public String getIt() {
        if(emf == null)
          return "emf is null";
        return "emf is not null";
      }
    }
    
  • Added an empty beans.xml (not sure if it's necessary);

Fabricio Koch
  • 1,395
  • 12
  • 20
  • As a side note, if you're new to Java and have the option of choosing your tools, I suggest taking a look at Spring instead. The Spring Boot autoconfiguration makes this sort of setup much simpler and eliminates the need for an external container. – chrylis -cautiouslyoptimistic- Sep 05 '16 at 16:24
  • @chrylis agree but might depend on his cicumstance... plus ejb has gotten easier in the last few years – Crowie Sep 05 '16 at 20:40

3 Answers3

3

It seems that Jersey conflicts with Resteasy. This way, I had 2 options:

  • Turn-off Resteasy on JBoss/Wildfly (I know that's possible, but I don't know how);
  • Remove Jersey and use Resteasy instead;

I ended up choosing the 2nd option because it was easier and I have no reasons to use specifically Jersey.

This way, I had to change my web.xml, replacing this:

<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
...
<servlet-mapping>
  <servlet-name>Jersey Web Application</servlet-name>
  <url-pattern>/webapi/*</url-pattern>
</servlet-mapping>

For this:

<servlet-name>javax.ws.rs.core.Application</servlet-name>
...
<servlet-mapping>
  <servlet-name>javax.ws.rs.core.Application</servlet-name>
  <url-pattern>/webapi/*</url-pattern>
</servlet-mapping>

*Another option was to create a class extending Application class.

*beans.xml was not necessary.

Then, I annotated my resource class with @Stateless and I was able to inject EntityManager properly:

@Path("myresource")
@Stateless
public class MyResource {

  @PersistenceContext(unitName="myPersistenceUnit")
  private EntityManager em; 
...

At this point, EntityManager was OK, but somehow it was using JBoss h2 in-memmory database (ExampleDS). So, I configured an oracle datasource on JBoss (OracleDS) and updated my persistence.xml to use OracleDS and JTA instead of "RESOURCE_LOCAL":

<persistence-unit name="myPersistenceUnit" transaction-type="JTA">
  <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
  <jta-data-source>java:jboss/datasources/OracleDS</jta-data-source>
...

With those steps I was able to inject EntityManager and make my CRUD operations successfully.

Fabricio Koch
  • 1,395
  • 12
  • 20
1

There is no point for a @ManagedBean annotation here, this is a JSF annotation and I according to your code you're trying to expose a REST layer.

Just remove it and all will be fine (also ensure that you have a beans.xml in your classpath to enable CDI, otherwise annotate your class with @Stateless)

Gab
  • 7,869
  • 4
  • 37
  • 68
  • Actually I was using javax.annotation.ManagedBean annotation. I removed @ManagedBean and EntityManagerFactory is still null. I have a empty beans.xml and I can see that the CDI service was started on console log: [org.jboss.weld.deployer] (MSC service thread 1-5) WFLYWELD0006: Starting Services for CDI deployment ..... – Fabricio Koch Sep 05 '16 at 16:27
  • I annoteted my class with @Stateless and didn't help also. – Fabricio Koch Sep 05 '16 at 20:21
0

I think Entity manager should be enough :

 @PersistenceUnit(unitName= "myPersistenceUnit")
   private EntityManager em;
Elgayed
  • 1,129
  • 9
  • 16
  • by the way you can not inject entity manager or entity manager factory in a managed bean, you have to inject it in an EJB bean, you have to create a DAO layer in which you define you deal with the database, and inject those EJB in the managed bean using @EJB – Elgayed Sep 05 '16 at 15:28
  • Since I'm using transaction-type="RESOURCE_LOCAL" I can't inject EntityManager. I have to inject EntityManagerFactory, otherwise I get an error. – Fabricio Koch Sep 05 '16 at 16:07
  • I'm new to Java, so let me see if I understand the "EJB bean" part. I have to create a EJB project with all my persistence configuration, create a session bean and refer this bean in my web/jersey project with @EJB ? – Fabricio Koch Sep 05 '16 at 16:14