DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Building Scalable Real-Time Apps with AstraDB and Vaadin
Register Now

Trending

  • Which Is Better for IoT: Azure RTOS or FreeRTOS?
  • RAML vs. OAS: Which Is the Best API Specification for Your Project?
  • What to Pay Attention to as Automation Upends the Developer Experience
  • How Agile Works at Tesla [Video]

Trending

  • Which Is Better for IoT: Azure RTOS or FreeRTOS?
  • RAML vs. OAS: Which Is the Best API Specification for Your Project?
  • What to Pay Attention to as Automation Upends the Developer Experience
  • How Agile Works at Tesla [Video]
  1. DZone
  2. Coding
  3. Frameworks
  4. Building Web Applications With Spring, Cucumber, and Swagger

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).

Suren Konathala user avatar by
Suren Konathala
·
Updated May. 10, 19 · Tutorial
Like (2)
Save
Tweet
Share
11.45K Views

Join the DZone community and get the full member experience.

Join For Free

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

  • Source files for the example project are here
  • Behaviour-Driven Development
  • Using Spring boot
  • Using Swagger with Spring Boot
Spring Framework application Web Service Testing Spring Boot Cucumber (software) Build (game engine) Web application

Published at DZone with permission of Suren Konathala. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Which Is Better for IoT: Azure RTOS or FreeRTOS?
  • RAML vs. OAS: Which Is the Best API Specification for Your Project?
  • What to Pay Attention to as Automation Upends the Developer Experience
  • How Agile Works at Tesla [Video]

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: