Rest Controller

👉 Spring boot tutorial to Develop and Expose API over HTTP using Controllers / Rest Controllers.


RESTFul Service Development

Developing RESTful services in Spring Boot is made simple using the spring-boot-starter-web dependency.

This starter bundles key components like Spring MVC and an embedded Tomcat server, allowing you to quickly define @RestController classes and test with embedded server.


Table of Contents


Maven Dependency

The core functionality for creating REST services and handling the response entity is provided by the spring-boot-starter-web.

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Creating REST Controllers

In a Spring Boot application, the primary way to create controller this is by annoating the class with @Controller annotation.

Specifically, the @RestController annotation is a convenient shorthand, which combines the @Controller and @ResponseBody annotations.

On Application Booting Spring scans this class and finds that,

  • This class handles incoming web requests - @RestController.
  • The return value of the methods should be automatically converted to the response body (typically JSON or XML) - @ResponseBody.

Controller

We will utilize ServletUriComponentsBuilder to easily construct the newly created resource’s URI based on the current request’s context.

// language: java
import java.net.URI;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

@RestController
public class UserResource {

    // ... UserDaoService and Logger Autowire / initialization ...

    /**
     * Creates a new User and returns a 201 Created status
     * with the new resource's URI in the Location header.
     */
    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody User user) {

        // 1. Save the new resource
        logger.debug("User to save : {}", user);
        User savedUser = userDaoService.save(user);

        // 2. Build URL to the new Resource using the current request's context
        // e.g., POST http://localhost:8080/users -> URI: http://localhost:8080/users/{id}
        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
            .path("/{id}") // Append the path segment
            .buildAndExpand(savedUser.getId()) // Replaces {id} with the actual ID
            .toUri();
    
        // 3. Wrap new URL and response object in ResponseEntity
        // ResponseEntity.created(location) sets the HTTP status to 201 and the Location header
        return ResponseEntity.created(location).body(savedUser);
    }
}

Project Reference:
Check the project POC on Github - Social Media App.

HTTP POST Verb

When a resource is successfully created via a POST request, the response is returned with standard HTTP status code 201 Created. Best practice dictates including a Location header in the response, pointing to the newly created resource’s URI.

The primary goal of a well-designed POST endpoint is to create a new resource and inform the client of its new location. This adheres to the HATEOAS (Hypermedia as the Engine of Application State) principle.

It is focused on a specific, valuable pattern in Spring Boot REST service development: returning a response with a link to a newly created resource using the 201 Created status and the Location header.


Other HTTP Verbs

RESTful API relies entirely on the semantics of HTTP verbs (methods) to define the intended action on a resource.

Spring Boot abstracts this perfectly by providing specific, intention-revealing annotations for HTTP Verbs.

This approach ensures the API is self-describing and adheres to the uniform interface constraint of REST. The client knows exactly what behavior to expect just by looking at the verb and the URI structure.

REST Controller

// language: java
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ItemResource {

    // 1. GET: Retrieve a resource or a collection
    @GetMapping("/items")
    public List<Item> retrieveAllItems() {
        return itemDaoService.findAll(); // Returns a list (200 OK)
    }

    // 2. GET: Retrieve a specific resource
    @GetMapping("/items/{id}")
    public Item retrieveItem(@PathVariable int id) {
        return itemDaoService.findOne(id); // Returns the Item (200 OK)
    }

    // 3. POST: Create a new resource (as discussed)
    @PostMapping("/items")
    public ResponseEntity<Item> createItem(@RequestBody Item item) {
        // ... logic for 201 Created ...
        return ResponseEntity.created(location).body(item);
    }

    // 4. PUT: Update an existing resource (full replacement)
    @PutMapping("/items/{id}")
    public ResponseEntity<Item> updateItem(@PathVariable int id, @RequestBody Item itemDetails) {
        // Update logic...
        return ResponseEntity.ok(updatedItem); // 200 OK
    }

    // 5. PATCH: Partially update an existing resource (partial modification)
    @PatchMapping("/items/{id}")
    public ResponseEntity<Item> patchItem(@PathVariable int id, @RequestBody Item itemPatch) {
        // Partial update logic...
        return ResponseEntity.ok(patchedItem); // 200 OK
    }

    // 6. DELETE: Remove a resource
    @DeleteMapping("/items/{id}")
    public ResponseEntity<Void> deleteItem(@PathVariable int id) {
        itemDaoService.deleteById(id);
        return ResponseEntity.noContent().build(); // 204 No Content
    }
}

HTTP Status Codes

Returning correct HTTP Status Codes is vital for a clear contract between the server and the client.

Spring’sResponseEntity class makes it easy for developers to control the status code returned in the response.

CodeCategoryUse Case / MeaningSpring Boot Response
200SuccessOK. Standard response for successful HTTP requests (GET, PUT, DELETE).ResponseEntity.ok().body(...)
201SuccessCreated. Successful creation of a new resource (POST).ResponseEntity.created(uri).body(...)
204SuccessNo Content. Successful request, but no content to return (e.g., successful DELETE).ResponseEntity.noContent().build()
400Client ErrorBad Request. The server cannot process the request due to client error (e.g., malformed JSON).ResponseEntity.badRequest().body(...)
401Client ErrorUnauthorized. Authentication is required and has failed or not been provided.Handled by Spring Security.
403Client ErrorForbidden. The client is authenticated but does not have permission to access the resource.Handled by Spring Security.
404Client ErrorNot Found. The requested resource could not be found.Throw a custom ResponseStatusException or NotFoundException.
500Server ErrorInternal Server Error. A generic error occurred on the server.Thrown by default for unhandled exceptions.