API development (Part 1): Spring Boot, Jersey and Swagger always happy together

19 October
The API world. Graphic from Wikimedia

We are on the cusp of the API economy: APIs are everywhere, boosting the digital transformation and disrupting the way we think. So a shifting is required also in the way we develop.

APIs are expected to enable automation, in turn driving efficiency, consistency and cost savings. API quality matters, both for API consumers and implementers. For these reasons, building an API infrastructure from scratch may not be a good idea. It is much easier and more productive to use a good framework or library, often more than one.

From a development point of view, it's crucial to achieve target whilst ensuring the fulfillment of the following requirements: timing, costs saving and quality. Standardization is one of important way to achieve those goals: to ensure consistency, speed-up development, enable factorization and simplify maintanance.

Furthermore, a very important factor in APIs is a complete and accurate documentation. And best of all, the documentation should be produced and provided in a standard form, to automate the documentation process and to ensure a great overall experience in API consuming.

Even for the simplest API, achieving all these goals and accomplishing all the required tasks may be not so simple for a developer. A minimal infrastructure must be setted up, a set of components has to be selected, configured and enabled to work together. The API implementation stack configuration can be a complex, repetitive and error-prone process. The developer should not take care about the configuration and components integration details, focusing on the business tasks the API has to face and resolve.

It is where standards, frameworks and libraries come to help, taking charge of the API infrastructure setup and configuration and leaving the developer free to focus on the API goals. In one sentence: focus on what matters and forget the tedious stuff.

The Holon Platform can act both as glue for industry-standard libraries and as a catalyst for API development productivity.

In this post, we'll start from the beginning, showing how to create a simple API service. We'll focus on project setup and configuration, leaving out the API business logic concerns. In fact, this API will provide a single "ping" operation, which will respond with a pong message.

The building blocks we're going to use for this project are:

  1. Spring Boot for auto-configuration and execution using an embedded servlet container
  2. Jersey, the reference JAX-RS implementation, to create the API operations using the RESTful paradigm
  3. JSON as data interchange format
  4. Swagger (OpenAPI) for API documentation
  5. Spring Boot Actuator for service monitoring and management
  6. And of course, the Holon Platform JAX-RS module, to leverage on some configuration facilities and automate the API documentation creation and provisioning

The code of this example is available on GitHub: https://github.com/holon-platform/spring-boot-jaxrs-swagger-api-example.

Creating the API application

Maven is used for project setup and dependency management, so let's start with configuring the project's pom dependencies.

First of all, we import the Holon Platform BOM (Bill Of Materials), this way we'll no longer need to specify the Holon Platform artifacts version. The right version of each artifact is declared and provided by the platform BOM.

<dependencyManagement>
  <dependencies>
    <!-- Holon Platform BOM -->
    <dependency>
      <groupId>com.holon-platform</groupId>
      <artifactId>bom</artifactId>
      <version>5.0.2</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

We'll use the Holon JAX-RS Spring Boot starter with Jersey as implementation, so we declare the following dependency:

<!-- Holon JAX-RS using Jersey -->
<dependency>
  <groupId>com.holon-platform.jaxrs</groupId>
  <artifactId>holon-starter-jersey</artifactId>
</dependency>

Do you prefer to use Resteasy as JAX-RS implementation? With Holon it's only a matter of configuration, just change the Holon starter to use:

<!-- Holon JAX-RS using Resteasy -->
<dependency>
  <groupId>com.holon-platform.jaxrs</groupId>
  <artifactId>holon-starter-resteasy</artifactId>
</dependency>

These Holon Spring Boot starters inherit the standard Spring Boot web starters, and provide embedded servlet container configuration, logging and Holon specific auto-configuration facilities. By default, Tomcat is used as embedded servlet container. Want to use Undertow? Just change the starter name (for example, holon-starter-jersey-undertow). Concerning JSON data format instead, Jackson is automatically setted up. What if Gson is your preferred choice? It's only about changing a name, again (for example, holon-starter-jersey-gson).

Now, independently from the starter you choosed, we have to create just 2 Java classes. The first one, which we call Application, is the Spring Boot application entry-point, which triggers auto-configuration and provides the main method used to run the application itself, starting the embedded servlet container and deploying our API endpoints:

@SpringBootApplication
public class Application {

  public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
  }
	
}

A application.yml file can be used to provide application configuration properties. For example, to configure the embedded server port:

server:
  port: 9999

Next it's time to create the API endpoint, which will provide the API operations listening to the HTTP requests and returning the corresponding responses, using JSON as data format. As said before, this simple API will only provide a ping operation, mapped to the GET request method, returning a pong response encoded as JSON. Finally, we want to map the API operations endpoint to the base "/api" path. Using JAX-RS, this is how the API endpoint can be defined:

@Component
@Path("/api")
public class ApiEndpoint {

    @GET
    @Path("/ping")
    @Produces(MediaType.APPLICATION_JSON)
    public Response ping() {
        return Response.ok("pong").build();
    }

}

