In this tutorial, we are going to see an essential crud operation on Spring Boot DataRest Example.
Spring Boot DataRest:
Spring Boot DataRest build on top of the Spring Data, and it’s taking the advantages of Spring HATEOAS. We can say that Spring Boot Data Rest combines the Spring Data and Spring HATEOS to provide the hypermedia-based Restful front end.
Technologies:
- Spring Boot 2.1.4 RELEASE
- Spring Boot Data JPA
- Spring Boot DataRest
- Lombok
- MySQL connector
- Java 8
- Maven
1. Project Structure:

2. Project Dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
As part of this example, we are going to implement a simple crud operation using spring datarest – here the data persisted in MySQL database.
3. Application properties:
We are configuring MySQL properties.
spring.datasource.driver-class-name:com.mysql.jdbc.Driver
spring.datasource.url:jdbc:mysql://localhost:3306/otp
spring.datasource.username:root
spring.datasource.password:1234
spring.jpa.show-sql=true
spring.jpa.generate-ddl=false
spring.jooq.sql-dialect=org.hibernate.dialect.MySQL5Dialect
4. Creating a Domain Object:
We are preparing Item domain object – representing an item table in the database.
package com.onlinetutorialspoint.domain;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
@Data
@NoArgsConstructor
public class Item {
@Id
@GeneratedValue
private long id;
private String name;
private String category;
}
On the above Item class, we have used @Data and @NoArgsConstructor annotations to eliminate the boilerplate code like getters and setters, for more details on Lombok you can see this document.
5. Creating ItemRepository:
The ItemRepository interface allows you to perform various CRUD operations on Item object. This repository gets CRUD operations from the PagingAndSortingRepository – it internally uses Spring Data Commons.
Apart from the basic CRUD operations, if we wanted to expose any domain related operations, you can always free to define your custom JPA operations or even use any JPQL operations inside the ItemRepository like below findByCategory().
package com.onlinetutorialspoint.repo;
import com.onlinetutorialspoint.domain.Item;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import java.util.List;
@RepositoryRestResource(path="items",collectionResourceRel = "items")
public interface ItemRepository extends PagingAndSortingRepository<Item,Long> {
List<Item> findByCategory(@Param("category") String category);
}
@RepositoryRestResource creates HATEOAS service with Spring JPA and the operations will be exposed in HATEOAS format.
6. Spring Boot Main class:
package com.onlinetutorialspoint;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootDataRestExampleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDataRestExampleApplication.class, args);
}
}
7. Run the application:
$ mvn clean install
$ mvn spring-boot:run
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.4.RELEASE)
2019-05-05 13:44:12.317 INFO 556 --- [ restartedMain] c.o.SpringBootDataRestExampleApplication : Starting SpringBootDataRestExampleApplication on DESKTOP-RN4SMHT with PID 556 (D:\work\SpringBoot-DataRest-Example\target\classes started by Lenovo in D:\work\SpringBoot-DataRest-Example)
2019-05-05 13:44:12.323 INFO 556 --- [ restartedMain] c.o.SpringBootDataRestExampleApplication : No active profile set, falling back to default profiles: default
2019-05-05 13:44:12.491 INFO 556 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2019-05-05 13:44:12.491 INFO 556 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2019-05-05 13:44:16.069 INFO 556 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2019-05-05 13:44:16.218 INFO 556 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 126ms. Found 1 repository interfaces.
2019-05-05 13:44:17.287 INFO 556 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$3afa984d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-05 13:44:17.346 INFO 556 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.hateoas.config.HateoasConfiguration' of type [org.springframework.hateoas.config.HateoasConfiguration$$EnhancerBySpringCGLIB$$ba7ae57f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-05-05 13:44:18.873 INFO 556 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-05-05 13:44:18.968 INFO 556 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-05-05 13:44:18.968 INFO 556 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.17]
2019-05-05 13:44:19.275 INFO 556 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-05-05 13:44:19.276 INFO 556 --- [ restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 6784 ms
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
2019-05-05 13:44:19.969 INFO 556 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-05-05 13:44:19.976 WARN 556 --- [ restartedMain] com.zaxxer.hikari.util.DriverDataSource : Registered driver with driverClassName=com.mysql.jdbc.Driver was not found, trying direct instantiation.
2019-05-05 13:44:20.766 INFO 556 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-05-05 13:44:21.126 INFO 556 --- [ restartedMain] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
......
......
8. Access application:
After running the application, go to http://localhost:8080/ then you would see the following JSON structure.

You can observe, there were two endpoints available /items with three different options (page, size, sort) and /profile which provides the application metadata.
Currently, there are no items in our database, let’s create some of them.

8.1 Getting all list of Items:
Now you can access all the available items using the http://localhost:8080/items/ endpoint.
{
"_embedded": {
"items": [
{
"name": "Thinking in Java",
"category": "Books",
"_links": {
"self": {
"href": "http://localhost:8080/items/1"
},
"item": {
"href": "http://localhost:8080/items/1"
}
}
},
{
"name": "Hibernate in Action",
"category": "Books",
"_links": {
"self": {
"href": "http://localhost:8080/items/2"
},
"item": {
"href": "http://localhost:8080/items/2"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/items{?page,size,sort}",
"templated": true
},
"profile": {
"href": "http://localhost:8080/profile/items"
},
"search": {
"href": "http://localhost:8080/items/search"
}
},
"page": {
"size": 20,
"totalElements": 2,
"totalPages": 1,
"number": 0
}
}
On the above output, we can observe that, along with the items list, there is one more /search endpoint available. It is used to call the custom endpoints. Let’s try to access our custom endpoint getItemByCategory();
http://localhost:8080/items/search/findByCategory?category=Books

Done!
References:
Download Source from GIT:
Happy Learning 🙂