Sunday, June 18, 2017

JavaEE: EntityManager, PersistenceContext, Data from Database

On the previous post, we learned how to define a persistence unit and DataSource on TomEE.  On this post, we will see how to make a database connection and get data from a relational database using the persistence unit.

A persistence context is a set of managed unique entity instances, and the entity instances and their lifecycle are managed by the entity manager within the persistence context.  A container-managed entity manager's lifecycle is managed by the Java EE container and an application-managed entity manager's lifecycle is managed by the application.

The entity manager for a persistence context is obtained from an entity manager factory.  When container-managed entity managers are used (in Java EE environments), the application does not interact with the entity manager factory. The entity managers are obtained directly through dependency injection or from JNDI, and the container manages interaction with the entity manager factory transparently to the application.  An entity manager must not be shared among multiple concurrently executing threads, as the entity manager and persistence context are not required to be threadsafe. Entity managers must only be accessed in a single-threaded manner. [JPA 2.1 Specification]

Obtaining a (container-managed) Entity Manager
The PersistenceContext annotation is used for entity manager injection with a name 'demoDB', which is a persistence-unit name specified in the persistence.xml. This is a UserService class with an entity manager injected.

@Logging
@Stateless
public class UserService {
   @Inject
   private Logger logger;
   
   @PersistenceContext(name="demoDB")
   private EntityManager em;
   
   public List<User> getAllUsers(){
      Query query = em.createNamedQuery("User.findAll");
      return query.getResultList();
   }
   
   public User getUser(Long id){
      Query query = em.createQuery("SELECT u From User u WHERE u.id = :id");
      query.setParameter("id", id);
      
      User user = null;
      try{
         user = (User)query.getSingleResult();
      }catch(NoResultException ne){
         logger.info(ne.getMessage() + " for an input id " + id);
      }
      return user;
   }
}

In addition to the @PersistenceContext annotation, an interceptor @Logging annotation and an injected Logger object are also used.

User Entity Object
The UserService class uses a User entity object that maps to a 'Users' database table in a PostgreSQL database.  This is a User class without the getter/setter methods to save the space.  Many IDEs such as an Eclipse provide a tool to create the Entity classes after connecting to a database.  This User class was also defined in the persistence.xml from the previous post.

@Entity
@Table(name="users")
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
   private static final long serialVersionUID = 1L;

   @Id
   @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="user_id_seq")
   @SequenceGenerator(name="user_id_seq", sequenceName="USERS_USER_ID_SEQ") 
   @Column(name="user_id")
   private Long userId;

   @Column(name="birth_day")
   private Integer birthDay;

   @Column(name="birth_month")
   private Integer birthMonth;

   @Column(name="birth_year")
   private Integer birthYear;

   @Column(name="create_time")
   private Timestamp createTime;

   @Column(name="first_name")
   private String firstName;

   @Column(name="last_name")
   private String lastName;

   @Column(name="update_time")
   private Timestamp updateTime;

   @Column(name="user_name")
   private String userName;

RESTful web service
This is a web service entry point that uses the UserService.  The return type is a Response abstract class in a javax.ws.rs.core package and the TomEE provides a ResponseImpl class from an Apache CXF library.  Therefore, adding any additional library is not required.

@Logging
@Path("/user")
public class UserRestEnd {
   @Inject
   private UserService userService;
   
   @GET
   @Produces(MediaType.APPLICATION_JSON)
   public Response getAllUser(){
      List<User> users = userService.getAllUsers();
      Response res = Response.status(Response.Status.OK).entity(users).build();
      return res;
   }
   
   @GET
   @Path("/{id}")
   @Produces(MediaType.APPLICATION_JSON)
   public Response getUser(@PathParam("id") Long id){
      User user = userService.getUser(id);
      Response res = Response.status(Response.Status.OK).entity(user).build();
      return res;
   }
}

Start a TomEE-maven-plugin and available APIs shown on logs
  mvn clean package tomee:run

When the server starts, the TomEE logs show available RESTful APIs.

org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints      Service URI: http://localhost:8080/demo/user      -> Pojo demo.rest.endpoint.UserRestEnd
org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints               GET http://localhost:8080/demo/user/     ->      Response getAllUser() 
org.apache.openejb.server.cxf.rs.CxfRsHttpListener.logEndpoints               GET http://localhost:8080/demo/user/{id} ->      Response getUser(Long)

Result



 







Logs from the interceptor @Logging
There are no log on the UserRestEnd class and the UserService, but the @Logging annotation will create the logs with an execution time.

demo.interceptor.LoggingInterceptor.logMethod  Entering demo.rest.endpoint.UserRestEnd - getAllUser
demo.interceptor.LoggingInterceptor.logMethod  Entering demo.rest.service.UserService - getAllUsers
demo.interceptor.LoggingInterceptor.logMethod  Exiting  demo.rest.service.UserService - getAllUsers Execution Time: 2ms
demo.interceptor.LoggingInterceptor.logMethod  Exiting  demo.rest.endpoint.UserRestEnd - getAllUser Execution Time: 3ms


No comments:

Post a Comment

Java 9: Flow - Reactive Programming

Programming world has always been changed fast enough and many programming / design paradigms have been introduced such as object oriented p...