Spring Boot Restful API Documentation With Swagger 2

What the difference between REST API and RESTful API?

What the difference between REST API and RESTful API?

Representational state transfer (REST) is a style of software architecture. As described in a dissertation by Roy Fielding, REST is an "architectural style" that basically exploits the existing technology and protocols of the Web. RESTful is typically used to refer to web services implementing such an architecture.

The short answer is that REST stands for Representational State Transfer. It’s an architectural pattern for creating web services. A RESTful service is one that implements that pattern.

The long answer starts with “sort of” and “it depends” and continues with more complete definitions.

Defining REST

Let’s start by defining what REST is and is not. For some, REST means a server that exchanges JSON documents with a client over HTTP. Not only is that not a complete definition, but it’s also not always true. The REST specification doesn’t require HTTP or JSON. (The spec doesn’t mention JSON or XML at all.)

The Origins of REST

Roy Fielding introduced the REST architectural pattern in a dissertation he wrote in 2000. The paper defines a means for clients and servers to exchange application data. A key feature is that the client doesn’t need to know anything about the application in advance. The link is to chapter five of his paper. While the entire dissertation describes the hows and whys of REST, that chapter defines the architectural pattern.

Fielding doesn’t mandate specific requirements. Instead, he defines REST regarding constraints and architectural elements.

REST’s Architectural Constraints

Here is a summary of the constraints.

  • Client-server – REST applications have a server that manages application data and state. The server communicates with a client that handles the user interactions. A clear separation of concerns divides the two components. This means you can update and improve them in independent tracks.
  • Stateless – servers don’t maintain any client state. Clients manage their application state. Their requests to servers contain all the information required to process them.
  • Cacheable – servers must mark their responses as cacheable or not. So, infrastructures and clients can cache them when possible to improve performance. They can dispose of non-cacheable Information, so no client uses stale data.
  • Uniform interface – this constraint is REST’s most well known feature or rule, depending on who you ask. Fielding says “The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components.” REST services provide data as resources, with a consistent namespace. We’ll cover this in detail below.
  • Layered system – components in the system cannot “see” beyond their layer. So, you can easily add load-balancers and proxies to improve security or performance.

A RESTful service is more than a web server that exchanges JSON, or any other, documents. These constraints work together to create a very specific type of application.

Applying the Constraints

First, the client-server, layered systems and stateless constraints combine to form an application with solid boundaries and clear separations between concerns. Data moves from the server to the client upon request. The client displays or manipulates it. If the state changes, the client sends it back to the server for storage. Fielding specifically contrasts REST with architectures that use distributed objects to hide data from other components. In REST, the client and server share knowledge about data and state. The architecture doesn’t conceal data, it only hides implementations.

The cacheable and uniform state constraints go one step further. Application data is available to clients in a clear and consistent interface and cached when possible.

So, that’s the technical definition of REST. What does it look like in the real world?

RPC Over HTTP vs. RESTful

Often when someone says that a service “isn’t REST,” they’re looking at the URIs or how the service uses HTTP verbs. They’re referring to REST’s presentation of data as a uniform set of resources.

This distinction is sometimes framed as a difference between remote procedures calls (RPC) and REST. Imagine a web service for listing, adding, and removing, items from an e-commerce inventory.

In one version, there’s a single URL that we query with HTTP GETs or POSTs.  You interact with the service by POSTing a document, setting the contents to reflect what you want to do.

Add new items with a POST with a NewItem:

POST /inventory HTTP/1.1
 
{
    "NewItem": {
          "name": "new item",
          "price": "9.99",
          "id": "1001"
      }
}    

Query for items with a POST and an ItemRequest:

POST /inventory HTTP/1.1
 
{
    "ItemRequest": {
          "id": "1001"
      }
}

Some implementations accept a request for a new item with a get, too.

POST /inventory?id=1001 HTTP/1.1

We also change or delete items with a POST and an ItemDelete or ItemUpdate.

POST /inventory HTTP/1.1
 
