Spring Data Rest – Repositories

Professionals 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 contain 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 the 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 implementations of the RepositoryRestConfigurer interface. And we can override the methods for our customization.

The list of methods available in the 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 the response body otherwise it will not.

3)useHalAsDefaultJsonMediaType: we need HAL(Hypermedia Links) to response or not.

configureConversionService: It will override with this Spring Default conversion service factory, if we added any new conversion services, for matters we can add to ConfigurableConversionService class.

configureValidatingRepositoryEventListener: we can configure the validator manually, for each type of event we can add the validator.

While saving the entity Spring Data will raise beforeSave, after saving 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 object mapper. Object Mapper to be used by the system.

Spring Data REST uses a RepositoryDetectionStrategy to determine if a repository will be exported as a REST resource or not. The following strategies

(enumeration values of RepositoryDiscoveryStrategies) are available:

NameDescription
DEFAULTExposes all public repository interfaces but considers @(Repository)RestResource’s exported flag.
ALLExposes all repositories independently of type visibility and annotations.
ANNOTATIONOnly repositories annotated with @(Repository)RestResource are exposed, unless their exported flag is set to false.
VISIBILITYOnly 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.

HATE OS 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 the root, we can extract the links the from root response and every child resource link can be found from their parent.

We can use the curl command to get the resource links:

After the server starts, we can hit the command curl -v http://localhost:8080 it will show all possible children 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 require 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; 
@Entit
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 provide all the methods not only for CRUD operations and also for pagination support.

Spring Data rest provides @RepositoryRestResource annotation which will expose 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 the 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 the 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 a record either using the curl command or we can use postman to create a record using the 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&#8221;
 
    },
 
    “person”: {
 
      “href”: “http://localhost:8080/people/1&#8221;
 
    }
 
  }
 
}
Response headers:
 
Location →http://localhost:8080/people/1

The response will depend upon the returnBodyOnCreate property.

The location header will give the URL to generated record.

The query for all records:

We can use the 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&#8221;
 
          },
 
          “person”: {
 
            “href”: “http://localhost:8080/people/1&#8221;
 
          }
 
        }
 
      }
 
    ]
 
  },
 
  “_links”: {
 
    “self”: {
 
      “href”: “http://localhost:8080/people&#8221;
 
    },
 
    “profile”: {
 
      “href”: “http://localhost:8080/profile/people&#8221;
 
    },
 
    “search”: {
 
      “href”: “http://localhost:8080/people/search&#8221;
 
    }
 
  },
 
  “page”: {
 
    “size”: 20,
 
    “totalElements”: 1,
 
    “totalPages”: 1,
 
    “number”: 0
 
  }
 
}
 
To get the individual records: use the GET method of http://localhost:8080/people/1
The response will look like this:
 
{
 
  “firstName”: “sravan”,
 
  “lastName”: “kumar”,
 
  “_links”: {
 
    “self”: {
 
      “href”: “http://localhost:8080/people/1&#8221;
 
    },
 
    “person”: {
 
      “href”: “http://localhost:8080/people/1&#8221;
 
    }
 
  }
 
}
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 this:
 
{
 
  “_links”: {
 
    “findByLastName”: {
 
      “href”: “http://localhost:8080/people/search/findByLastName{?name}”,
 
      “Templated”: true
 
    },
 
    “self”: {
 
      “href”: “http://localhost:8080/people/search&#8221;
 
    }
 
  }
 
}
 
In PersonRepository class we only specified one method to the records, so the response will contain only the 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 have a specified name argument that is annotated with @Param, which means for executing this method it needs a name parameter.

The Response will look like this:
 
{
 
  “_embedded”: {
 
    “People”: [
 
      {
 
        “firstName”: “sravan”,
 
        “lastName”: “kumar”,
 
        “_links”: {
 
          “self”: {
 
            “href”: “http://localhost:8080/people/1&#8221;
 
          },
 
          “person”: {
 
            “href”: “http://localhost:8080/people/1&#8221;
 
          }
 
        }
 
      }
 
    ]
 
},
 
  “_links”: {
 
    “self”: {
 
      “href”: “http://localhost:8080/people/search/findByLastName?name=kumar&#8221;
 
    }
 
  }
 
}
 
Updating an entity:
PUT method: http://localhost:8080/people/1
We can pass the JSON as a 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&#8221;
 
    },
 
    “person”: {
 
      “href”: “http://localhost:8080/people/1&#8221;
 
    }
 
  }
 
}
 
Deleting the record:
DELETE method for http://localhost:8080/people/1
It will delete the record.

Conclusion:
Using Spring Data Rest, repositories can be exposed as rest services. By writing entity class and repository interface, all CRUD and search paging and sorted related endpoints will be generated by Spring Data Rest without writing any code.

Spring Data Rest uses HAL (hypermedia links) to render their response.

Hope the experts of the 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 it in your comments and wait for their response.

Related Articles:

How to use AWS Cloud watch? Explain the concept to make a Java application development process simpler

Can Outsourcing Java Services Be An Answer To Technology Concerning Doubts Of People?

Leave a comment