In the previous tutorial, we have shown you how to create REST API easily in Groovy language using Grails Framework which everything is set up in Grails ways. Now, we will do the same thing but create with Spring Boot ways like configure sever and database, create an entity, create a repository, create service, and create REST controller. Using Groovy will decrease the codes lines instead of using Java. So, CRUD (Create, Read, Update, Delete) operation to build REST API simple and less library to use.
This tutorial is divided into several steps:
- Step #1: Create and Configure Spring Boot Groovy Project
- Step #2: Create Groovy Model or Entity Class
- Step #3: Create Groovy Repository Interface
- Step #4: Create Groovy Service and Implementation
- Step #5: Create Groovy RESTful Controller
- Step #6: Run and Test the Spring Boot Groovy PostgreSQL REST API
Before we start, the following tools, framework, library, and dependencies are required:
- JDK 11
- Maven
- Spring Boot
- Spring Data PostgreSQL
- Spring Initializr
- IDE (Netbeans, Eclipse, Spring Tool Suite, or IntellijIdea)
You can watch the video tutorial on our YouTube channel here.
Let's get started with the main steps!
Step #1: Create and Configure Spring Boot Groovy Project
We assume that you have installed JDK 11, Gradle, and IDE (Netbeans, Eclipse, STS, or IntellijIdea). Next, we will create a new Spring Boot Groovy Gradle project of REST API using Spring Initializer. Spring Initializr provides an extensible API to generate quickstart projects, and to inspect the metadata used to generate projects, for instance, to list the available dependencies and versions. Just go to Spring Initializr web-based Spring project generator then fill the required frameworks and libraries.
Fill the required fields as above, also, add the standard dependencies for creating REST APIs such as Spring Web, PostgreSQL Driver, and Spring Data JPA. Click the Generate button to download the compressed Spring Boot project. Next, extract the downloaded Spring Boot project then open it with your IDE (we are using IntellijIdea).
Next, open src/main/resources/application.properties then add these lines of server port, path, JPA, and PostgreSQL connection configuration.
server.port=8080
server.servlet.context-path=/api/v1
spring.jpa.database=POSTGRESQL
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=create
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://localhost:5432/groovyrest
spring.datasource.username=djamware
spring.datasource.password=dj@mw@r3
spring.datasource.driver-class-name=org.postgresql.Driver
As you see, we need to create a new PostgreSQL database. For that, run the PostgreSQL console in the terminal.
psql postgres --u postgres
Next, type this command for creating a new user with a password then give access for creating the database.
postgres-# CREATE ROLE djamware WITH LOGIN PASSWORD 'dj@mw@r3';
postgres-# ALTER ROLE djamware CREATEDB;
Quit `psql` then log in again using the new user that was previously created.
postgres-# \q
psql postgres -U djamware
Enter the password, then you will enter this `psql` console.
psql (9.5.13)
Type "help" for help.
postgres=>
Type this command to create a new database.
postgres=> CREATE DATABASE groovyrest;
Then give that new user privileges to the new database then quit the `psql`.
postgres=> GRANT ALL PRIVILEGES ON DATABASE groovyrest TO djamware;
postgres=> \q
Step #2: Create Groovy Model or Entity Class
In this tutorial, we will use 2 entity with one to many relationship. There's a Product entity which has many Variant entity as describe in this diagram.
To create that entity-relationship, first, we need to create a new package with the name com/djamware/groovyrest/entity the new Groovy files (com/djamware/groovyrest/entity/Product.groovy and com/djamware/groovyrest/entity/Variant.groovy). Next, open and edit com/djamware/groovyrest/entity/Product.groovy then add these lines of Groovy codes.
package com.djamware.groovyrest.entity
import javax.persistence.CascadeType
import javax.persistence.Entity
import javax.persistence.FetchType
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.OneToMany
import javax.persistence.Table
@Entity
@Table(name = 'product')
class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id
String prodName
String prodDesc
Double prodPrice
String prodImageUrl
@OneToMany(
fetch = FetchType.EAGER,
cascade = CascadeType.ALL,
orphanRemoval = true,
mappedBy = 'product'
)
List<Variant> variants
}
As you see, that entity class is very simple because all constructors, getters, and setters are handled by Groovy. We still using standard JPA notation for entity class type, ID generation, and one-to-many relationships. Next, open and edit com/djamware/groovyrest
entity/Variant.groovy then add these lines of Groovy codes.
package com.djamware.groovyrest.entity
import com.fasterxml.jackson.annotation.JsonIgnore
import javax.persistence.Entity
import javax.persistence.FetchType
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.ManyToOne
import javax.persistence.Table
@Entity
@Table(name = "variant")
class Variant {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id
String variantName
String variantColor
Double variantPrice
@ManyToOne(
fetch = FetchType.LAZY,
optional = false
)
@JsonIgnore
Product product
}
We are using @JsonIgnore to prevent a whole Product entity persist to the Variant entity. So, it just persists the Product ID only.
Step #3: Create Groovy Repository Interface
We will extend the Product repository with Spring Data PagingAndSortingRepository and the Variant with CrudRepository. First, create a new package com/djamware/groovyrest/repository then add to that package these Groovy files (com/djamware/groovyrest/repository/IProductRepository.groovy and com/djamware/groovyrest/repository/IVariantRepository.groovy). Open and edit com/djamware/groovyrest/repository/IProductRepository.groovy then replace all Groovy codes with these lines of Groovy codes.
package com.djamware.groovyrest.repository
import com.djamware.groovyrest.entity.Product
import org.springframework.data.repository.PagingAndSortingRepository
import org.springframework.stereotype.Repository
@Repository
interface IProductRepository extends PagingAndSortingRepository<Product, Long> {}
Open and edit com/djamware/groovyrest/repository/IVariantRepository.groovy then replace all Groovy codes with these lines of Groovy codes.
package com.djamware.groovyrest.repository
import com.djamware.groovyrest.entity.Variant
import org.springframework.data.repository.CrudRepository
interface IVariantRepository extends CrudRepository<Variant, Long> {}
Step #4: Create Groovy Service and Implementation
Now, we will put all CRUD logic in the Groovy services. We will only operate CRUD in Products that included variants too. For that, create the new packages com/djamware/groovyrest/service, com/djamware/groovyrest/service/impl and a Groovy class and interface files (com/djamware/groovyrest/service/IProductService.groovy and com/djamware/groovyrest/service/impl/ProductServiceImpl.groovy). Open and edit com/djamware/groovyrest/service/IProductService.groovy then replace all Groovy codes with this.
package com.djamware.groovyrest.service
import com.djamware.groovyrest.entity.Product
interface IProductService {
List<Product> findAll()
Product findById(Long productId)
Product saveProduct(Product product)
Product updateProduct(Long productId, Product product)
Product deleteProduct(Long productId)
}
Next, open and edit com/djamware/groovyrest/service/impl/ProductServiceImpl.groovy then replace all Groovy codes with this.
package com.djamware.groovyrest.service.impl
import com.djamware.groovyrest.entity.Product
import com.djamware.groovyrest.repository.IProductRepository
import com.djamware.groovyrest.service.IProductService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
@Service
class ProductServiceImpl implements IProductService {
@Autowired
IProductRepository productRepository
@Override
List<Product> findAll() {
productRepository.findAll()
}
@Override
Product findById(Long productId) {
productRepository.findById productId get()
}
@Override
Product saveProduct(Product product) {
product.variants?.each { it.product = product }
productRepository.save product
}
@Override
Product updateProduct(Long productId, Product product){
def existingProduct = findById(productId)
existingProduct.with {ep ->
prodName = product.prodName
prodDesc = product.prodDesc
prodPrice = product.prodPrice
prodImageUrl = product.prodImageUrl
}
def variantsToRemove = []
existingProduct.variants.each {
def v = product.variants.find { vr -> vr.id == it.id }
if (v == null) variantsToRemove.add(it)
else it.variantName = v.variantName
}
existingProduct.variants.removeAll(variantsToRemove)
product.variants.each {
if (it.id == null) {
it.product = existingProduct
existingProduct.variants.add(it)
}
}
productRepository.save existingProduct
}
@Override
Product deleteProduct(Long productId){
productRepository.deleteById productId
}
}
All CRUD operation is standard CRUD operation. The save method only uses 2 lines which save Variants and Products all at once. To save all variants from the REST request payload, simply iterate through the product object then set the product for each variant. If you don't add @JsonIgnore annotation in the many-to-one relationship in the Variant entity, the products will loop to save.
Update scenario compares the existing variants in an existing product entity with variants in a product that get from REST request payload. If not exist then the existing variants will be prepared for removal. Then compare product variants from payload with the existing product variants by ID. If found then update the variant, else then add a new variant to the product. So, in the update operation, JSON payload should be included ID, for the new variant ID value may be null.
Step #4: Create Groovy RESTful Controller
The Groovy REST controller will handle all requests and responses in JSON format. Also, specify the endpoint path for all entities and each CRUD operation. Create a new package com/djamware/groovyrest/controller and a Groovy file com/djamware/groovyrest/controller/ProductController.groovy. Open and edit that file then replace all Groovy codes with this.
package com.djamware.groovyrest.controller
import com.djamware.groovyrest.entity.Product
import com.djamware.groovyrest.service.impl.ProductServiceImpl
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("product")
class ProductController {
@Autowired
ProductServiceImpl ProductService
@GetMapping
List<Product> getAllProductList(){
ProductService.findAll()
}
@PostMapping
Product saveProduct(@RequestBody Product product){
ProductService.saveProduct product
}
@PutMapping('/{productId}')
Product updateProduct(@PathVariable Long productId, @RequestBody Product product){
ProductService.updateProduct productId, product
}
@DeleteMapping('/{productId}')
deleteProduct(@PathVariable Long productId){
ProductService.deleteProduct productId
}
@GetMapping('/{productId}')
Product getProductById(@PathVariable Long productId){
ProductService.findById productId
}
}
There's nothing special here, just the Spring Boot standard REST controller.
Step #5: Run and Test the Spring Boot Groovy PostgreSQL REST API
Before running this Spring Boot Groovy application, make sure the PostgreSQL is running. Next, run this application by type this command in the terminal.
gradle bootRun
Start the Postman, then create a POST request http://localhost:8080/api/v1/product in JSON content-type headers. Use the raw data payload as below then click the Send button.
Here is the GET method with the same request URL and headers.
Here is the GET by ID method with the same request URL with additional URL parameters and the same headers.
Here is the UPDATE method with the same request URL with additional URL parameters, headers, and body except for the variants array of object should include the ID.
Here is the DELETE method with the same request URL with additional URL parameters and the same headers.
That it's, the Spring Boot Groovy PostgreSQL CRUD REST API. You can get the full source codes from our GitHub.
That just the basic. If you need more deep learning about Groovy and Grails you can take the following cheap course:
- Mastering Grails. A Comprehensive Grails Course.
- Groovy Scripting for Developers / Testers
- Introduction to JVM Languages Clojure, Kotlin, and Groovy
Thanks!