{
    "ItemDelete": {
          "id": "1001"
      }
}

This isn’t REST. We’re not exchanging the state of resources. We’re calling a function with arguments that happen to be in a JSON document or URL arguments.

A RESTful service has a URI for each item in the inventory.

So, adding a new item would look like the example above.

POST /item HTTP/1.1
 
{
    "Item": {
          "name": "new item",
          "price": "9.99",
          "id": "1001"
      }
}    

But the similarities end there. Retrieving an item is always a GET:

GET /item/1001 HTTP/1.1   

Deleting is a DELETE:

DELETE /item/1001 HTTP/1.1  

Modifying an item is a PUT:

POST /inventory HTTP/1.1
 
{
    "Item": {
          "name": "new item",
          "price": "7.99",
          "id": "1001"
      }
}    

The difference is important. In REST, operations that use distinct HTTP actions. These verbs correspond directly to the activity on the data. GET, POST, PUT, DELETE and PATCH all have specific contracts. Most well-designed REST APIs also return specific HTTP codes, depending on the result of the request.

The critical point is that the URIs operate on the data, not on remote methods.

But there’s another reason why the resource model is essential.

REST vs RESTful and the Richardson Maturity Model

When you model your URIs after resources and use HTTP verbs you make your API predictable. Once developers know how you defined your resources, they can almost predict what the API looks like. Here again, the emphasis is on understanding the data, not the operations.

But even if you can’t make the API entirely predictable, you can document any REST service with hypertext. So, each item returned in the inventory app would contain links for deleting, modifying, or setting the inventory level of the resource. Fielding says that before a service is RESTful, it must provide hypertext media as part of the API.

Many sites don’t meet this requirement but are still called REST. Fact is, many sites break the rules in one way or another. So many that Leonard Richardson created a model breaks down REST into levels of compliance

We’ve already covered the source levels:

  • 0 – exporting an API over HTTP with methods called with arguments
  • 1 – Exporting resources instead of methods
  • 2 – Proper use of HTTP verbs
  • 3 – Exporting hypertext with objects that make all or part of the API discoverable.

Richardson’s model is his own, and it doesn’t map directly into Fielding’s spec. Since Fielding requires level three, he would say that most apps aren’t REST anyway.

The point is many services that we colloquially refer to as REST, technically aren’t.

REST vs RESTful: Does It Matter?

So, does the REST vs. RESTful comparison matter? Probably not. How well your architecture complies with an arbitrary standard isn’t as important with how well it suits your needs and can grow with your business.

The REST architectural pattern has many advantages. Fielding designed it for the web and, 18 years later, most of the constraints he had in mind are still with us. In 2000 we didn’t have Android or the iPhone. IE5 had 50% of the browser market share. It’s biggest rival was Firefox. But Fielding recognized what online applications needed and how web clients would evolve from HTML display engines into complete applications. The tools we use today have grown to suit REST, not the other way around.

Thank you for reading. Hope this tutorial will help you!

How to use WebClient to call the API in Spring

How to use WebClient to call the API in Spring

In this quick tutorial, we will look at how to unit test services that use WebClient to call APIs in Spring

1. Overview

These days, we expect to call REST APIs in most of our services. Spring provides a few options for building a REST client, and WebClient is recommended.

In this quick tutorial, we will look at how to unit test services that use WebClient to call APIs.

2. Mocking

We have two main options for mocking in our tests:

3. Using Mockito

Mockito is the most common mocking library for Java. It's good at providing pre-defined responses to method calls, but things get challenging when mocking fluent APIs. This is because in a fluent API, a lot of objects pass between the calling code and the mock.

For example, let's have an EmployeeService class with a getEmployeeById method to fetch data via HTTP using WebClient:

public class EmployeeService {
 
    public Mono<Employee> getEmployeeById(Integer employeeId) {
        return webClient
                .get()
                .uri("http://localhost:8080/employee/{id}", employeeId)
                .retrieve()
                .bodyToMono(Employee.class);
    }
}

We can use Mockito to mock this:

