Pure Restful web services with Spring Data Rest
spring data rest for restful webservice

Last couple of weeks I had a chance to work with spring data rest project. When I read the documentation I thought I pretty awesome.Because It has lot of features for REST API development.Here I will describe main features contains in spring data rest. At the end of this thread I will create simple rest API for product management.
What is Pure Restful Web-service ?
First we talk about what is restful web service. Restful web service is architectural style for request and response mapping in web service. There are different kind of HTTP request coming to API. But when it comes to REST API every URL have different meaning for different HTTP request methods.
Ex: /api/v1/student/ — → GET
/api/v1/student/ — → POST
/api/v1/student/ — -> PUT
And there are different response Status codes for different purposes.

As Example When we POST student object to rest API it will need to Send 204 no content status code rather than 200 status code.likewise there are standard ways to send response.If all the standard are fulfill it will become pure restful web service.
These are the core areas we are discus in this tutorial.
- Projection
- Search
- Advance Search
- Pagination & Sorting
- Spring Security
To Discuss spring data rest we used simple sales management demo. These are the entity classes. We have Product,Sale,SalesAgent.
package dev.firelimez.io.domain;
import org.springframework.data.annotation.Id;
public class Product {
@Id
private String productId;
private String name;
private String price;
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}package dev.firelimez.io.domain;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import java.util.List;
public class Sale {
@Id
private String salesId;
private String date;
@DBRef
private SalesAgent salesAgent;
@DBRef
private List<Product> products;
public String getSalesId() {
return salesId;
}
public void setSalesId(String salesId) {
this.salesId = salesId;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public SalesAgent getSalesAgent() {
return salesAgent;
}
public void setSalesAgent(SalesAgent salesAgent) {
this.salesAgent = salesAgent;
}
}package dev.firelimez.io.domain;
import org.springframework.data.annotation.Id;
import java.io.Serializable;
public class SalesAgent implements Serializable {
@Id
private String agentId;
private String name;
private String lastName;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getAgentId() {
return agentId;
}
public void setAgentId(String agentId) {
this.agentId = agentId;
}
}
So this tutorial I will use Mongo database as database reference. First you have to add these dependencies to your maven project.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Spring data rest all are written using interfaces. So first thing we have to do is create repository. All the entity classes should have repository classes. As example this is the example Repository class.
package dev.firelimez.io.repo;
import dev.firelimez.io.domain.Product;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource
import org.springframework.data.rest.core.annotation.RestResource;
import java.util.List;
@RepositoryRestResource(collectionResourceRel = "products", path = "products")
public interface ProductRepository extends MongoRepository<Product, String> {
@RestResource(path = "names", rel = "demo1")
List<Product> findByName(@Param("name") String name);
@RestResource(path = "similar", rel = "demo")
List<Product> findByNameLike(@Param("name") String name);
@Override
@RestResource(exported = true)
void delete(String productId);
}
And Final step is start program as spring boot application.
package dev.firelimez.io;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StarterApplication {
public static void main(String[] args) {
SpringApplication.run(StarterApplication.class, args);
}
}
And next step is add application.yml and configuration should be like this.
server:
port: 9008
spring:
data:
mongodb:
host: 127.0.0.1
port: 27017
database: sales_management
And that is your REST API is ready.

Projection
Projection is concept expose specific fields to rest api end points. As example in sales rest API how to get the sales agent details who are done the sales. In this case we can use projection. For that we have to add what are the properties we expect when we using projection.
Ex: sales expand projection return sales agent details with the sales object
package dev.firelimez.io.domain.projection;
import dev.firelimez.io.domain.Sale;
import org.springframework.data.rest.core.config.Projection;
import java.util.List;
@Projection(name = "expand", types = Sale.class)
interface SalesProjection {
String getSalesId();
String getDate();
SalesAgentProjection getSalesAgent();
List<ProductProjection> getProducts();
}package dev.firelimez.io.domain.projection;
import org.springframework.beans.factory.annotation.Value;
interface SalesAgentProjection {
int getAge();
String getAgentId();
@Value("#{target.name} #{target.lastName}")
String getFullName();
}
And then you can access projection data using this way.
http://localhost:9008/sales?projection=expand
Search & Advance Search
When we creating rest api biggest issue is dealing with database and based on user REST end point what we did was write query and get result from database and return to user. But spring data rest support queryless way to get result from database.
Ex: if we want to get product by product name
@RestResource(path = "names", rel = "name")
List<Product> findByName(@Param("name") String name);
These are the inbuild query methods in spring jpa repository.
Advanced Search
For advance search we have to use ExampleMatcher class and it will support advance search in spring data rest.
@Autowired
SalesAgentRepository salesAgentRepository;
@RequestMapping(method = RequestMethod.POST, path = "/api/v2/agent/search/advance", consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<SalesAgent> claimSupportTicket(@RequestBody SalesAgent salesAgent) {
ExampleMatcher exampleMatcher = ExampleMatcher.matching().withIgnoreNullValues().withIgnoreCase();
List<SalesAgent> advanceSearch = salesAgentRepository.findAll(Example.of(salesAgent, exampleMatcher));
return advanceSearch;
}
Pagination And Sorting
When we build rest API or any API the biggest problem in how to represent data in client side. And when it comes to web browsers pagination and sorting is the big issue. Lets assume we have to implement pagination and sorting we have to write methods to database get paginated data. But Spring data rest pagination and sorting is in out of box. No need to do any simple code.


Above two screens shows that pagination out of box in spring data rest.
Hope this thread helps to understand the spring data rest.