Java - Using Spring to create a REST API
Tags: java, rest, api
Published: 2020-03-10 19:42:45

**Introduction**

Spring is one of the most popular frameworks for Java web development. 
Extensions of it, namely SpringBoot and Spring Initializr plug-in for IntelliJ, have become one of industry's standards for developing web applications with Spring. 
Within web applications, a very common and modern trend is developing REST APIs. These simply use HTTP as the means of communication between front-end and back-end. Typically, the front-end sends an http request to obtain a *resource* and the endpoint returns a response. These responses usually contain a resource and a response code.
We'll see how to write a basic endpoint that consumes and produces JSON and how to write an integration test for such an endpoint. 

**The setup**

For our setup, we will use the Spring initializr for IntelliJ (but you can use whatever you have available in your IDE or even set up some things manually).

For the purpose of this simple post, let's assume that we want to send a JSON with the following structure in the body of a POST request:

```json
{"name":"John", "age":12}
```

and as a response we want to return the following JSON:


```json
{"greet":"Hi, John", "date":<return date of request>}
```

When working with REST APIs, it's usually necessary to have a few things in place:

- DTOs (Data Transfer Objects): for both the request and the response, we need to be able to have objects in place that represent our request and response so that we can build it on the Java side. These objects will be used to do further data processing on the request and to build a response.

- Use an ObjectMapper, like Jackson, to de/serialize from and to JSON.

REST APIs should accept JSON for request payload and also send responses to JSON. JSON is the standard for transferring data. Almost every networked technology can use it: JavaScript has built-in methods to encode and decode JSON either through the Fetch API or another HTTP client. Server-side technologies have libraries that can decode JSON without doing much work.

- It's also good practice to have a "service class" to which we delegate the actual business logic, as the only

With these in place, we can then prepare our endpoint. Let's set them up.

 **Preparing the data transfer classes**

For the request, let's say we have a `PersonDTO` class:

```java
public class PersonDTO {
    private String name;
    private int age;

    //Needed for Jackson
    public PersonDTO() {
    }

    public PersonDTO(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
```

And, for the response, we will have a `GreetDTO`:

```java
public class GreetDTO {
    private String greet;
    private Date date;

    //Needed for Jackson
    public GreetDTO() {
    }

    public GreetDTO(String greet, Date date) {
        this.greet = greet;
        this.date = date;
    }

    public String getGreet() {
        return greet;
    }

    public void setGreet(String greet) {
        this.greet = greet;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}
```

Note that if we want to use these classes in test contexts, or if we will need to load them from external sources for some reason, we need Jackson to de/serialize them to and from JSON and for that, we need the default constructor. To learn more about Jackson you can read my [post](https://dev.to/brunooliveira/introduction-to-objectmappers-using-jackson-in-the-wild-3ecf) about it.

**Introduction to Spring's capabilities - the `@RestController` annotation**

In Spring, controllers are used to provide application functionality and orchestrate its inner code flows.

When some class in Spring gets this specific annotation: `@RestController` ,the framework will know that there are certain additional annotations that can be supported in methods and members of the class to enhance it with the necessary capabilities to work as an endpoint.

What this means is that we can annotate methods with `@RequestMapping` annotations that will "bind" the method to a certain HTTP verb, used to perform a request.

When using `@RequestMapping` we need to specify the actual "verb" used, so PUT, GET, POST, DELETE, etc, or alternatively, we can use specific mappings for a certain verb, such as `@PostMapping` which indicates that the endpoint will only accept Post requests.

Let's see how the endpoint looks and let's break it down on the important bits:

```java
@RestController
public class GreetingsResource {

    private static final Log LOG = LogFactory.getLog(GreetingsResource.class);

//1
    @PostMapping(value = "/greet", consumes = MediaType.APPLICATION_JSON_VALUE)
//2
    public ResponseEntity<GreetDTO> greet(@RequestBody PersonDTO person) {
        if(person==null) {
            LOG.error("Request Body can not be null");
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }
        GreetingService greetingService = new GreetingService(person);
        GreetDTO response = greetingService.getGreeting();
        if(response==null){
            return new ResponseEntity<>(HttpStatus.EXPECTATION_FAILED);
        }

        return new ResponseEntity<>(response, HttpStatus.OK);
    }
}
```

We already discussed the `@RestController` annotation above, so, let's focus on the areas with the numbers as comments:

`//1` - analyzing the `@PostMapping` annotation

The annotation is used to ensure that the `greet` method will map to the `/greet` endpoint and additionally, that it only accepts POST requests. 
We also see the `consumes = MediaType.APPLICATION_JSON_VALUE` parameter, that states that this endpoint can only receive requests in JSON format. This is good for both consistency with the good practices of writing REST APIs and also serves as "documentation" for future uses of the API.

`//2` - Drilling down into `ResponseEntity<>` and `@RequestBody` constructs

We see that there's a lot of useful information regarding the way the REST Controller works under the hood in the header of the method. 

The `@RequestBody` annotation is used to define that the method parameter is going to be sent to our endpoint in the body of the http request.

When we send across the JSON, there will be an implicit mapping from the JSON to the Java DTO and the values from the JSON will be set on our Java object, so effectively our requestBody object will be a Java representation of our JSON request data.

Then, we can process our data using Java. Typically, this processing step takes place inside a service class which is a class typically used to encapsulate business logic. Thus, if the business logic changes, we do not need to change the endpoint and can simply adapt the service class.

The service class can also build a response, which is typically encapsulated by a `ResponseEntity<T>` class, which is a class from Spring that contains a response DTO, of type T, in our case: `ResponseEntity<GreetDTO>`.
The last thing we'll discuss is the implementation of the service class that will encapsulate the business logic for our endpoint. 

**The service class**

To link all we have done together, the last thing we need is to see the actual implementation of the service class, which will contain the logic of our endpoint and will generate a `ResponseEntity` with the JSON and a success code. Let's see the implementation:

```java
public class GreetingService {
      private final PersonDTO person;

      public GreetingService(PersonDTO person) {
             this.person = person;
      }

      public GreetDTO getGreeting() {
             return new GreetDTO("Hi, "+person.getName(), new Date());
      }
}
```

All the logic of the service class is trivial in this example and it's focused on building a new response object from the `PersonDTO` object which was what was sent in our request body.

This concludes all the work for our simple endpoint.

**Conclusion**

Hope you got a better idea on how to write a simple endpoint using Spring's capabilities! On the next post, we will see how to use Postman to actually see it working, and we will see what we can leverage in Spring's ecosystem to write an integration test for it.