@ExtendWith(MockitoExtension.class)
public class EmployeeServiceTest {
    
    @Test
    void givenEmployeeId_whenGetEmployeeById_thenReturnEmployee() {
 
        Integer employeeId = 100;
        Employee mockEmployee = new Employee(100, "Adam", "Sandler", 
          32, Role.LEAD_ENGINEER);
        when(webClientMock.get())
          .thenReturn(requestHeadersUriSpecMock);
        when(requestHeadersUriMock.uri("/employee/{id}", employeeId))
          .thenReturn(requestHeadersSpecMock);
        when(requestHeadersMock.retrieve())
          .thenReturn(responseSpecMock);
        when(responseMock.bodyToMono(Employee.class))
          .thenReturn(Mono.just(mockEmployee));
 
        Mono<Employee> employeeMono = employeeService.getEmployeeById(employeeId);
 
        StepVerifier.create(employeeMono)
          .expectNextMatches(employee -> employee.getRole()
            .equals(Role.LEAD_ENGINEER))
          .verifyComplete();
    }
 
}

As we can see, we need to provide a different mock object for each call in the chain, with four different when/thenReturn calls required. This is verbose and cumbersome. It also requires us to know the implementation details of how exactly our service uses WebClient, making this a brittle way of testing.

How can we write better tests for WebClient?

4. Using MockWebServer

MockWebServer, built by the Square team, is a small web server that can receive and respond to HTTP requests.

Interacting with MockWebServer from our test cases allows our code to use real HTTP calls to a local endpoint. We get the benefit of testing the intended HTTP interactions and none of the challenges of mocking a complex fluent client.

Using MockWebServer is recommended by the Spring Team for writing integration tests_._

4.1. MockWebServer Dependencies

To use MockWebServer, we need to add Maven dependencies for both okhttp and mockwebserver to our pom.xml:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.0.1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>mockwebserver</artifactId>
    <version>4.0.1</version>
    <scope>test</scope>
</dependency>

4.2. Adding MockWebServer to our Test

Let's test our EmployeeService with MockWebServer:

public class EmployeeServiceMockWebServerTest {
 
    public static MockWebServer mockBackEnd;
 
    @BeforeAll
    static void setUp() throws IOException {
        mockBackEnd = new MockWebServer();
        mockBackEnd.start();
    }
 
    @AfterAll
    static void tearDown() throws IOException {
        mockBackEnd.shutdown();
    }
}

In the above JUnit Test class, the setUp and tearDown method takes care of creating and shutting down the MockWebServer.

The next step is to map the port of the actual REST service call to the MockWebServer's port.

@BeforeEach
void initialize() {
    String baseUrl = String.format("http://localhost:%s", 
      mockBackEnd.getPort());
    employeeService = new EmployeeService(baseUrl);
}

Now it's time to create a stub so that the MockWebServer can respond to an HttpRequest.

4.3. Stubbing a Response

Let's use MockWebServer's handy enqueue method to queue a test response on the web server:

@Test
void getEmployeeById() throws Exception {
    Employee mockEmployee = new Employee(100, "Adam", "Sandler", 
      32, Role.LEAD_ENGINEER);
    mockBackEnd.enqueue(new MockResponse()
      .setBody(objectMapper.writeValueAsString(mockEmployee))
      .addHeader("Content-Type", "application/json"));
 
    Mono<Employee> employeeMono = employeeService.getEmployeeById(100);
 
    StepVerifier.create(employeeMono)
      .expectNextMatches(employee -> employee.getRole()
        .equals(Role.LEAD_ENGINEER))
      .verifyComplete();
}

When the actual API call is made from the getEmployeeById(Integer employeeId) method in our _EmployeeService _class, MockWebServer will respond with the queued stub.

4.4. Checking a Request

We may also want to make sure that the MockWebServer was sent the correct HttpRequest.

MockWebServer has a handy method named takeRequest that returns an instance of RecordedRequest:

RecordedRequest recordedRequest = mockBackEnd.takeRequest();
  
