Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Building Web Applications With Spring, Cucumber, and Swagger

DZone 's Guide to

Building Web Applications With Spring, Cucumber, and Swagger

In this post, I will be showing how to build a production ready Java web application that provides some services (REST APIs).

· Web Dev Zone ·
Free Resource

Why?

Because a lot of software developers spend a lot of time building production ready Java-based web applications (with APIs) that include an automated test suite.

My intention is to build a reference application using a proven/robust application stack which can then be used to build applications from the scratch, fast. Maybe 10X faster.

TL;DR

In this post, I will be showing how to build a production ready Java web application that provides some services (REST APIs). The best part is that I will be including a test suite that with one Maven command will test all the APIs. This lays the foundation of how software should be developed from the start using proper unit tests, which allows developers to spend less time wiring the frameworks and spend more time on the actual code and business logic.

We will be using the Spring Boot framework, Cucumber, and Apache Maven.

The entire application code can be downloaded from here. Please give me a *STAR* if you like it.

Part 1: The Puzzle

The Example Application

We will build a sample Weather Tracker application that takes in some parameters, and computes the values (generate statistics). Don’t worry about the calculations. The main point is to the setup and overall application development and build.

Pieces of the Puzzle


Tech stack for this article. All logos are copyright of respective owners.

Tech stck we'll use; all logos are copyright of respective owners.

We will need all the above tech to build a complete web application. Let us see how we can wire all of them together.

Part 2 :  Fixing the Puzzle

Let's build the application progressively.

  • Build a Java web application (and include the code for services — APIs).
  • Add test cases to verify each of the services.
  • Add Swagger for API documentation.
Build — Test — Documentation—(Repeat) — Ship it


SDLC
Illustration — From Scratch to Production

Part 3 :  Getting to Work

Folder Structure

We'll use Spring Boot to create, build, and launch a sample project. Then add the APIs (per our business requirements) and Cucumber tests. Then, we'll use Swagger to generate the API docs. Finally, we'll build the application using Apache Maven.

Below is the folder structure of the sample application.

Illustration of folder structure
Application Folder Structure

Part 3.1. Java Code

The main part of the app will be built woth Spring Boot under thesrc/WeatherTrackerApplication.java file — this is the main file that wires the Java code.

Part 3.2. Add Tests using Cucumber/Gherkins

All tests are under the features folder. Each test file has an extension of .feature

A sample test looks like this gist.
Feature: Add a measurement
  In order to have source information to examine later
  I want to be able to capture a measurement of several metrics at a specific time

  Scenario: Add a measurement with valid (numeric) values
    # POST /measurements
    When I submit a new measurement as follows:
      | timestamp                  | temperature | dewPoint | precipitation |
      | "2015-09-01T16:00:00.000Z" | 27.1        | 16.7     | 0             |
    Then the response has a status code of 201
    And the Location header has the path "/measurements/2015-09-01T16:00:00.000Z"

 Scenario: Cannot add a measurement with invalid values
    # POST /measurements
    When I submit a new measurement as follows:
      | timestamp                  | temperature    | dewPoint | precipitation |
      | "2015-09-01T16:00:00.000Z" | "not a number" | 16.7     | 0             |
    Then the response has a status code of 400

1: Include the test jar in the project in theassets folder. I included the c1-code-test-take-home-tester-1.1.0.tgz file.

2: Add test tasks in pom.xml (as shown below).

<plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.6.0</version>
        <executions>
          <execution>
            <id>install-tester</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>exec</goal>
            </goals>
            <configuration>
              <executable>npm</executable>
              <arguments>
                <argument>install</argument>
                <argument>--no-save</argument>
                <argument>./assets/c1-code-test-take-home-tester-${takeHomeTester.version}.tgz</argument>
                <argument>--prefix</argument>
                <argument>.</argument>
              </arguments>
            </configuration>
          </execution>
          ...
          ...


3: When you run the command mvn clean verify the below task from pom.xml is called.

<plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.6.0</version>
        <executions>
          <execution>
            <id>integration-test</id>
            <phase>verify</phase>
            <goals>
              <goal>exec</goal>
            </goals>
            <configuration>
              <skip>${skipTests}</skip>
              <executable>node</executable>
              <arguments>
                <argument>--no-warnings</argument>
                <argument>${npm.binDirectory}/take-home-integration-test</argument>
                <argument>features</argument>
                <argument>--check-new</argument>
                <argument>--command</argument>
                <argument>java -jar ${project.build.directory}/${project.build.finalName}.jar</argument>
                <argument>--port</argument>
                <argument>${takeHomeTester.port}</argument>
                <argument>--out-file</argument>
                <argument>${takeHomeTester.logFile}</argument>
                <argument>--</argument>
                <argument>--tags</argument>
                <argument>not @skip</argument>
              </arguments>
            </configuration>
          </execution>
        </executions>

4: The test scenarios defined in the .feature files test each API using the application URLhttp:\\localhost:8000\ and show the result.

Part 3.3. Adding Swagger

Swagger is a great open-source package that generates documentation for APIs in our code. The best part is that it also creates the web UI for us. A URL like this, http://localhost:8000/swagger-ui.html#, will load the API docs.

We have to add some details around our classes, methods, and params for the docs to look more detailed, though.

1: Add dependencies to pom.xml:

<!-- Swagger -->
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger2</artifactId>
  <version>2.9.2</version>
</dependency>
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger-ui</artifactId>
  <version>2.9.2</version>
</dependency>

2: Add the primary config class.

The file can be anywhere under your src folder. The best option is to place it at the same level as your main @SpringBootApplication config class.

package com.weathertracker;

import static springfox.documentation.builders.PathSelectors.regex;
import java.util.Collections;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * Swagger configuration file to generate API documentation
 */
@Configuration
@EnableSwagger2
public class Swagger2Config {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2).select()
                .apis(RequestHandlerSelectors
                        .basePackage("com.capitalone.weathertracker"))
                .paths(PathSelectors.regex("/.*"))
                .build()
                .apiInfo(apiEndPointsInfo());
    }
    private ApiInfo apiEndPointsInfo() {
        return new ApiInfoBuilder()
                .title("Weather Tracker API Documentation")
                .description("Weather Tracker REST API")
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
                .version("1.0.0")
                .build();
    }
}

The file can be anywhere under your src folder. The best option is to place it at the same level as your main @SpringBootApplication config class.

3: Test. Visit the URL http://localhost:8000/swagger-ui.html#/. This should load the documentation page as

The API documentation page is generated by Swagger.

Part 4: Wiring it All Together , the  Final Test

Run this command and you should see all tests passed and application running at localhost:8000.

<project-root>$ mvn spring-boot:run -e

Resources

Topics:
swagger ,cucumber ,web dev ,java web development ,spring boot tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}