newmudhar
newmudhar

Reputation: 11

JPA EJB Jersey @PersistenceContext is not instantiating EntityManager

I am trying to use @PersistenceContext to have Container-Managed Persistence with no lucks for couple of days now, I have searched every single related question. I am using:
- IntelliJ14
- Jersey 2
- JPA 2
- webapp schema 3.1
- EJB 3

I have tried so many things nothing worked for me, it only works if I use the transaction type is "Resource_Local" with creating EntityManagerFactory myself. I have looked at all similar questions here, please any help would be appreciated! I am getting this error:

Caused by: org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=PersistenceManager,parent=UserController,qualifiers={},position=-1,optional=false,self=false,unqualified=null,454129121)
    at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74) [hk2-locator-2.4.0-b25.jar:]
    at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:214) [hk2-locator-2.4.0-b25.jar:]
    at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:237) [hk2-locator-2.4.0-b25.jar:]
    ... 56 more

here is my current code:
web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

  <display-name>Rest</display-name>

    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.mudhar.rest.controller</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

</web-app>

persistence.xml

<?xml version="1.0" encoding="UTF-8" ?>
<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"
             version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
    <persistence-unit name="mudhar" transaction-type="JTA">
        <class>com.mudhar.rest.model.User</class>
        <properties>
            <property name="hibernate.enable_lazy_load_no_trans" value="true" />
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/mudhardb" />
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="root" />
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
        </properties>
    </persistence-unit>
</persistence>

Service Resource:

package com.mudhar.rest.controller;

import com.mudhar.rest.dao.PersistenceManager;
import com.mudhar.rest.model.RequestBody;
import com.mudhar.rest.model.User;

import javax.ejb.EJB;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.sql.Timestamp;

@Path("/user")
public class UserController {

    @Inject
    PersistenceManager persistenceManager;

    @POST
    @Path("/get")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public User getUser(RequestBody body) {

        String idUser = body.getIdUser();

        EntityManager em = persistenceManager.getEntityManager();
        em.getTransaction().begin();

        User user = em.find(User.class, Long.valueOf(idUser));

        em.getTransaction().commit();
        em.close();
        return user;
    }

    @PUT
    @Path("/add")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String addUser(User user){

        System.out.println(user.toString());
        String result = "Success";
        EntityManager em = persistenceManager.getEntityManager();
        em.getTransaction().begin();
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        user.setTimestamp(timestamp);
        try {
            em.merge(user);
            em.getTransaction().commit();
        }catch (Exception e){
            e.printStackTrace();
            result = "Failed";
        }

        em.close();
        return result;

    }

}

PersistenceManager.java

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;

@Stateless
public class PersistenceManager {

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


    public EntityManager getEntityManager() {
        return em;
    }
    public void close() {
        em.close();
    }
}

pom.xml

<properties>
    <jersey2.version>2.19</jersey2.version>
    <jaxrs.version>2.0.1</jaxrs.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <!-- JAX-RS -->
    <dependency>
      <groupId>javax.ws.rs</groupId>
      <artifactId>javax.ws.rs-api</artifactId>
      <version>${jaxrs.version}</version>
    </dependency>
    <!-- Jersey 2.19 -->
    <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-servlet</artifactId>
      <version>${jersey2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.core</groupId>
      <artifactId>jersey-server</artifactId>
      <version>${jersey2.version}</version>
    </dependency>


    <!-- https://mvnrepository.com/artifact/org.hibernate.javax.persistence/hibernate-jpa-2.1-api -->
    <dependency>
      <groupId>org.hibernate.javax.persistence</groupId>
      <artifactId>hibernate-jpa-2.1-api</artifactId>
      <version>1.0.0.Final</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson -->
    <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-json-jackson</artifactId>
      <version>2.19</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/javax.ejb/ejb-api -->
    <dependency>
      <groupId>javax.ejb</groupId>
      <artifactId>ejb-api</artifactId>
      <version>3.0</version>
      <scope>provided</scope>
    </dependency>


  </dependencies>
  <build>
    <finalName>DealderRest</finalName>
  </build>
</project>

Upvotes: 0

Views: 1099

Answers (2)

Steve C
Steve C

Reputation: 19445

I'm guessing that you're building a WAR file and deploying to GlassFish or Payara.

In any case, you need to add <scope>provided</scope> to the following dependencies:

  • javax.ws.rs-api
  • hibernate-jpa-2.1-api

and completely remove:

  • jersey-container-servlet
  • jersey-server
  • jersey-media-json-jackson

These jars are replacing the server implementations with code that does not have the integration required to be able to inject entity managers or EJBs.

Completely remove the web.xml file as it is redundant.

Finally, I recommend that you forget about your PersistenceManager class for now and change UserController as follows:

@Stateless
@Path("/user")
public class UserController {

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

    @POST
    @Path("/get")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public User getUser(RequestBody body) {

        String idUser = body.getIdUser();    
        User user = em.find(User.class, Long.valueOf(idUser));    
        return user;
    }

    @PUT
    @Path("/add")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String addUser(User user){

        System.out.println(user.toString());
        String result = "Success";
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        user.setTimestamp(timestamp);
        user = em.merge(user);
        return result;

    }

}

You can see that this is much simpler. Note that it has been annotated @Stateless so it's now an EJB, so you get transaction management and other features for the price of one line of code.

Note that if you're using GlassFish/Payara then the JPA implementation will be EclipseLink and not Hibernate.

Upvotes: 0

ytg
ytg

Reputation: 1857

I think you're missing an AbstractBinder implementation like this answer suggests for the same exception.

Upvotes: 0

Related Questions