0% found this document useful (0 votes)
7 views

Unit-5(API)

Uploaded by

Eg Emma
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Unit-5(API)

Uploaded by

Eg Emma
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 35

Unit-5

Spring REST
Spring REST - An Introduction

Spring's web module carries the support for REST as well.

Spring MVC and REST


Spring Web MVC is the source of Spring REST as well. So, let us just quickly
understand the internals of Spring MVC in detail.

Spring MVC framework is based on MVC and the front controller design patterns.

The core element of Spring MVC is the Dispatcher Servlet and, that is the Front
Controller which provides an entry point for handling all the requests and forwards the
same to the appropriate components.

The Dispatcher Servlet interacts with handler mappings to determine which controller to
execute upon user request. Same way, it consults view resolver to decide the view in
which the response to be rendered.
Spring MVC Architecture
The following figure shows the working internals of Spring MVC.

1. The DispatcherServlet intercepts the incoming HTTP request.


2. An application can have multiple controllers. So, the DispatcherServlet consults
the handler mapping to decide the controller that should work on the request.
3. The handler mapping uses request URL to choose the controller. Once done, this
decision should be sent to the DispatcherServlet back.
4. After receiving appropriate controller name, DispatcherServlet sends the request
to the controller.
5. The controller receives the request from the DispatcherServlet and executes the
business logic that is available in the service layer.
6. Once done with the business logic, controller generates some information that
needs to be sent back to the client and displayed in the web browser. This
information is called as model. Now, the controller sends the model and logical
name of the view to the DispatcherServlet.
7. The DispatcherServlet passes the logical View name to the ViewResolver, which
determines the actual view.
8. The actual view is sent back to the DispatcherServlet, now.
9. The DispatcherServlet then passes the model to the View, which generates the
response.
10. The generated respose is sent back to the DispatcherServlet.
11. The DispatcherServlet returns the generated response over to the client.
Spring REST
Spring provides support for creating RESTful web services using Spring MVC. Availing
this support requires, Spring version 3.0 and above.

The REST controllers are different from MVC controllers because REST controllers'
methods return results which can be mapped to a representation rather than a view.

For this, Spring 3.0 introduced @ResponseBody annotation. So, the methods of REST
controllers that are annotated with @ResponseBody tells the DispatcherServlet that the
result of execution need not to be mapped with a view.

@ResponseBody annotation automatically converts the response to a JSON string


literal

by applying serialization on the return value of the method.

@RestController

In Spring 4.0, the @RestController annotation was introduced.

This annotation is a combination of @Controller and @ResponseBody.

This annotation when used on a REST controller class bounds all the values returned
by controller methods to the response body.

Developing Spring REST as a Boot project still simplifies the developers' job as a lot of
things are auto-configured.

In our course, we will learn, how to develop a Spring REST application using Spring
Boot.
Spring MVC vs Spring REST
The below table summarizes the differences between Spring MVC and Spring REST.

Creating a Spring REST Controller,


Spring REST Internals

Spring Web MVC module is the source of Spring REST as well.

Working Internals of Spring REST:

Spring REST requests are delegated to the DispatcherServlet that identifies the specific
controller with the help of handler mapper. Then, the identified controller processes the
request and renders the response. This response, in turn, reaches the dispatcher
servlet and finally gets rendered to the client.

Here, ViewResolver has no role to play.

Steps involved in exposing the business functionality as a


RESTful web service
What are the steps involved in exposing business functionality as a RESTful web
service?

Step 1: Create a REST Resource


Step 2: Add the service methods that are mapped against the standard HTTP methods

Step 3: Configure and deploy the REST application

Since we are going to develop REST applications using Spring Boot, lot of
configurations needed in Step-3 can be avoided as Spring Boot takes care of the same.

Creating a REST Resource

Any class that needs to be exposed as a RESTful resource has to be annotated with
@RestController

@RestController

 This annotation is used to create REST controllers.


 It is applied on a class in order to mark it as a request handler/REST resource.
 This annotation is a combination of @Controller and @ResponseBody
