Experts of Java outsourcing company are sharing this post with an intention to make you learn about Spring Data Rest and repositories. You will also learn about the customization methods used for Spring Data Rest.
Technology: Spring Data Rest is the framework on top of Spring Data Framework for producing the Rest API.It uses Spring MVC and Spring Data frameworks to export all functionalities through Rest API, and integrates the resources with hyper media based functionality using Spring Hateos automatically.
Getting Started:
Spring Data Rest is implemented as a plugin for Spring based applications,we can easily integrate this with spring.
Prerequisite:
Integrating with Spring Boot Applications:
- Maven Dependency:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency>
- Gradle Dependency:
compile("org.springframework.boot:spring-boot-starter-data-rest")
Integrating with Spring MVC applications:
- Gradle Dependency:
Compile ("org.springframework.data:spring-data-rest-webmvc:2.5.2.RELEASE")
- Maven Dependency:
<Dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-rest-webmvc</artifactId> <version>2.5.2.RELEASE</version> </dependency>
Configuring Spring Data Rest:
Spring Data Rest provides RepositoryRestMvcConfiguration configuration java file which will contains all beans required for Spring Data Rest.
We need to import RepositoryRestMvcConfiguration class to our application configuration so that Spring Data Rest will bootstrap.
This step is not needed if we are using Spring Boot’s auto-configuration.
Spring Boot will automatically enable Spring Data REST if we include spring-boot-starter-data-rest and either in list of dependencies, and application is flagged with either @SpringBootApplication or @EnableAutoConfiguration.
We can also customize the Spring Data Rest default behavior in two ways:
- We can implement RepositoryRestConfigurer
- We can extend the RepositoryRestConfigurerAdapter It is one of the empty implementation of RepositoryRestConfigurer interface. And we can override the methods for our customization.
The list of methods available in RepositoryRestConfigurer interface:
public interface RepositoryRestConfigurer { void configureRepositoryRestConfiguration(RepositoryRestConfiguration config); void configureConversionService(ConfigurableConversionService conversionService); void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener); void configureExceptionHandlerExceptionResolver(ExceptionHandlerExceptionResolver exceptionResolver); void configureHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters); void configureJacksonObjectMapper(ObjectMapper objectMapper); }
Using configureRepositoryRestConfiguration we can override the baseUri, pageSize, maxPagesize, and pageParamName,sortParamName,limitParamName,and defaultMediaType.
Using this also we can configure
1)returnBodyOnCreate: if the object is created do we need to send the created object in response body or not. If this property is true then it will send the created object in response body otherwise it will not.
2) returnBodyOnUpdate: If the object is updated do we need to send the updated object in response body or not. If this property is true then it will send the updated object in response body otherwise it will not.
3)useHalAsDefaultJsonMediaType: we need to HAL(Hyper media Links) to response or not.
configureConversionService: It will override with this Spring Default conversion service factory, if we added any new conversion services, formatters we can add to ConfigurableConversionService class.
configureValidatingRepositoryEventListener: we can configure the validator manually, each type of event we can add the validator.
While saving the entity Spring Data will raise beforeSave, afterSave events,what are the different validators we need to invoke for each event.
configureExceptionHandlerExceptionResolver: The default exception resolver on which we can add custom argument resolvers.
configureHttpMessageConverters: we can configure all Http Message Converters.
configureJacksonObjectMapper: we can customize the objectmapper. objectMapper to be used by the system.
Spring Data REST uses a RepositoryDetectionStrategy to determine if a repository will be exported as REST resource or not. The following strategies
(enumeration values of RepositoryDiscoveryStrategies) are available:
Name | Description |
DEFAULT | Exposes all public repository interfaces but considers @(Repository)RestResource’s exported flag. |
ALL | Exposes all repositories independently of type visibility and annotations. |
ANNOTATION | Only repositories annotated with @(Repository)RestResource are exposed, unless their exported flag is set to false. |
VISIBILITY | Only public repositories annotated are exposed. |
Customizing the base URI:
- spring data rest provides RepositoryRestProperties class, using this we can customize the properties.
Eg: spring.data.rest.basePath=/api
- We can create a configuration class extending RepositoryRestConfigurerAdapter
@Component Public class RepositoryRestConfigurer extends RepositoryRestConfigurerAdapter { @Override Public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.setBasePath("/api"); } }
Resource discoverability: The main advantage of HATEOAS is that resources should be discoverable through the publication of links that point to the available resources.
HATEOS has some standards to show how to represent links in JSON format, by default Spring Data Rest uses HAL to render its responses. Resource Discovery will start from root, we can extract the links from root response and every child resource link can be found from their parent.
We can use curl command to get the resource links:
After the server starts, we can hit the command curl -v http://localhost:8080 it will show the all possible child to it.
Sample response will be:
* Rebuilt URL to: http://localhost:8080/ * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > GET / HTTP/1.1 > Host: localhost: 8080 > User-Agent: curl/7.50.0 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/hal+json; charset=UTF-8 < Transfer-Encoding: chunked < Date: Fri, 22 Jul 2016 17:17:59 GMT < { "_links”: { "people”: { "Href”: "http://localhost:8080/people{?page,size,sort}", "templated”: true }, "profile”: { "Href" : "http://localhost:8080/profile" } } }* Connection #0 to host localhost left intact
Creating Spring Data Rest applications:
We need to create a model class and mark it as an entity.
Import javax.persistence.Entity; Import javax.persistence.GeneratedValue; Import javax.persistence.GenerationType; Import javax.persistence.Id; @Entity public class Person { @Id @GeneratedValue (strategy = GenerationType.AUTO) privatelong id; private String firstName; Private String lastName; public String getFirstName() { returnfirstName; } Public void setFirstName (String firstName) { this.firstName = firstName; } public String getLastName() { returnlastName; } public void setLastName(String lastName) { this.lastName = lastName; } }
And we can use PagingAndSortingRepository which is provided by Spring Data, it will provides all the methods not only for CRUD operations and also for pagination support.
Spring Data rest provides @RepositoryRestResource annotation which will exposes all public methods which are marked with exported=true are exported as Rest API endpoints.
Creating Spring Data Rest Repositories:
Import java.util.List; Import org.springframework.data.repository.PagingAndSortingRepository; Import org.springframework.data.repository.query.Param; Import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource(collectionResourceRel = "people", path = "people") publicinterface PersonRepository extends PagingAndSortingRepository<Person, Long> { public List<Person> findByLastName(@Param("name") String name); }
RepositoryRestResource annotation will create endpoints for all the CRUD and as well as paging and sorting endpoints.
Creating a Main class for Spring Boot:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
1) GET: to get the data for entity.
2) POST: saving the entity.
3) PUT: updating the entity.
4) DELETE: deleting the entity.
If we run the application and when we run the curl command for people:
E:\curl>curl -v http://localhost:8080/people * Trying ::1... * Connected to localhost (::1) port 8080 (#0) > GET /people HTTP/1.1 > Host: localhost: 8080 > User-Agent: curl/7.50.0 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/hal+json;charset=UTF-8 <Transfer-Encoding: chunked < Date: Fri, 22 Jul 2016 17:35:28 GMT < { "_embedded" : { "people" : [ ] }, "_links”: { "self”: { "href" : "http://localhost:8080/people" }, "profile" : { "href”: "http://localhost:8080/profile/people" }, "search" : { "href" : "http://localhost:8080/people/search" } }, "page" : { "size" : 20, "totalElements" : 0, "totalPages" : 0, "number" : 0 } }* Connection #0 to host localhost left intact
Creating a Person record:
We can create record either using curl command or we can use postman to create a record using POST method with http://localhost:8080/people.
curl -i -X POST -H “Content-Type: application/json” -d ‘{ “firstName” : “sravan”, “lastName” : “Kumar” }’ http://localhost:8080/people
Response from endpoint :
{ "firstName": "sravan", "lastName": "kumar", "_links": { "self": { "href": "http://localhost:8080/people/1" }, "person": { "href": "http://localhost:8080/people/1" } } }
Response headers:
Location →http://localhost:8080/people/1
Response will depends upon returnBodyOnCreate property.
Location header will give the url to generated record.
Query for all records:
We can use same url http://localhost:8080/people GET method to get the data.
The response will look like this:
{ "_embedded": { "people": [ { "firstName": "sravan", "lastName": "kumar", "_links": { "self": { "href": "http://localhost:8080/people/1" }, "person": { "href": "http://localhost:8080/people/1" } } } ] }, "_links": { "self": { "href": "http://localhost:8080/people" }, "profile": { "href": "http://localhost:8080/profile/people" }, "search": { "href": "http://localhost:8080/people/search" } }, "page": { "size": 20, "totalElements": 1, "totalPages": 1, "number": 0 } }
To get the individual records: use GET method of http://localhost:8080/people/1
Response will look like this:
{ "firstName": "sravan", "lastName": "kumar", "_links": { "self": { "href": "http://localhost:8080/people/1" }, "person": { "href": "http://localhost:8080/people/1" } } }
Searching for entity:
Listing all possible search endpoints:
GET method of http://localhost:8080/people/search
It will show the all possible methods that we specified in Repository Resource.
Sample response will look like:
{ "_links": { "findByLastName": { "href": "http://localhost:8080/people/search/findByLastName{?name}", "Templated": true }, "self": { "href": "http://localhost:8080/people/search" } } }
In PersonRepository class we only specified one method to the records, so response will contain only search method.
Searching for entities using findByLastName endpoint:
Ex: http://localhost:8080/people/search/findByLastName?name=kumar
If we remembered the method argument for findByLastName we are specified name argument and which is annotated with @Param, means for executing this method it needs name parameter.
Response will look like this:
{ "_embedded": { "People": [ { "firstName": "sravan", "lastName": "kumar", "_links": { "self": { "href": "http://localhost:8080/people/1" }, "person": { "href": "http://localhost:8080/people/1" } } } ] }, "_links": { "self": { "href": "http://localhost:8080/people/search/findByLastName?name=kumar" } } }
Updating an entity:
PUT method : http://localhost:8080/people/1
We can pass the json as request body it will update the record.
Sample request body:
{ "firstName" : "sravan1", "lastName" : "kumar1" } Sample response will look like this: { "firstName": "sravan1", "lastName": "kumar1", "_links": { "self": { "href": "http://localhost:8080/people/1" }, "person": { "href": "http://localhost:8080/people/1" } } }
Deleting the record:
DELETE method for http://localhost:8080/people/1
It will delete the record.
Conclusion:
using Spring Data Rest, repositories can be exposes as rest services. By writing entity class and repository interface, all CRUD and search, paging and sorted related endpoints will be created by Spring Data Rest without writing any code.
Spring Data Rest uses HAL (hyper media links) to render their response.
Hope the experts of java outsourcing company have made you clear about the concept of Spring Data Rest. If you want to ask anything related to the subject, mention in your comments and wait for their response.
Tags: Java, Java outsorcing, Spring Data
1 Comment