
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 […]
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.
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 file) and 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.
Share:
We’re excited to announce that Payara Platform Community 7 Beta application server is now fully certified as Jakarta EE 11 […]
Managing Payara Server Just Got Smarter Imagine managing your Jakarta EE applications not just with Maven goals, but by […]
Enterprise Java applications power global commerce, healthcare, government and countless other industries. These systems must be scalable, secure and […]
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?
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?
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?
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.
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?
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.
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”.
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!
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