Build REST CRUD APIs with Micronaut and Data Hibernate JPA
Hello everyone, today we will learn how to build RESTful CRUD APIs using Micronaut and Data Hibernate JPA with the help of one simple example.
Related topics,
Related topics,
Micronaut is a modern, JVM-predicated, full-stack Java framework designed for building modular, facilely testable JVM applications with support for Java, Kotlin and the Groovy language.
Micronaut provides:
- Dependency Injection and Inversion of Control (IoC)
- Aspect-Oriented Programming (AOP)
- Sensible Defaults and Auto-ConfigurationMessage-Driven Applications
- HTTP Routing
- Client-Side Load Balancing
- Command-Line Applications
- HTTP ServersDistributed Configuration
- Service Discovery
- Fast startup time
- Reduced memory footprint
- Minimal use of reflection
- Minimal use of proxies
- No runtime bytecode generation
- Easy Unit Testing
Technologies used:
- Java 11
- Micronaut 3.1.1
- Micronaut Data Hibernate JPA 3.1.1
- H2DB
- Micronaut-Hikari-Cp 3.1.1
- Maven 3.6.3
Final Project Structure:
Dependency management - Maven - Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.knf.dev.demo</groupId>
<artifactId>micronaut-data-jpa-crud</artifactId>
<version>0.1</version>
<packaging>${packaging}</packaging>
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>3.1.1</version>
</parent>
<properties>
<packaging>jar</packaging>
<jdk.version>11</jdk.version>
<release.version>11</release.version>
<micronaut.version>3.1.1</micronaut.version>
<exec.mainClass>org.knf.dev.demo.Application</exec.mainClass>
<micronaut.runtime>netty</micronaut.runtime>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-runtime</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-hibernate-jpa</artifactId>
</dependency>
<dependency>
<groupId>io.micronaut.sql</groupId>
<artifactId>micronaut-jdbc-hikari</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- Uncomment to enable incremental compilation -->
-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
<annotationProcessorPaths
combine.children="append">
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-validation</artifactId>
<version>${micronaut.version}</version>
</path>
<path>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-processor</artifactId>
<version>${micronaut.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amicronaut.processing.group=org.knf.dev.demo</arg>
<arg>-Amicronaut.processing.module=micronaut-data-jpa-crud</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
Data source & JPA configuration in src/main/resources/application.yml
micronaut:
application:
name: micronautDataJPA
datasources:
default:
url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
driverClassName: org.h2.Driver
username: sa
password: ''
jpa.default.properties.hibernate.hbm2ddl.auto: update
jpa:
default:
properties:
hibernate:
hbm2ddl:
auto: update
show_sql: true
Entity class
package org.knf.dev.demo.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "users")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String emailId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public User(Long id, String firstName, String lastName, String emailId) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}
public User() {
super();
}
}
UserRepository
package org.knf.dev.demo.repository;
import org.knf.dev.demo.entity.User;
import io.micronaut.data.annotation.Repository;
import io.micronaut.data.repository.CrudRepository;
@Repository
public interface UserRepository extends CrudRepository<User,Long>{
}
UserController
package org.knf.dev.demo.controller;
import java.util.List;
import java.util.Optional;
import org.knf.dev.demo.entity.User;
import org.knf.dev.demo.repository.UserRepository;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Delete;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.annotation.Put;
import io.micronaut.scheduling.TaskExecutors;
import io.micronaut.scheduling.annotation.ExecuteOn;
@ExecuteOn(TaskExecutors.IO)
@Controller("/users")
public class UserController {
protected final UserRepository userRepository;
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Get
public List<User> getUsers() {
return (List<User>) userRepository.findAll();
}
@Get("/{id}")
public Optional<User> getUser(Long id) {
return userRepository.findById(id);
}
@Put("/{id}")
public User updateUser(Long id, @Body User user) throws Exception {
if (userRepository.existsById(id)) {
user.setId(id);
userRepository.update(user);
return user;
} else {
/*
* For demo purposes, I am using Generic Exception.
* In a real scenario, you must
* implement custom exception handling.
*/ throw new Exception("Id Not Found");
}
}
@Post
public User addUser(@Body User user) {
return userRepository.save(user);
}
@Delete("/{id}")
public void deleteUser(Long id) throws Exception {
if (userRepository.existsById(id)) {
userRepository.deleteById(id);
} else {
/*
* For demo purposes, I am using Generic Exception.
* In a real scenario, you must
* implement custom exception handling.
*/
throw new Exception("Id Not Found");
}
}
}
Main Class
package org.knf.dev.demo;
import io.micronaut.runtime.Micronaut;
public class Application {
public static void main(String[] args) {
Micronaut.run(Application.class, args);
}
}
Verify REST APIs
Run as Java Application
or
mvn mn:run