assertEquals("GET", recordedRequest.getMethod());
assertEquals("/employee/100", recordedRequest.getPath());

With RecordedRequest, we can verify the HttpRequest that was received to make sure our WebClient sent it correctly_._

5. Conclusion

In this tutorial, we tried the two main options available to mock WebClient based REST client code.

While Mockito worked and may be a good option for simple examples, the recommended approach is to use MockWebServer.

As always, the source code for this article is available over on GitHub.

Spring Data REST Tutorial: Developing RESTful APIs with Ease

Spring Data REST Tutorial: Developing RESTful APIs with Ease

In this article, you will learn how to develop REST APIs with ease by using Spring Data REST and Spring Boot together. Throughout the article, you will scaffold a new Spring Boot application, create a JPA entity, and use Spring Data REST to provide some basic operations over it. Besides that, you will also learn how to validate the data your API is dealing with and how to secure the application.

In this article, you will learn how to develop REST APIs with ease by using Spring Data REST and Spring Boot together. Throughout the article, you will scaffold a new Spring Boot application, create a JPA entity, and use Spring Data REST to provide some basic operations over it. Besides that, you will also learn how to validate the data your API is dealing with and how to secure the application. If you need, you can check the final code developed throughout the article in this GitHub repository.

Introduction

Developing RESTful APIs is a task that most developers have faced at least once in their lives. Nowadays, with the increasing popularity of front-end frameworks like Angular, React, and Vue.js and with the mass adoption of smartphones, RESTful APIs became the most popular approach backend developers leverage to provide an interface for their applications. Knowing that, the Spring community, as you will see in this article, worked hard to build Spring Data REST, a framework that facilitates the life of developers while creating these APIs.

Spring Data REST builds on top of Spring Data repositories, analyzes your application’s domain model and exposes hypermedia-driven HTTP resources for aggregates contained in the model. — Spring Data REST
Together with Spring Boot, Spring Data REST enables developers to create production-ready APIs in a matter of minutes. Want some proof? Keep reading!
Spring Data REST builds on top of Spring Data repositories, analyzes your application’s domain model and exposes hypermedia-driven HTTP resources for aggregates contained in the model. — Spring Data REST## What You Will Build

To learn about Spring Data REST, you will build a simple RESTful API that exposes CRUD (Create, Retrieve, Update, and Delete) operations over an entity called Ad. The Ad entity, in this case, stands for advertisements and will be used to represent some product or service that a user is trying to sell. As such, your API will enable users to manipulate ads that hold information like title, owner, description, and price.

As mentioned before, while developing this RESTful API, you will learn how to:

  • provide an API with different basic operations over the entity created (Ad);
  • validate data;
  • and secure the API.
Prerequisites

To follow along with this article, you will need Java 8 or greater (up to Java 11) installed in your machine. If you don’t have Java yet, please, refer to the official documentation to install it in your development environment.

Besides Java, you will need some IDE (Integrated Development Environment) to help you in the development process. For that, there are a few great choices available out there (e.g., IntelliJ IDEA, Eclipse, and NetBeans). If you don’t have a preferred one yet, try using the community version of IntelliJ IDEA.

Scaffolding an App with Spring Boot

For starters, before diving into developing your RESTful API, you will need to scaffold your new application. To do so, open the Spring Initializr website in your browser and fill the presented form as follows:

  • provide an API with different basic operations over the entity created (Ad);
  • validate data;
  • and secure the API.

Then, on the Dependencies section, use the search for dependencies field to add five dependencies:

  • provide an API with different basic operations over the entity created (Ad);
  • validate data;
  • and secure the API.

After filling this page, click on the Generate Project button to download your new application. When done, you will have to extract the downloaded .zip file and move the extracted folder to a desired location.

If you are on a Unix-like operating system, you can also unzip the downloaded file with the following command:

unzip ads.zip


With that in place, use your IDE to open your new project. For example, if you are using IntelliJ IDEA, you can open the project by issuing the following command from the project root:

idea .


