Using Hibernate 5 on Payara Server

Uncategorized

Hibernate is the object/relational mapping tool that handles mapping of Java classes to relational tables and Java types to SQL data type. It’s a well-known framework in the Enterprise Java eco-system since it’s being actively developed for the last 16 years.

With this article, I’m going to show the ways of using Hibernate inside a sample application – source code available here – and deploy it onto Payara Server. I will be using the latest version of Hibernate, which is 5.2.10.Final at the time of writing.

 

Getting Started

My sample project is a web application architected with Maven and it contains one simple domain object, its DAO implementation and its REST based web service for exposing CRUD operations to the outside world.

 

Let’s start with the Maven configuration of the project. Hibernate is added as a single dependency to the project since it transitively fetches the necessary dependencies underneath.

 

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>5.2.10.Final</version>
</dependency>

 

For demonstration purposes, the in-memory H2 database will be used for easy configuration. Its dependency definition is as follows:

 

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.192</version>
</dependency>

 

The JDBC resource and Connection Pool definitions are defined in a glassfish-resources.xml file, which is located under the WEB-INF folder. This helps to isolate the definitions within our sample project, and mitigates needing to deal with the Payara Server Admin Console or asadmin commands to define the resources.

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN"
        "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
    <jdbc-resource pool-name="H2Pool"
                   jndi-name="java:app/jdbc/hibernate"/>
    <jdbc-connection-pool name="H2Pool"
                          res-type="javax.sql.DataSource"
                          datasource-classname="org.h2.jdbcx.JdbcDataSource">
        <property name="user" value="sa"/>
        <property name="password" value=""/>
        <property name="url" value="jdbc:h2:mem:hibernateExample"/>
    </jdbc-connection-pool>
</resources>

 

You can see that H2 database URL is defined as in-memory, and the JNDI name mapping that should be used by the project is jdbc/hibernate.

 

The persistence.xml file is used to register a persistence unit to the application at the application level. I am using the registered JDBC Resource that was defined in the glassfish-resources.xml file, and naming the persistence unit as payaraHibernate.

 

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">
    <persistence-unit name="payaraHibernate" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>java:app/jdbc/hibernate</jta-data-source>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
        </properties>
    </persistence-unit>
</persistence>

 

By defining the persistence provider, the application will use Hibernate as the underlying ORM. The H2 database is also related to the hibernate.dialect property so that it allows Hibernate to generate H2 optimized SQLs.

 

The Person domain object class is defined as follows:

 

@Entity
@NamedQueries({
        @NamedQuery(name = "Person.findOne", query = "select p from Person p where p.id = :id"),
        @NamedQuery(name = "Person.getAll", query = "select p from Person p")
    }
)
public class Person {

    @Id
    @GeneratedValue
    private long id;
    private String name;
    private String lastName;

    public Person() {
    }

    public Person(String name, String lastName) {
        this.name = name;
        this.lastName = lastName;
    }

    // getter methods
}

 

The DAO implementation for the corresponding Person domain class is as follows:

 

@Stateless
public class PersonDao {

    @PersistenceContext
    private EntityManager entityManager;

    public List<Person> getAll() {
        return entityManager.createNamedQuery("Person.getAll", Person.class).getResultList();
    }

    public Person find(Long id) {
        return entityManager.createNamedQuery("Person.findOne", Person.class).setParameter("id", id).getSingleResult();
    }

    public void save(Person person) {
        entityManager.persist(person);
    }

    public void update(Person person) {
        entityManager.merge(person);
    }

    public void delete(Person person) {
        entityManager.remove(person);
    }
}

 

The REST web service implementation is as follows:

 

@Stateless
@Path("person")
public class PersonResource {

    @Inject
    private PersonDao personDao;

    @GET
    @Produces("application/json")
    public List<Person> all() {
        return personDao.getAll();
    }

    @POST
    @Consumes("application/json")
    public void save(Person person) {
        personDao.save(person);
    }

    @PUT
    @Consumes("application/json")
    public void update(Person person) {
        personDao.update(person);
    }

    @DELETE
    @Path("/{id}")
    @Consumes("application/json")
    public void delete(@PathParam("id") Long id) {
        Person person = personDao.find(id);
        personDao.delete(person);
    }
}

 