annotations.
 @ResponseBody is responsible for the automatic conversion of the response to
a JSON string literal. If @Restcontroller is in place, there is no need to use
@ResponseBody annotation to denote that the Service method simply returns
data, not a view.
 @RestController is an annotation that takes care of instantiating the bean and
marking the same as REST controller.
 It belongs to the package,
org.springframework.web.bind.annotation.RestController

Spring REST

@RequestMapping
 This annotation is used for mapping web requests onto methods that are
available in the resource classes. It is capable of getting applied at both
class and method levels. At method level, we use this annotation mostly to
specify the HTTP method.

//Functionality goes here

Adding request handler methods


REST resources have handler methods with appropriate HTTP method mappings to handle the
incoming HTTP requests. And, this method mapping usually happens with annotations.

For example, in the Infytel application, developed for a telecom company, we would like to
create a REST resource that can deal with operations like creating, deleting, fetching and
updating the customers. Here comes the summary of HTTP operations and the corresponding
mappings. An important point to be noted here is, Infytel is a Spring Boot application .
CustomerController with handler methods
Following is the code of a REST controller that has several handler methods with
appropriate method mapping annotations.

}
// Fu

Configuring a REST Controller


(Since we are creating a Spring Boot application with spring-boot-starter-web
dependency, we need not pay much focus on the configurations.

 spring-boot-starter-web dependency in the pom.xml will provide the


dependencies that are required to build a Spring MVC application including the
support for REST. Also, it will ensure that our application is deployed on an
embedded Tomcat server and we can replace this option with the one that we
prefer based on the requirement.

 Application class is simply annotated with @SpringBootApplication


@SpringBootApplication is a convenient annotation that adds the following:

 @Configuration marks the class as a source where bean definitions can


be found for the application context.
 @EnableAutoConfiguration tells Spring Boot to start adding beans based on
the classpath and property settings.
 @ComponentScan tells Spring to look for other components, configurations,
and, services in the packages being specified.

And, one more point to be added here is,

@EnableWebMvc is used explicitly in a regular Spring MVC application. But, Spring


Boot adds it automatically when it sees spring-webmvc on the classpath. This marks the
application as a web application and enables the key behaviors such as setting up
the DispatcherServlet etc.

The main() method uses Spring Boot’s SpringApplication.run() method to launch an


application. Notice, we haven't written any web.xml file. This web application uses 100%
pure Java-based configuration and we need not deal with any configurations (no XML
files except pom.xml) pertaining to infrastructure.

@RequestBody and ResponseEntity


@RequestBody
@RequestBody is the annotation that helps map our HTTP request body to a Java
DTO. And, this annotation has to be applied on the local parameter (Java DTO) of the
request method.

Whenever Spring encounters @RequestBody, it takes the help of the registered


HttpMessageConverters which will help convert the HTTP request body to Java
Object depending on the MIME type of the Request body.

Example: In the below code snippet, the incoming HTTP request body is deserialized to
CustomerDTO. If the MIME type of the incoming data is not mentioned, it will be
considered as JSON by default and Spring will use the JSON message converter to
deserialize the incoming data.
We can specify the expected Mime type using the consumes attribute of the HTTP
method matching annotation

Example: The above code is equivalent to the below code that promotes the application
of the attribute, consumes.

consumes attribute can be supplied with a single value or an array of media types as
shown below

ResponseEntity

How to send a Java Object in the response?

Scenario-1

Java objects can be returned by the handler method just like how the normal Java
methods can return an object.

Example: In the below example, the fetchCustomer() returns a list of Customer Objects.
This list will be converted by Spring's message converter to JSON data.
Scenario-2

We can specify the MIME type, to which the data to be serialized, using
the produces attribute of HTTP method matching annotations

Just like consumes, the attribute, produces can also take a single value or an array of
MIME types

Setting response using ResponseEntity

While sending a response, we may like to set the HTTP status code and headers .To
help achieving this, we can use ResponseEntity class.

ResponseEntity<T> Will help us add a HttpStatus status code and headers to our
response.

Example: In the below code snippet, createCustomer() method is returning a String


value and setting the status code as 200.
As shown in the code snippet, we can use the static functions of ResponseEntity class
that are available for standard Http codes (ok() method is used, here). One more way of
setting response entity is as follows.

Example:

ResponseEntity - Constructors and Methods


Below is the list of constructors available to create ResponseEntity
Note: There are some ResponseEntity methods available as well.

Parameter Injection, Usage of @PathVariable,


@RequestParam and @MatrixVariable
URI Parameter Injection Annotations

it is not always that the client prefers sending the data as request body. The client can
even choose to send the data as part of the request URI. For example, if the client feels
that the data is not sensitive and doesn't need a separate channel to get
transferred. So, how to receive this kind of data that appears in the URI.

Before we look into the ways to extract the URI data, we will have a look at the
formal categorization of the data that appear in the request URI.

1. Query Parameter
2. Path Variables
3. Matrix Variables

Query Parameter

 Query parameters or request parameters usually travel with the URI and are
delimited by question mark.
 The query parameters in turn are delimited by ampersand from one another.
 The annotation @RequestParam helps map query/request parameters to the
method arguments.
 @RequestParam annotation expects the name that it holds to be similar to the
one that is present in the request URI.This makes the code tightly coupled with
the request URI.

Example: Assume, there is a RestController called CallDetailsController that has a


service method to return the call details of a specific phone number on a particular date.
The service method here, takes the phoneNo of the customer and the date as query
/request parameters.

Example URI:
Path Variables

 Path variables are usually available at the end of the request URIs delimited by
slash (/).
 @Pathvariable annotation is applied on the argument of the controller method
whose value needs to be extracted out of the request URI.
 A request URI can have any number of path variables.
 Multiple path variables require the usage of multiple @PathVariable annotations.
 @Pathvariable can be used with any type of request method. For example, GET,
POST, DELETE, etc.,

We have to make sure that the name of the local parameter (int id) and the placeholder
({id}) are same. Name of the PathVariable annotation's argument (@PathVarible("id"))
and the placeholder ({id}) should be equal, otherwise.
Matrix variable
 These variables may appear in the middle of the path unlike query parameters
which appear only towards the end of the URI.
 Matrix variables follow name=value format and use semicolon to get delimited
from one other matrix variable.
 A matrix variable can carry any number of values, delimited by commas.
 @MatrixVariable is used to extract the matrix variables.

See how the matrix variable, localRate gets extracted in the controller method.

Code:
@MatrixVariable(pathVar="query") Map<String, List<Integer>> map :The code
snippet mentions that all the matrix variables that appear in the path segment of
name query should be stored in a Map instance called map. Here, the map's key is
nothing but the name of the matrix variable and that is nothing but localRate. And,
the value of the map is a collection of localRates (1,4) of type Integer.

Note:If the matrix variable appears towards the end of the URI as in the below example,

we can use the following approach to read the matrix variable.

Exception Handling
Exception Handling - An Introduction
Handling exceptions will make sure that the entire stack trace is not thrown to the end-
user which is very hard to read and, possesses a lot of security risks as well. With
proper exception handling routine, it is possible for an application to send customized
messages during failures and continue without being terminated abruptly.

In simple words, we can say that exception handling makes any application robust.

@ExceptionHandler is a Spring annotation that plays a vital role in handling


exceptions thrown out of handler methods(Controller operations). This annotation can
be used on the

 Methods of a controller class. Doing so will help handle exceptions thrown out of
the methods of that specific controller alone.
 Methods of classes that are annotated with @RestControllerAdvice. Doing so will
make exception handling global.

The most common way is applying @ExceptionHandler on methods of the class that is
annotated with @RestControllerAdvice. This will make the exceptions that are thrown
from the controllers of the application get handled in a centralized way. As well, there is
no need for repeating the exception handling code in all the controllers, keeping the
code more manageable.
Example - Exception with no handler method
Example: An online telecom app called Infytel exposes its functionalities as RESTful
resources. And, CustomerController is one among such resources that deal with the
customers of Infytel. CustomerController has a method to delete a customer based on
the phone number being passed.

Below is the code snippet for the same.

What if the phoneNo does not exist and the code throws NoSuchCustomerException?

If no Exception handler is provided, Spring Boot provides a standard error message as


shown below.

Example - Exception with handler method

In case, a customized error message that is easy to understand has to be provided, we


need to

 Create a class annotated with @RestControllerAdvice


 Have methods annotated with @ExceptionHandler(value=NameoftheException)
which takes the exception class as the value for which the method is the handler
We can have multiple methods in the Advice class to handle exceptions of different
types and return the custom messages accordingly.

Example: Below is the RestControllerAdvice class that holds a method which handles
NoSuchCustomerException by returning a customized error message.

Data Validation
Need for validation

Some times, the RESTful web service might need data in certain standard that should
pass through specific constraints.

What if the data is not in the format as needed by the RESTful service?

By default, Spring Boot provides some implementation for validation

 415 - Unsupported Media Type : If the data is sent in a different format other than
what is expected(eg:XML instead of JSON)
 400 - Bad Request : If JSON data is not in proper format, for example.

Some times, we might send valid format and structure, but with missing data. Still, the
request gets processed. In such situations, it becomes even more important to validate
the data.

Hibernate Validator, is one of the implementations of the bean validation API. Let us
see, how to use the Validation API to validate our incoming data.

Bean Validation API provides a number of annotations and most of these annotations
are self explanatory.

 Digits
 Email
 Max
 Min
 NotEmpty
 NotNull
 Null
 Pattern

Applying validation on the incoming data

Let us apply validation on the customer data that comes to the createCustomer()
method of CustomerController. Infytel expects the name field not to be null and the
email field to be of proper email format.

Have a look at the usage of @NotNull and @Email on the fileds, name and email
respectively.

Adding the constraints simply on the bean will not carry out validation. In addition, we
need to mention that validation is required while the JSON data is deserialized to
CustomerDTO and get the validation error, if any, into
org.springframework.validation.Errors object. This can be done by applying @Valid
annotation on the handler method argument which captures the CustomerDTO object
as shown below.We can inject the Errors object too into this method.
Discussion on how the validation takes place
@Valid @RequestBody CustomerDTO customerDTO - indicates that CustomerDTO
should be validated before being taken.

Errors - indicates the violations, if any, to get stored in Errors object.

Finally, the business logic will be divided into two courses of actions. That is, what
should be done when there are no validation errors. And, what should be done,
otherwise.

If there are errors:

Collect all the errors together as a String.

Set the String that contains errors in the message field and appropriate error code in the
errorCode field of ErrorMessage.

Finally, return the ResponseEntity that is set with the ErrorMessage object.
The ErrorMessage class:

. If there are no errors, invoke the service layer to create the customer and return the
response back to the client.

Rich set of annotations

We are done dealing with validating the incoming objects/DTOs. Also, we finished
traversing a set of annotations that impose validation on the individual fields/attributes of
the DTO.

Apart from the annotations that we discussed, we have few other interesting
annotations in place. For example,

@PastOrPresent

@Past

@Future

@FutureOrPresent
@DateTimeFormat - part of org.springframework.format.annotation unlike other
annotations being mentioned here which are part of
standard javax.validation.constraints

These annotations can only be applied on the fields/attributes of type, date/time,


for example, LocalDate/LocalTime.

One more interesting annotation that needs a mention here is @Positive which is
used to make sure a number should possess only positive values for example, cost of
an article.

Last but not the least to be brought in for discussion is @NotBlank which makes
sure that the string is not null and the trimmed length should be greater than zero.

Further Reading : Explore javax.validations.constraints API to get the complete list of


validation annotations that can be applied on the fields/attributes.

URI parameter validation

Like how it is important to validate the incoming objects/DTOs, it is essential to validate


the incoming URI parameters as well. For example, when the customer details need to
be deleted based on the phone number and if the same is reaching the REST endpoint
as URI parameter (path variable, for example), it becomes essential that the URI
parameter, phone number should also be validated (should be of 10 digits, for
example).

The code snippet given below helps serving the purpose discussed above.

Here, the message that should be rendered during the validation failure need not be
hard-coded always. It can be fetched from the external property file as well and the
name of the file is ValidationMessages.properties that Spring Boot searches for. If the
file name is other than ValidationMessages.properties, MessageSource and
LocalValidatorFactoryBean need to be configured in the bootstrap class.

One important thing that needs attention while validating the URI parameters
is, @Validated.

The controller where the URI parameter validation is carried out should be annotated
with @Validated. The validation on URI parameters will not be triggered, otherwise.
Here, the CustomerController has validations pertaining to phoneNo that is received as
URI parameter (DELETE and UPDATE). So, @Validated annotation needs to be
applied on the same as follows.

Handling validation failures in a centralized way

So, we know how to apply validation on the incoming objects and URI parameters.

Now, its time to handle the validation failures, if any. We have attempted to handle the
validation exceptions with respect to the incoming DTOs in the earlier sample code. But,
that was not in a centralized way. Only, the controller was coded to do so. This way of
coding will lead to code duplication and the code will not be manageable as well.

So, the code that should be reached out during validation failures should also be made
centralized as how we did for exceptions. We can enhance
the ExceptionControllerAdvice class which is annotated with @RestControllerAdvice
by adding exception handlers for

 MethodArgumentNotValidException - Validation failures in DTOs


Creating a REST Client

RestTemplate

There are situations where a Spring REST endpoint might be in need of contacting
other RESTful resources. Situations like this can be hadled with the help of REST client
that is available in the Spring framework. And, the name of this REST client
is RestTemplate.

RestTemplate has a wonderful support for standard HTTP methods.

The methods of the RestTemplate need to be provided with the absolute URI where the
service can be found, input data, if any and, the response type that is expected out of
the service.

Calling a RESTful service of HTTP request method Get:

The following code snippet shows how to consumes a RESTful service exposed by url
:http://localhost:8080/infytel/customers using HTTP GET .

Calling a RESTful service of HTTP request method Post:

URI of the service:http://localhost:8080/infytel/customers


Versioning a Spring REST endpoint
Versioning a service becomes important when we want to create a new version of an
already existing service. But at the same time, we need to support the earlier version as
well, to ensure backward compatibility.

There are different ways of achieving API versioning such as

 URI versioning
 Request Parameter Versioning
 Custom Header Versioning
 Accept Header versioning

URI versioning

URI versioning involves different URI for every newer version of the API.

Example: There is a need for two versions of functionality that fetches the plan
details of Infytel telecom application. And, this fetch operation is based on the planId
being passed as a path variable.

version-1: Fetches the complete plan details that include plainId, planName,
localRate and nationalRate

version-2: Fetches only the localRate and nationalRate.

Below is the URI proposed to be used

Now, let us look at how the handler method can be written.

For Version-1
For Version-2

Observe, how a functionality with two different versions or approaches is made


available in a REST resource. Also, focus on how the consumers call the different
versions of the API method using the URIs that carry information about versioning.

Versioning with Custom Headers

This type of versioning requires the inclusion of custom headers in the request URI to
map to the correct version of the API endpoint.

Let us take the service that fetches plan details, here as well.

Below is the URI proposed to be used

Now, let us look at how the handler method can be written

For Version-1
For Version-2

Observe, how a functionality with two different versions or approaches is made


available in a REST resource. Also, focus on how the consumers call the different
versions of the API method using the URIs that carry information about versioning as
part of the request headers.

Accept Header Versioning


Accept Header Versioning approach is one other way of versioning the API methods
that insists the usage of Accept Header in the request

Now, let us look at how the handler method can be written


For Version-1

For Version-2

Observe, how a functionality with two different versions or approaches is made


available in a REST resource. Also, focus on how the consumers call the different
versions of the API method using the URIs that carry information about versioning as
part of the request headers named, accept. One more important thing to be noted here
is the inclusion of custom MIME type.

Request Parameter versioning


Request parameter versioning can be achieved by providing the request parameter in
the URI that holds the version details.

Now, let us look at how the handler method can be written

For Version-1
For Version-2

Observe, how a functionality with two different versions or approaches is made


available in a REST resource. Also, focus on how the consumers call the different
versions of the API method using the URIs that carry information about versioning in the
form of request parameter.

Enabling CORS in Spring REST


Why CORS?
Typically, scripts running in a web application of one origin (domain) cannot
have access to the resources of a server available at a different origin. If the clients of
different origins try to access the REST endpoints of an application, CORS error will be
thrown simply. And, below is a sample of the same.

Look at the image below, which depicts the request for resources by the clients of the
same origin and different origins as well .
How to enable CORS?

Cross-origin calls can be enabled for Spring REST resources in three ways by applying:

 CORS configuration on the REST controller methods


 CORS configuration on the REST controller itself
 CORS configuration globally (common to the entire application)

CORS configuration on controller methods:

In this style, we need to apply @CrossOrigin on the handler method.

Here, the annotation, @CrossOrigin enables cross-origin requests only for the specific
handler method.

By default, it allows all origins, all headers, all HTTP methods specified in
the @RequestMapping annotation. Also, a lot more other defaults are available.

We can customize this behavior by specifying the value for the following attributes that
are available with Http method mapping annotations (@GetMapping, @PostMapping,
etc.,)

 origins - list of allowed origins to access the method


 methods - list of supported HTTP request methods
 allowedHeaders - list of request headers which can be used during the request
 exposedHeaders - list of response headers which the browser can allow the
clients to access
 allowCredentials - determines whether the browser can include cookies that
are associated with the request

Example:
Global CORS configuration:

As an alternative to fine-grained, annotation-based configuration, we can also go for


global CORS configuration as well.

Look at the code below. The starter class has been modified to implement
WebMvcConfigurer and override addCorsMappings() method that takes the
CorsRegistry object as argument using which we can configure the allowed set of
domains and HTTP methods as well.

Securing Spring REST endpoints


Need for securing a RESTful service arises when the authorized entities alone have
to access to the end points.
Securing REST APIs here, follows the same steps involved in securing any other web
application that is developed using Spring Boot. As we all know, Spring Boot minimizes
configuration and that goes good with security as well.

We can secure the Spring REST endpoints using,

 Basic Authentication (one that will be used in our course)


 OAUTH2 authentication

Basic Authentication:

When client requests for a protected resource, server demands the client to supply the
authentication credentials.

Client will get the requested resource only when the credentials pass authentication at
server side.

Steps involved in basic authentication are shown below.

With Basic Authentication in place, clients send their Base64 encoded credentials with
each request using HTTP Authorization header.
This type of authentication does not mandate us to have any Login page which is the
very standard way of authenticating the client requests in any web application. In
addition, there is no need to store the credentials or any related info in the session.

Each request here, is treated as an independent request which in turn promotes


scalability.

Our example for implementing security will follow this approach.

Enabling Basic Authentication

Enabling security in a Spring Boot application needs the inclusion of the following
dependency as the very first step.

This will include the SecurityAutoConfiguration class – containing the initial or default
security configuration.

By default, authentication gets enabled for the whole application.

There are some predefined properties as shown below which needs to be configured in
the application.properties file.

 spring.security.user.name
 spring.security.user.password

If there is no password configured using the predefined


property spring.security.user.password, Spring Boot generates a password in a
random fashion during the application start. And, the same will be found in the console
log.

Following steps are required only when we need to customize the security related
aspects.
Need to override the below methods

You might also like