Creating RESTful APIs for JPA Entities with Spring Data REST

Now that you have scaffolded a new Spring Boot project and that you have opened it in your IDE, the first thing you will do is to create the JPA entity that you will expose with the help of Spring Data REST. To do so, create a new class called Ad inside the com.auth0.ads package, and add the following code to it:

// ./src/main/java/com/auth0/ads/Ad.java
package com.auth0.ads;

import lombok.EqualsAndHashCode;
import lombok.Getter;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.math.BigDecimal;

@Entity
@Getter
@EqualsAndHashCode
public class Ad {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long id;

    public String owner;
    public String title;
    public String description;
    public BigDecimal price;

    protected Ad() {
    }

    public Ad(String owner, String title, String description, BigDecimal price) {
        this.owner = owner;
        this.title = title;
        this.description = description;
        this.price = price;
    }
}


As you can see from the code above, you are defining a new JPA @Entity called Ad to hold five different fields. Most of these fields are self-explanatory (their names should be enough for you to understand what they will hold). The only one that might need some explanation is the Long id field. As you can see, this field is marked with two annotations:

  • provide an API with different basic operations over the entity created (Ad);
  • validate data;
  • and secure the API.

After creating the Ad JPA entity, you will need to focus on creating a class that will allow you to interface with the database. Also, you will need to map the database operations into RESTful API endpoints so external clients can use them. Sounds like a lot of work? On the contrary! This is where Spring Data REST shines.

To achieve both things described in the last paragraph (map to the database and expose the operations in your API), you will need to do only one thing. You will need to create an interface called AdRepository (inside the com.auth0.ads package) and add the following code to it:

// ./src/main/java/com/auth0/ads/AdRepository.java
package com.auth0.ads;

import org.springframework.data.repository.PagingAndSortingRepository;

public interface AdRepository extends PagingAndSortingRepository<Ad, Long> {
}


That’s it! With this interface in place, you are ready to run your application and start issuing requests to it. Magic? Indeed it looks like so. However, what is happening here is that Spring Boot (a framework that is bound to the “convention over configuration” strategy) and Spring Data REST identify that you defined an interface that extends PagingAndSortingRepository and work together to create a bunch of endpoints for you.

If you check the JavaDocs of the PagingAndSortingRepository interface, you will see that this interface is an “extension of [CrudRepository](https://docs.spring.io/spring-data/data-commons/docs/current/api/org/springframework/data/repository/PagingAndSortingRepository.html "CrudRepository") to provide additional methods to retrieve entities using pagination and sorting.

More specifically, as described on the Core Concepts documentation of the Spring Data library, together, PagingAndSortingRepository and CrudRepository add the following methods to your application to allow it to manipulate your entities in a SQL database:

  • provide an API with different basic operations over the entity created (Ad);
  • validate data;
  • and secure the API.

Then, as you are using Spring Data REST, this library creates RESTful endpoints to exposes all the methods defined by PagingAndSortingRepository and CrudRepository.

To see all this magic in action, you can either press the play button in your IDE, or you can issue the following code in a terminal (as long as this terminal is pointing to the project root):

./gradlew bootRun


After the application starts executing (it will take a few seconds for it to be ready), you can start sending HTTP requests to its endpoints. To do so, you can use a graphical HTTP client like Postman, or you can open a new terminal and use a tool like curl. The next subsection will show you how to use curl to issue some requests to your new application. However, translating them to Postman or a similar client should not be a problem.

Spring Data REST builds on top of Spring Data repositories, analyzes your application’s domain model and exposes hypermedia-driven HTTP resources for aggregates contained in the model. — Spring Data REST### Issuing requests to the Spring Data REST endpoints

For starters, to confirm that your application is working as expected, you can issue the following request (you might need to run the command below in a new terminal or, as mentioned, you can use Postman):

# check if there are ads persisted
curl http://localhost:8080/ads


Running this command will make your API return all the ads persisted on the database (which will be none: "ads" : [ ]), and a few other things like:

  • provide an API with different basic operations over the entity created (Ad);
  • validate data;
  • and secure the API.

As you haven’t created any entity yet, the results won’t be very interesting. So, the next thing you can do is to issue a request to insert a new ad in your API:

# insert a new ad
curl -X POST -H "Content-Type:application/json" -d '{
    "owner": "me",
    "title": "My Car",
    "description": "Pretty awesome but, unfortunately, I have to sell it.",
    "price": 225599.99
}' http://localhost:8080/ads 