After deploying the application onto Payara Server, I can easily invoke the REST web services for creating/updating/deleting person information. To invoke REST, I favored Postman , a GUI tool for API invocation. You can import given Postman project  by yourself (see JSON fileand invoke endpoints deployed on localhost:8080. The URL for the endpoint would be http://localhost:8080/hibernate-example/resources/person for a local deployment.

 

The screenshot below shows the GET request on the provided URL.

 

Hibernate_on_Payara.png

 

 

 

Comments (9)

Post a comment

Your email address will not be published. Required fields are marked *

Payara needs the contact information you provide to us to contact you about our products and services. You may unsubscribe from these communications at any time. For information on how to unsubscribe, as well as our privacy practices and commitment to protecting your privacy, please review our Legal & Privacy Policy.

  1. Martin Charlesworth

    Thanks Mert. When I try your example with payara-micro 172 I get java.lang.NoSuchMethodError: org.jboss.logging.Logger.debugf(Ljava/lang/String;I)V.

    I think this is caused by the bean-validator.jar packaged inside payara micro containing some classes from jboss logging, which must be an older version than 3.3.0.Final which is the version of jboss-logging which is also provided. Do you know of any way round this?

  2. Martin Charlesworth

    Thanks Mert. When I try your example with payara-micro 172 I get java.lang.NoSuchMethodError: org.jboss.logging.Logger.debugf(Ljava/lang/String;I)V.

    I think this is caused by the bean-validator.jar packaged inside payara micro containing some classes from jboss logging, which must be an older version than 3.3.0.Final which is the version of jboss-logging which is also provided. Do you know of any way round this?

  3. Martin Charlesworth

    Thanks Mert. When I try your example with payara-micro 172 I get java.lang.NoSuchMethodError: org.jboss.logging.Logger.debugf(Ljava/lang/String;I)V.

    My suspicion was right – if I remove the jboss logging classes from inside the bean-validator jar then the app deploys and runs fine. Should I open a bug in payara-micro?

  4. Mert Caliskan

    you’re right Martin. this is due to bean-validator.jar re-bundled by hk2 team for OSGI compatibility. You can either re-package bean-validator.jar that resides under MICRO-INF/runtime folder by removing that org.jboss.logging package or you can move onto 4.1.2-173-SNAPSHOT by building from source or grabbing a nightly build from our downloads page. With latest build, we’re moving onto hk2 2.5.x and hk2 guys now don’t re-bundle hibernate & jboss-logging together with that new release.

  5. Martin Charlesworth

    Thanks for your reply, Mert. I can work around it for now by repackaging without the jboss logging classes.

    Just wondered if you have ever tried to use hibernate 5’s multitenancy support on payara-micro? I’m following roughly this blog https://www.toptal.com/hibernate/build-multitenant-java-hibernate but I can’t deploy the app – when it tries to get the datasource in the provider class I always get javax.naming.NamingException: Lookup failed for ‘java:app/jdbc/hibernate’. Have managed to do this successfully before?

    1. Mert Caliskan

      that shouldn’t be a problem, looks like glassfish-resources.xml cannot be picked up. Do you have a self-contained sample reproducer app that we can take a look at? If yes, feel free to file an issue on github regarding the problem. thanks.

  6. Guillermo González de Agüero

    This is a nice article, but any reason you didn’t you used @DataSourceDefinition or web.xml instead of the propietary glassfish-resources.xml to create the datasource?

    Also, JPA 2.1 provided a standard “javax.persistence.schema-generation.database.action” property which should be preferred over the propietary “hibernate.hbm2ddl.auto”.

    1. Mert Caliskan

      no reason, @DataSourceDefinition can be used as well. JPA property didn’t work for me back at the time but I’ll try again. feel free to send a PR for both. thanks!

  7. Janusz

    Hi Mert,
    I’ve followed your post and unfortunately I have issue ‘A JTA EntityManager cannot use getTransaction()’ when I’m trying to send any POST request to save any new data to DB.
    All GETs to read data from DB works ok.
    Please advice

    My environment:
    java 1.8, javaee-api 7.0, javax.servlet-api 3.1.5, hibernate-entitymanager 5.1.13.Final, postgresql 42.2.2 and olingo 2.0.9

Related Posts

4 minutes
Uncategorized

Leading the Way: Payara Platform Community 7 Beta Now Fully Jakarta EE 11 Certified

We’re excited to announce that Payara Platform Community 7 Beta application server is now fully certified as Jakarta EE 11 […]

Understanding the Security Issues of Aging Middleware 6 minutes
Community

Boost Developer Productivity with Payara Server Maven Plugin + AI Agent

Managing Payara Server Just Got Smarter  Imagine managing your Jakarta EE applications not just with Maven goals, but by […]

What Is a Java Application Server? A Short Guide 6 minutes
Jakarta EE

What Is a Java Application Server? A Short Guide

Enterprise Java applications power global commerce, healthcare, government and countless other industries. These systems must be scalable, secure and […]