Grails REST Example
In this example we shall show you how to create RESTful APIs using Grails. Exposing your application functionality to other applications is always achieved using web services. Grails provides several features that make implementing a RESTful web service in Grails easy using a RESTful resource.
Originally, web services grew in popularity as a means for system integration. But with the recent popularity of sites such as Google Maps and Amazon.com, and social networking sites like Facebook, there is an expectation that public APIs should be offered so users can create new and innovative client applications. When these clients combine multiple services from multiple providers, they are referred to as mashups. They can include command-line applications, desktop applications, web applications, or some type of widget.
In this example, we will learn how to expose your application functionality as a Representational State Transfer (REST) web service for Finacial market order gateway application to provide access to domain objects. This RESTful web service will be able to return either XML or JavaScript Object Notation (JSON), depending on the needs of the client application. This web service will also be designed to take advantage of convention over configuration for exposing CRUD functionality for any Grails domain model.
1. Project Environment
- Groovy/Grails Tool Suite
- Grails 3.0.10
- Groovy 2.4.5
- JDK 1.8
2. Grails Project
2.1. Create new project
We will start creating a new Grails 3 project using the following Grails command line.
grails create-app grails-rest-example --profile=web-api
2.2. Project Structure
build
directory where build related files like compiled classes and assembled packages are located.gradle
directory contains the Gradle Wrapper that allows you to build the project without a local Gradle installation.conf
directory contains the YAML configuration files and Logback configuration.init
directory contains Bootstrap.groovy and the new Application main class which looks like main class in Spring Boot.controllers
directory contains controllers classes.domain
directory contains location of domain classes.i18n
directory contains location of message bundles for i18n.services
directory contains location of services.util
directory contains special utility classes.src
folder is an optional directory for Groovy source files of types other than those in grails-app/*build.gradle
andgradle.properties
contain the build configuration.
3. REST Web Service
REST is not really a technology itself, but more like an architectural pattern. REST is very simple and just involves using plain XML or JSON as a communication medium, combined with URL patterns that are “representational” of the underlying system, and HTTP methods such as GET
, PUT
, POST
and DELETE
.
Each HTTP method maps to an action type. For example GET
for retrieving order, POST
for submitting new order, PUT
for updating submitted one and so on.
Grails includes flexible features that make it easy to create RESTful APIs. Creating a RESTful resource can be as simple as one line of code, as demonstrated in the next section.
3.1. Domain classes as REST resources
The easiest way to create a RESTful API in Grails is to expose a domain class as a REST resource. Simply by adding the Resource transformation and specifying a URI, your domain class will automatically be available as a REST resource in either XML or JSON formats. The transformation will automatically register the necessary RESTful URL mapping and create a controller called OrderController
.
Also, If you wish to change the default to return JSON instead of XML, you can do this by setting the formats attribute of the Resource transformation:
@Resource(uri='/api/orders', formats=['json', 'xml']) class Order { ... }
Order.groovy:
package grails.rest.example import grails.rest.* @Resource(uri='/api/orders', formats=['json', 'xml']) class Order { Long id String stock String side Double price Long size static mapping = { version false table 'orders' id column: 'id', generator:'native', params:[sequence:'order_seq'] } static constraints = { stock blank:false side blank:false price blank:false size blank:false } }
4. Running Grails Web Service
4.1. Initial Order Data
We added some orders data to BootStrap.groovy
, then we run our Grails application as a spring boot app using Application.groovy
.
BootStrap.groovy:
import grails.rest.example.Order class BootStrap { def init = { servletContext -> new Order(stock:"AAPL", side:"S", price:200, size:1000).save() new Order(stock:"IBM", side:"B", price:300, size:2000).save() new Order(stock:"JNJ", side:"T", price:150, size:3000).save() } def destroy = { } }
Application.groovy:
import grails.rest.example.Order class BootStrap { def init = { servletContext -> new Order(stock:"AAPL", side:"S", price:200, size:1000).save() new Order(stock:"IBM", side:"B", price:300, size:2000).save() new Order(stock:"JNJ", side:"T", price:150, size:3000).save() } def destroy = { } }
4.2. List Orders
Hitting the URL http://localhost:8080/api/orders
, which will render the response with the default JSON format like:
[{ "class": "grails.rest.example.Order", "id": 1, "price": 200.0, "side": "S", "size": 1000, "stock": "AAPL" }, { "class": "grails.rest.example.Order", "id": 2, "price": 300.0, "side": "B", "size": 2000, "stock": "IBM" }, { "class": "grails.rest.example.Order", "id": 3, "price": 150.0, "side": "T", "size": 3000, "stock": "JNJ" }]
Also, we can set the desired response format using the file extension in the URI, hitting the URL http://localhost:8080/api/orders.xml
, will render the response with the XML format like:
<?xml version="1.0" encoding="UTF-8"?> <list> <order id="1"> <price>200.0</price> <side>S</side> <size>1000</size> <stock>AAPL</stock> </order> <order id="2"> <price>300.0</price> <side>B</side> <size>2000</size> <stock>IBM</stock> </order> <order id="3"> <price>150.0</price> <side>T</side> <size>3000</size> <stock>JNJ</stock> </order> </list>
Also, instead of using the file extension in the URI, you can also obtain a JSON response by issuing a GET
request while using the ACCEPT
header. Here’s an example using the Unix curl tool:
curl -i -H "Accept: application/json" localhost:8080/api/orders
Output:
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Application-Context: application:development Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Wed, 06 Jul 2016 21:52:22 GMT [{"class":"grails.rest.example.Order","id":2,"price":300.0,"side":"B","size":2000,"stock":"IBM"},{"class":"grails.rest.example.Order","id":3,"price":150.0,"side":"T","size":3000,"stock":"JNJ"},{"class":"grails.rest.example.Order","id":4,"price":200.0,"side":"S","size":5000,"stock":"TWT"}]
4.3. Submit Order
We can create a new order by issuing a POST
request:
curl -i -X POST -H "Content-Type: application/json" -d '{"price": 200,"side": "S","size": 5000,"stock": "TWT"}' localhost:8080/api/orders
Output:
HTTP/1.1 201 Created Server: Apache-Coyote/1.1 X-Application-Context: application:development Location: http://localhost:8080/api/orders/4 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Wed, 06 Jul 2016 21:35:14 GMT {"class":"grails.rest.example.Order","id":4,"price":200.0,"side":"S","size":5000,"stock":"TWT"}
4.4. Update Order
We can create a new order by issuing a PUT
request:
curl -i -X PUT -H "Content-Type: application/json" -d '{"price": 210,"size": 500}' localhost:8080/api/orders/1
Output:
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Application-Context: application:development Location: http://localhost:8080/api/orders/1 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Wed, 06 Jul 2016 21:37:41 GMT {"class":"grails.rest.example.Order","id":1,"price":210.0,"side":"S","size":500,"stock":"AAPL"}
4.5. Delete Order
We can create a new order by issuing a DELETE
request:
curl -i -X DELETE localhost:8080/api/orders/1
Output:
HTTP/1.1 204 No Content Server: Apache-Coyote/1.1 X-Application-Context: application:development Content-Type: application/json;charset=UTF-8 Date: Wed, 06 Jul 2016 21:39:12 GMT
As you can see, the Resource transformation enables all of the HTTP method verbs on the resource. You can enable read-only
capabilities by setting the readOnly
attribute to true. However, In this case POST
, PUT
and DELETE
requests will be forbidden.
@Resource(uri='/api/orders', formats=['json', 'xml'], readOnly=true) class Order { ... }
5. Download the Source Code
This was an example on how to create a Grails REST web service.
You can download the full source code of this example here: GrailsRESTWebServiceExampleCode.zip
You could do ALL this alot easier by just doing the following:
grails create-app –profile org.grails.profiles:beapi:1.0.0
https://www.beapi.io/documentation