Issuing this command will output the details of the ad created (all the properties above) along with a link to the ad itself (self.href). If you use this link in a curl command, you will retrieve the details of the ad:

# retrieve the new ad
curl http://localhost:8080/ads/1


Now, if you run the command to see the list of persisted ads again:

curl http://localhost:8080/ads


You will see that the ads array includes your new ad and that the page properties (size, totalElements, etc.) are updated accordingly.

After that, if you want, you can delete the ad by issuing the following command:

curl -X DELETE http://localhost:8080/ads/1


Incredible, huh? After scaffolding your application, you just had to create two things (the Ad entity and the AdRepository interface), and you got a runnable RESTful API.

Data Validation

After seeing Spring Data REST in action, you might be thinking: “Ok, this library does facilitate creating RESTful APIs, but I need to validate the data before persisting it to the database. Will it be easy to validate my data?” The answer to that is yes! By using the Bean Validation Java specification, validating your data is as easy as adding some annotations to the fields in your JPA entity.

Spring Data REST builds on top of Spring Data repositories, analyzes your application’s domain model and exposes hypermedia-driven HTTP resources for aggregates contained in the model. — Spring Data REST> Spring Data REST builds on top of Spring Data repositories, analyzes your application’s domain model and exposes hypermedia-driven HTTP resources for aggregates contained in the model. — Spring Data REST
If you want some proof, open the Ad class and update its code to look like this:

// ./src/main/java/com/auth0/ads/Ad.java
package com.auth0.ads;

import lombok.EqualsAndHashCode;
import lombok.Getter;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;

@Entity
@Getter
@EqualsAndHashCode
public class Ad {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long id;

    @NotNull(message = "Who is the owner of this ad?")
    public String owner;

    @NotNull(message = "Please, inform a title for your ad.")
    @Size(min = 5, max = 140, message = "Titles must have between {min} and {max} characters.")
    public String title;

    @NotNull(message = "Please, inform a description for your ad.")
    @Size(min = 5, max = 500, message = "Titles must have between {min} and {max} characters.")
    public String description;

    @Min(message = "Price cannot be negative", value = 0)
    public BigDecimal price;

    protected Ad() {}

    public Ad(String owner, String title, String description, BigDecimal price) {
        this.owner = owner;
        this.title = title;
        this.description = description;
        this.price = price;
    }
}


On the new version of this entity, you are importing and using three new annotations:

  • provide an API with different basic operations over the entity created (Ad);
  • validate data;
  • and secure the API.

After updating the Ad class, you can rerun your application (by issuing ./gradlew bootRun or by pressing the start button on your IDE). When the app finishes booting, you can issue requests like the following to confirm that the restrictions are working:

# won't work, too few characters on the title property
curl -X POST -H "Content-Type:application/json" -d '{
    "owner": "me",
    "title": "Abc",
    "description": "Pretty awesome but, unfortunately, I have to sell it.",
    "price": 500
}' http://localhost:8080/ads 

# won't work, negative price
curl -X POST -H "Content-Type:application/json" -d '{
    "owner": "me",
    "title": "My Car",
    "description": "Pretty awesome but, unfortunately, I have to sell it.",
    "price": -10
}' http://localhost:8080/ads 

# won't work, no description
curl -X POST -H "Content-Type:application/json" -d '{
    "owner": "me",
    "title": "My Car",
    "price": 500
}' http://localhost:8080/ads 

