Skip to content

An example to help you hit the ground running when building REST services using Spring.

License

Notifications You must be signed in to change notification settings

bilalwahla/rest-services-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tags projects
gradle
spring-boot
spring-boot-actuator
jpa
rest
hateoas
restdocs
spring-boot
spring-boot-actuator
spring-data
spring-hateoas
spring-restdocs

Build Status codecov

This guide walks you through the process of building RESTful services using Spring. This is a bookmarks service example that adopts Building REST services with Spring, applies some refactoring and builds on it by writing tests to verify HATEOAS responses. Example takes advantage of the Spring REST Dcos to document the REST APIs for the service.

What is this template

Example models a RESTful bookmark service. It simply collects a URI, and a description where all bookmarks belong to a user account. This relationship is modeled using JPA and Spring Data JPA repositories in the model module. Our application will use Spring Boot. A Spring Boot application is, at a minimum, a public static void main entry-point and the @EnableAutoConfiguration annotation. This tells Spring Boot to help out, wherever possible.

Documenting the REST API

Example is using Spring REST Docs to document the RESTful service. Spring REST Docs uses Asciidoctor, a high quality hand-written documentation tool, and applies test driven approach to help guarantee the accuracy of service’s documentation. Spring REST Docs makes use of snippets produced by tests written with Spring MVC Test.

Build Configuration

  • Apply the Asciidoctor plugin

plugins { id "org.asciidoctor.convert" version "1.5.2" }
  • Add a dependency on spring-restdocs-mockmvc in the testCompile configuration

dependencies { testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc:1.0.0.RELEASE' }
  • Configure a property to define the output location for generated snippets

ext { snippetsDir = file('build/generated-snippets') }
  • Configure the test task to add the snippets directory as an output

test { outputs.dir snippetsDir }
  • Configure the asciidoctor task

    • Define the source adoc templates directory for Asciidoctor to generate the html files from

    • Define an attribute named snippets that can be used when including the generated snippets in your documentation

    • Configure the snippets directory as an input

    • Make the task depend on the test task so that the tests are run before the documentation is created

asciidoctor {
    sourceDir 'src/main/asciidoc'
    attributes 'snippets': snippetsDir
    inputs.dir snippetsDir
    dependsOn test
}

And that is it. Really. All the tests written for the service in this test class will produce three snippets by default:

  • build/generated-snippets/curl-request.adoc

  • build/generated-snippets/http-request.adoc

  • build/generated-snippets/http-response.adoc

To explore all the more RestDocumentation and RestDocumentationResultHandler has to offer, please visit reference documentation for Spring REST Docs project.

Packaging

Depending on documentation deployment strategy, documentation can be packaged inside the jar/war distribution or copied to e.g. a centralised documentation server on the intranet. To package it into the jar’s static directory simply make the Gradle 'jar' task depend on Gradle 'asciidoctor' task and specify the location in the package where the documentation is preferred to be copied to. When the project is built Asciidoctor originally generates the documentation in the build folder under src/main/asciidoc.

jar {
    dependsOn asciidoctor
    from ("${asciidoctor.outputDir}/html5")
    {
        into 'static/docs'
    }
}

Generating the documentation snippets

As described earlier Spring REST Docs uses Spring’s MVC Test framework to make requests to the service that you are documenting. It then produces documentation snippets for the result’s request and response in specified location (for the adoc templates that live under /src/main/asciidoc to utilize). Spring MVC test needs to be setup in the following manner:

@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("build/generated-snippets");

private RestDocumentationResultHandler document;

@Autowired
private WebApplicationContext context;

private MockMvc mockMvc;

@Before
public void setUp() {
  this.document = document(
    "{method-name}",
    preprocessRequest(prettyPrint()),
    preprocessResponse(prettyPrint())
  );
  this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
    .apply(documentationConfiguration(this.restDocumentation))
    .alwaysDo(this.document)
    .build();
}

Making the application executable

Although it is possible to package this service as a traditional WAR file for deployment to an external application server, the simpler approach demonstrated below creates a standalone application. You package everything in a single, executable JAR file, driven by a good old Java main() method. Along the way, you use Spring’s support for embedding the Tomcat servlet container as the HTTP runtime, instead of deploying to an external instance.

src/main/java/com/df/gs/rest/RestServicesTemplateApplication.java

link:src/main/java/com/df/gs/rest/RestServicesTemplateApplication.java[role=include]

@SpringBootApplication is a convenience annotation that adds all of the following:

  • @Configuration tags the class as a source of bean definitions for the application context.

  • @EnableAutoConfiguration tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.

  • Normally you would add @EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.

  • @ComponentScan tells Spring to look for other components, configurations, and services in the com.df.gs.rest package.

The main() method uses Spring Boot’s SpringApplication.run() method to launch an application. Did you notice that there wasn’t a single line of XML? No web.xml file either. This web application is 100% pure Java and you didn’t have to deal with configuring any plumbing or infrastructure.

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

Using Spring profiles

This example is setup to have two profiles:

  • default profile uses embedded HSQLDB and logs at DEBUG level for the service

  • dev profile connects to a local installation of PostgreSQL and logging level is set to INFO

Notice the difference between database and logging levels in application.properties and application-dev.properties.

Manually testing the service

Now that the service is up, visit http://localhost:8080/mohammadali/bookmarks, and you should see the following response:

{
  "_embedded": {
    "bookmarkResources": [
      {
        "bookmark": {
          "uri": "http://www.google.com",
          "description": "Google search"
        },
        "_links": {
          "bookmarks": {
            "href": "http://localhost:8080/mohammadali/bookmarks"
          },
          "self": {
            "href": "http://localhost:8080/mohammadali/bookmarks/1"
          }
        }
      },
      {
        "bookmark": {
          "uri": "http://www.youtube.com",
          "description": "YouTube"
        },
        "_links": {
          "bookmarks": {
            "href": "http://localhost:8080/mohammadali/bookmarks"
          },
          "self": {
            "href": "http://localhost:8080/mohammadali/bookmarks/2"
          }
        }
      }
    ]
  }
}

If you use Postman for testing web services, please find Postman collection and environment it depends on under src/main/test/resources/postman. All you need to do is to import them in to Postman and that’s it, they are ready to test the service.

Spring Boot Actuator

Notice that the service has a dependency on Spring Boot Actuator. Spring Boot detects the dependency and magically adds production-ready features to help you monitor and manage your application. You can also try & test these e.g. to see the status of the application try http://<host>/health. For more visit its reference documentation.

About

An example to help you hit the ground running when building REST services using Spring.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages