DEV Community

eidher
eidher

Posted on • Edited on

Spring MVC REST

Representational state transfer (REST) is an architectural style that describes best practices to expose web services over HTTP, emphasizing performance, scalability, simplicity, modifiability, visibility, portability, and reliability.

REST exposes resources through URIs using nouns (not verbs), supporting a limited set of operations (GET, PUT, POST, DELETE). Clients can request particular representations (HTML, XML, JSON, etc) that can link to other resources, and use Hypermedia as the Engine of Application State (HATEOAS). It uses a stateless architecture, headers, and status codes to communicate with clients.

Spring MVC provides REST support. The RequestMapping annotation is used to map web requests. The RequestMethod enumerators are: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, and TRACE.

@RequestMapping(path="/accounts", method=RequestMethod.GET)
Enter fullscreen mode Exit fullscreen mode

Since Spring 4.3, instead of RequestMapping you can use these annotations:

  • @GetMapping: To fetch a resource
  • @PostMapping: To create a new resource
  • @PutMapping: To update entirely a resource
  • @DeleteMapping: To delete an existing resource
  • @PatchMapping: To update partially a resource

For HEAD, OPTIONS, and TRACE use RequestMethod enumerators.

    @GetMapping(value = "/accounts")
    public @ResponseBody List<Account> accountSummary() {
        return accountManager.getAllAccounts();
    }

    @GetMapping(value = "/accounts/{id}")
    public @ResponseBody Account accountDetails(@PathVariable int id) {
        return retrieveAccount(id);
    }
Enter fullscreen mode Exit fullscreen mode

HTTP GET returns data in the response body. The @ResponseBody annotation allows us to return a serialized object. If the class is annotated as a @RestController, there is no need for @ResponseBody on GET methods.

To have more control over the response (e.g, set headers and control content), you can use ResponseEntity:

    @GetMapping(value = "/accounts/{id}")
    public ResponseEntity<Account> accountDetails(@PathVariable long id) {
        Account account = accountService.getAccount(id);
        return ResponseEntity
                .ok()
                .header("Last-Modified", account.getLastUpdate())
                .body(account);
    }
Enter fullscreen mode Exit fullscreen mode

In the example above, the ResponseEntity is built calling the ok method, which returns the 200 status code (success). See HttpStatus documentation. You also can add the @ResponseStatus annotation over the method.

Similarly to @ResponseBody, the @RequestBody annotation allows us to convert automatically incoming data based on the content type of the request.

    @PostMapping(value = "/accounts")
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseEntity<Void> createAccount(@RequestBody Account newAccount) {
        Account account = accountManager.save(newAccount);
        URI location = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/{childId}")
                .buildAndExpand(account.getEntityId()).toUri();
        return ResponseEntity.created(location).build();
    }
Enter fullscreen mode Exit fullscreen mode

In the previous example, we are building the URI. To create a URI you can use ServletUriComponentsBuilder or UriComponentsBuilder (for hard-coded URLs).

Spring MVC provides a Spring REST Client called RestTemplate (Spring Framework 5 introduced a new HTTP client called WebClient. See Reactive Spring Applications). RestTemplate provides access to RESTful services and supports all the HTTP methods. See RestTemplate documentation

  • DELETE: delete method
  • GET: getForObject and getForEntity (for ResponseEntity) methods
  • HEAD: headForHeaders method
  • OPTIONS: optionsForAllow method
  • POST: postForLocation, postForObject and exchange (for RequestEntity) methods
  • PUT: put method
    @Test
    public void listAccounts() {
        RestTemplate restTemplate = new RestTemplate();
        String url = "http://localhost:8080/accounts";
        Account[] accounts = restTemplate.getForObject(url, Account[].class);
        assertNotNull(accounts);
    }
Enter fullscreen mode Exit fullscreen mode

Finally, Spring HATEOAS provides an API for generating links in MVC Controller responses. Use Link class and @EnableHypermediaSupport annotation.

@Controller
@EnableHypermediaSupport(type = { HypermediaType.HAL })
public class EmployeeController {

    @GetMapping(value = "/{employeeId}")
    public Employee getEmployeeById(@PathVariable long employeeId) {
        Employee employeeById = ControllerLinkBuilder.methodOn(EmployeeController.class).getEmployeeById(employeeId);
        Link selfLink = ControllerLinkBuilder.linkTo(employeeById).withSelfRel();
        Employee employee = employeeService.getEmployee(employeeId);
        employee.add(selfLink);
        return employee;
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)