# will work, all properties contain valid values
curl -X POST -H "Content-Type:application/json" -d '{
    "owner": "me",
    "title": "My Car",
    "description": "Pretty awesome but, unfortunately, I have to sell it.",
    "price": 500
}' http://localhost:8080/ads 


While issuing the invalid requests above (i.e., the first three), you will see that your app returns a response that looks like this:

{
  "timestamp": "2019-02-19T18:35:52.094+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction",
  "path":"/ads"
}


Although this response is sufficient for the calling client to understand that something went wrong, it doesn’t help to identify what the problem was. To fix that, you can create a new class called RestExceptionHandler inside the com.auth0.ads package and add the following code to it:

// ./src/main/java/com/auth0/ads/RestExceptionHandler.java
package com.auth0.ads;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.persistence.RollbackException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(TransactionSystemException.class)
    protected ResponseEntity<List<String>> handleTransactionException(TransactionSystemException ex) throws Throwable {
        Throwable cause = ex.getCause();
        if (!(cause instanceof RollbackException)) throw cause;
        if (!(cause.getCause() instanceof ConstraintViolationException)) throw cause.getCause();
        ConstraintViolationException validationException = (ConstraintViolationException) cause.getCause();
        List<String> messages = validationException.getConstraintViolations().stream()
                .map(ConstraintViolation::getMessage).collect(Collectors.toList());
        return new ResponseEntity<>(messages, HttpStatus.BAD_REQUEST);
    }
}


With this class, you are creating and registering a global exception handler (ResponseEntityExceptionHandler) for your application. Then, inside this handler, you are defining a method that will catch instances of TransactionSystemException to unwrap the real problem (ex.getCause()). If the unwrapped exception is not an instance of RollbackException, then this method throws the underlying exception.

If the unwrapped problem is an instance of RollbackException, then this method unwraps the cause one more time (cause.getCause()). This time, the goal is to check if the second unwrap will result in an instance of ConstraintViolationException. If this is not the case, the unwrapped result is thrown. If this is the case, this method generates a list of messages to send back as a response.

After creating this exception handler, if you restart your app and issue bogus requests, you will get some friendly messages. For example, if you issue the following request:

curl -X POST -H "Content-Type:application/json" -d '{
    "owner": "me",
    "title": "My Car",
    "price": -10
}' http://localhost:8080/ads


You will get a list of messages saying that the “price cannot be negative” and to “please, inform a description for your ad.” Not to hard too validate your data in this stack, huh?

Securing Spring Data REST APIs

Cool, with a minimum amount of effort you were able to create a backend application that exposes a bunch of RESTful APIs and, in a couple of minutes, you were able to extend it with data validation. However, what about security? There is no production-ready RESTful API without security, right?

Luckily, adding a security layer to your current stack is not hard either. To do this, you will add the Spring Security framework on top of your application and will use it with Auth0 to generate and validate access tokens.

For starters, you will need to open the build.gradle file of your project and update it as follows:

// ... leave everything else untouched ...

dependencies {
    // ... leave the other dependencies untouched ...
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.2.RELEASE'
}


Here, you are making your project import two new dependencies. The first one is the Spring Boot extension for the Spring Security framework. The second one is a library that facilitates configuring OAuth (the authorization framework) which is used by Auth0.

After importing these new dependencies, you will have to:

  1. Add a couple of properties to the application.properties file to configure these dependencies.
  2. Create a class to define how the endpoints will be accessible.

However, before doing so, you will need to configure an Auth0 API to represent you RESTful backend.

Spring Data REST builds on top of Spring Data repositories, analyzes your application’s domain model and exposes hypermedia-driven HTTP resources for aggregates contained in the model. — Spring Data REST
After signing in (or signing up, if you didn’t have an Auth0 account yet), head to the APIs section of your Auth0 Dashboard and click on the Create API button. When you click on this button, Auth0 will show you a dialog where it will ask you for three things:

  • provide an API with different basic operations over the entity created (Ad);
  • validate data;
  • and secure the API.

After filling this form, click on the Create button. Then, back to your project, open the application.properties file and add the following to it:

