Skip to content

Latest commit

 

History

History
278 lines (217 loc) · 11.2 KB

README.adoc

File metadata and controls

278 lines (217 loc) · 11.2 KB

This guide walks you through the process of creating a “Hello, World” Hypermedia-driven REST web service with Spring.

Hypermedia is an important aspect of REST. It lets you build services that decouple client and server to a large extent and let them evolve independently. The representations returned for REST resources contain not only data but also links to related resources. Thus, the design of the representations is crucial to the design of the overall service.

What You Will Build

You will build a hypermedia-driven REST service with Spring HATEOAS: a library of APIs that you can use to create links that point to Spring MVC controllers, build up resource representations, and control how they are rendered into supported hypermedia formats (such as HAL).

The service will accept HTTP GET requests at http://localhost:8080/greeting.

It will respond with a JSON representation of a greeting that is enriched with the simplest possible hypermedia element, a link that points to the resource itself. The following listing shows the output:

{
  "content":"Hello, World!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=World"
    }
  }
}

The response already indicates that you can customize the greeting with an optional name parameter in the query string, as the following listing shows:

http://localhost:8080/greeting?name=User

The name parameter value overrides the default value of World and is reflected in the response, as the following listing shows:

{
  "content":"Hello, User!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=User"
    }
  }
}

Starting with Spring Initializr

You can use this pre-initialized project and click Generate to download a ZIP file. This project is configured to fit the examples in this tutorial.

To manually initialize the project:

  1. Navigate to https://start.spring.io. This service pulls in all the dependencies you need for an application and does most of the setup for you.

  2. Choose either Gradle or Maven and the language you want to use. This guide assumes that you chose Java.

  3. Click Dependencies and select Spring HATEOAS.

  4. Click Generate.

  5. Download the resulting ZIP file, which is an archive of a web application that is configured with your choices.

Note
If your IDE has the Spring Initializr integration, you can complete this process from your IDE.
Note
You can also fork the project from Github and open it in your IDE or other editor.

Create a Resource Representation Class

Now that you have set up the project and build system, you can create your web service.

Begin the process by thinking about service interactions.

The service will expose a resource at /greeting to handle GET requests, optionally with a name parameter in the query string. The GET request should return a 200 OK response with JSON in the body to represent a greeting.

Beyond that, the JSON representation of the resource will be enriched with a list of hypermedia elements in a _links property. The most rudimentary form of this is a link that points to the resource itself. The representation should resemble the following listing:

{
  "content":"Hello, World!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=World"
    }
  }
}

The content is the textual representation of the greeting. The _links element contains a list of links (in this case, exactly one with the relation type of rel and the href attribute pointing to the resource that was accessed).

To model the greeting representation, create a resource representation class. As the _links property is a fundamental property of the representation model, Spring HATEOAS ships with a base class (called RepresentationModel) that lets you add instances of Link and ensures that they are rendered as shown earlier.

Create a plain old java object that extends RepresentationModel and adds the field and accessor for the content as well as a constructor, as the following listing (from src/main/java/com/example/resthateoas/Greeting.java) shows:

link:complete/src/main/java/com/example/resthateoas/Greeting.java[role=include]
  • @JsonCreator: Signals how Jackson can create an instance of this POJO.

  • @JsonProperty: Marks the field into which Jackson should put this constructor argument.

Note
As you will see in later in this guide, Spring will use the Jackson JSON library to automatically marshal instances of type Greeting into JSON.

Next, create the resource controller that will serve these greetings.

Create a REST Controller

In Spring’s approach to building RESTful web services, HTTP requests are handled by a controller. The components are identified by the @RestController annotation, which combines the @Controller and @ResponseBody annotations. The following GreetingController (from src/main/java/com/example/resthateoas/GreetingController.java) handles GET requests for /greeting by returning a new instance of the Greeting class:

link:complete/src/main/java/com/example/resthateoas/GreetingController.java[role=include]

This controller is concise and simple, but there is plenty going on. We break it down step by step.

The @RequestMapping annotation ensures that HTTP requests to /greeting are mapped to the greeting() method.

Note
The above example does not specify GET vs. PUT, POST, and so forth, because @RequestMapping maps all HTTP operations by default. Use @GetMapping("/greeting") to narrow this mapping. In that case you also want to import org.springframework.web.bind.annotation.GetMapping;.

@RequestParam binds the value of the query string parameter name into the name parameter of the greeting() method. This query string parameter is implicitly not required because of the use of the defaultValue attribute. If it is absent in the request, the defaultValue of World is used.

Because the @RestController annotation is present on the class, an implicit @ResponseBody annotation is added to the greeting method. This causes Spring MVC to render the returned HttpEntity and its payload (the Greeting) directly to the response.

The most interesting part of the method implementation is how you create the link that points to the controller method and how you add it to the representation model. Both linkTo(…) and methodOn(…) are static methods on ControllerLinkBuilder that let you fake a method invocation on the controller. The returned LinkBuilder will have inspected the controller method’s mapping annotation to build up exactly the URI to which the method is mapped.

Note
Spring HATEOAS respects various X-FORWARDED- headers. If you put a Spring HATEOAS service behind a proxy and properly configure it with X-FORWARDED-HOST headers, the resulting links will be properly formatted.

The call to withSelfRel() creates a Link instance that you add to the Greeting representation model.

Logging output is displayed. The service should be up and running within a few seconds.

Test the Service

Now that the service is up, visit http://localhost:8080/greeting, where you should see the following content:

{
  "content":"Hello, World!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=World"
    }
  }
}

Provide a name query string parameter by visiting the following URL: http://localhost:8080/greeting?name=User. Notice how the value of the content attribute changes from Hello, World! to Hello, User! and the href attribute of the self link reflects that change as well, as the following listing shows:

{
  "content":"Hello, User!",
  "_links":{
    "self":{
      "href":"http://localhost:8080/greeting?name=User"
    }
  }
}

This change demonstrates that the @RequestParam arrangement in GreetingController works as expected. The name parameter has been given a default value of World but can always be explicitly overridden through the query string.

Summary

Congratulations! You have just developed a hypermedia-driven RESTful web service with Spring HATEOAS.