Note the @Component annotation on the API endpoint class. This is a standard Spring annotation to declare this class as a Spring component, candidate for auto-detection. Relying on the Holon Platform auto-configuration features, this class will be automatically detected and registered as a JAX-RS resource in Jersey (or Resteasy). And of course, will be enabled as a Spring component, allowing, for example, dependency injections.

To run the application, we'll use the Spring Boot maven plugin, declaring it in the project pom:

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <executions>
        <execution><goals><goal>repackage</goal></goals></execution>
      </executions>
    </plugin>
  </plugins>
</build>

This way, a runnable jar will be created by the Spring Boot plugin, with all the required dependencies and able to be execute standalone using a JRE.

To test the application, we can use the run Spring Boot maven goal this way:

mvn spring-boot:run

That's it. The application can be now started, activating our API service. The ping operation will be available sending an HTTP GET request to an URL like this:

http://hostname:9999/api/ping
Obtaining a response like the following:

HTTP/1.1 200
Content-Type: application/json
Content-Length: 4
post

Documenting the API operations

We'll use Swagger for API documentation. The Swagger specification is now the foudation of the Open API Initiative, which is trying to standardizing on how REST APIs are described.

The Holon Platform provides many configuration facilities for Swagger, perfectly integrated with JAX-RS and the Spring Boot auto-configuration architecture.

Let's start adding the Holon Platform Swagger depencency to our project pom:

<dependency>		
  <groupId>com.holon-platform.jaxrs</groupId>
  <artifactId>holon-jaxrs-swagger</artifactId>
</dependency>

From now on, the Holon Platform auto-configuration services will auto-detect any JAX-RS endpoint annotated with the standard Swagger @Api annotation and automatically create a JAX-RS endpoint to generate and provide the Swagger API documentation. By default, this endpoint will be mapped to the /api-docs path and supports a type query parameter to obtain the Swagger API documentation as JSON (the default behaviour) or YAML.

Standard Swagger annotations are supported to enrich and configure the API documentation, such as @ApiOperation. Additionaly, the Holon Platform Swagger module provides the @ApiDefinition annotation, which can be used to configure the overall API informations (such the title and the version) and to change the default API documentation endpoint path. In this example, we want to use the /api/docs path to provide the API documentation.

So you want to modify the ApiEndpoint class this way:

@ApiDefinition(docsPath = "/api/docs", title = "Example API", version = "v1", prettyPrint = true)
@Api("Test API")
@Component
@Path("/api")
public class ApiEndpoint {

    @ApiOperation("Ping request")
    @ApiResponses({ @ApiResponse(code = 200, message = "OK: pong", response = String.class) })
    @GET
    @Path("/ping")
    @Produces(MediaType.APPLICATION_JSON)
    public Response ping() {
        return Response.ok("pong").build();
    }

}

This way, the Swagger API documentation can be obtained in JSON format from the URL:

http://hostname:9999/api/docs

Or in the YAML format:

http://hostname:9999/api/docs?type=yaml

Using the Swagger Editor to display the API documentation, it will appear like this:

Monitoring the API application

As a last step, we want to add application monitoring and management capabilities, using the Spring Boot Actuator, which adds several production grade services to obtain application information, health check, configuration and so on.

To enable the Spring Boot Actuator endpoints auto-configuration, we have to add the following dependencies to the project pom:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>4.3.11.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
  <version>1.5.8.RELEASE</version>
</dependency>

Now a set of monitoring endpoints should be registered. For example, the health check endpoint listens to the /health path. So we expect to obtain the health information performing a GET request to an URL like this:

http://localhost:9999/health

But wait... things do not go as we expected: the server renponds with a 404 (not found) error code! Why?

This is a well-known and annoying problem which occurs when the Jersey servlet is mapped to the root context path. The problem is that Jersey will get all the request. It does not know that it needs to forward to any actuator endpoints.

This can be resolved by change Jersey to be used as filter instead of a servlet. Using Spring Boot we can do this using a configuration property in the application.yml file:

spring:
  jersey:
    type: filter

But this is not enough: we also have to set the Jersey property to forward requests for URLs it doesn't know. With the Holon Platform JAX-RS module this is simple, just another configuration property to set:

holon:
  jersey:
    forwardOn404: true

Well done, everything work as expected! The health check endpoint is reachable and provides the following JSON response content:

{"status":"UP"}

Summary

With 2 Java classes, a pom and a Spring Boot configuration file we setted up a production grade API application, able to be runned standalone, with API documentation and monitoring capabilities. Now it's time to focus on business tasks, making the API somehow useful!

This this only the first article in a series that shows how to use the Holon Platform to face the API development challenges, including the microservices world, so stay tuned!


The source code of the example API created in this post is available on GitHub: https://github.com/holon-platform/spring-boot-jaxrs-swagger-api-example.

See the Holon Platform examples for other API development related sample projects.

  • Riccardo Righi

We use cookies to ensure that we give you the best experience on our website.