# ./src/main/resources/application.properties
security.oauth2.resource.jwk.keySetUri=https://${YOUR-AUTH0-DOMAIN}/.well-known/jwks.json
security.oauth2.resource.id=https://ads-api


You will have to replace the ${YOUR-AUTH0-DOMAIN} placeholder with your Auth0 domain (e.g., blog-samples.auth0.com), and that you will have to make sure the resource.id property points to the identifier you used while registering your API.

Spring Data REST builds on top of Spring Data repositories, analyzes your application’s domain model and exposes hypermedia-driven HTTP resources for aggregates contained in the model. — Spring Data REST
With that in place, you will create a new class called SecurityConfig inside the com.auth0.ads package and add the following code to it:

// ./src/main/java/com/auth0/ads/SecurityConfig.java
package com.auth0.ads;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

@Configuration
@EnableResourceServer
public class SecurityConfig extends ResourceServerConfigurerAdapter {
    @Value("${security.oauth2.resource.id}")
    private String resourceId;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .mvcMatchers("/ads/**").authenticated();
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(resourceId);
    }
}


The code for this class is quite simple. As you can see, you are using some Spring Boot annotations (like @Configuration and @Value) to make Spring configure this class while bootstrapping the app. Also, you are defining two configure methods to define how the Spring Security framework must behave. The first configure method is telling the framework that all calls to /ads/** must be authenticated. The second one is telling the ResourceServerSecurityConfigurer to use, as the resourceId, the value you added to the security.oauth2.resource.id property.

After creating your Auth0 API and making the changes described above, you can restart your application one more time and issue the following request:

curl http://localhost:8080/ads


This request (or any other aiming endpoints starting with /ads that do not carry an access token) will result in the following response:

{
  "error":"unauthorized",
  "error_description":"Full authentication is required to access this resource"
}


To be able to issue valid (or authenticated) requests, you will need an access token. The process of getting an access token will depend on what type of client you are dealing with. This is out of scope here but, if you are dealing with a SPA application (like those created with React, Angular, and Vue.js), you can check this article to learn how to proceed. If you are dealing with some other type of client (e.g., regular web application or native application), check the Auth0’s docs for more info.

Nevertheless, to see the whole thing in action, you can head back to your Auth0 Dashboard, open the API you just created, and move to the Test section. On this section, you will see a button called Copy Token that will provide you a temporary token that you can use to test your API.

So, click on this button and then use your client (or the terminal) to issue an HTTP request to your API with the test token:

# use the token copied to set the TOKEN variable
TOKEN=eyJ...DRA

# issue an authenticated HTTP request
curl -H 'Authorization: Bearer '$TOKEN http://localhost:8080/ads


If everything works as expected, you will be able to consume your API endpoints again. Awesome, right?

Conclusion

In this article, you learned about how easy it is to develop RESTful API with Spring Data REST and Spring Boot. More specifically, you started by using the Spring Initializr website to scaffold a new application. After that, you used Spring Data REST to expose API endpoints to manipulate a JPA entity. Then, in the end, you learned how to validate data and how to secure your API.

With that in place, you are ready to start developing production-ready, secure APIs with Spring Boot, Spring Data REST, and Auth0.

Spring Data REST builds on top of Spring Data repositories, analyzes your application’s domain model and exposes hypermedia-driven HTTP resources for aggregates contained in the model. — Spring Data REST
*Originally published by Bruno Krebs at *https://auth0.com

Learn More

Build a Basic App with Spring Boot and JPA using PostgreSQL

Build a Simple CRUD App with Spring Boot and Vue.js

Building A REST API With MongoDB, Mongoose, And Node.js

Creating RESTful APIs with NodeJS and MongoDB Tutorial

Understanding the basics of RESTful APIs

GraphQL Tutorial: Understanding Spring Data JPA/SpringBoot

Complete Java Masterclass

Complete Step By Step Java For Testers

Java Web Service Complete Guide - SOAP + REST + Buide App

Selenium WebDriver with Java - Basics to Advanced& Interview