Public | Automated Build

Last pushed: 5 months ago
Short Description
A sample Spring Boot RESTful API microservice, backed by MongoDB.
Full Description

Candidate Service

Introduction

The Candidate Spring Boot Service is a RESTful Web Service, backed by MongoDB. The Candidate service exposes several HTTP API endpoints, listed below. API users can retrieve a list candidates, add a new candidate, and inspect technical information about the running service. API users can also create a sample list of candidates, based on the 2016 US Presidential Election, by calling the /simulation endpoint.

The Candidate service is designed to work along with the Voter Service, as part of a complete API. The Voter service is dependent on the Candidate service to supply a list of candidates. The Candidate service is called by the Voter service, using one of three methods:

  1. HTTP-based Synchronous IPC, when either the Voter service's /voter/candidates/http/{election} or /voter/simulation/http/{election} endpoints are called.
  2. Messaging-based Remote Procedure Call (RPC) IPC, when either the Voter service's /voter/candidates/rpc/{election} or /voter/simulation/rpc/{election} endpoints are called.
  3. Messaging-based Eventual Consistency, when either the Voter service's /voter/candidates/db/{election} or /voter/simulation/db/{election} endpoints are called.

Quick Start for Local Development

The Candidate service requires MongoDB to be running locally, on port 27017, RabbitMQ running on 5672 and 15672, and the Voter service to be running on 8099. To clone, build, test, and run the Candidate service as a JAR file, locally:

git clone --depth 1 --branch rabbitmq \
  https://github.com/garystafford/candidate-service.git
cd candidate-service
./gradlew clean cleanTest build
java -jar build/libs/candidate-service-0.3.0.jar

Getting Started with the API

The easiest way to get started with the Candidate and Voter services API, using HTTPie from the command line:

  1. Create sample candidates: http http://localhost:8097/candidate/simulation
  2. View sample candidates: http http://localhost:8097/candidate/candidates/summary/2016%20Presidential%20Election
  3. Create sample voter data: http http://localhost:8099/voter/simulation/2016%20Presidential%20Election
  4. View sample voter results: http http://localhost:8099/voter/results

Alternately, for step 3 above, you can use service-to-service RPC IPC with RabbitMQ, to retrieve the candidates:
http http://localhost:8099/voter/simulation/rpc/2016%20Presidential%20Election

Alternately, for step 3 above, you can use eventual consistency using RabbitMQ, to retrieve the candidates from MongoDB:
http http://localhost:8099/voter/simulation/db/2016%20Presidential%20Election

Service Endpoints

The service uses a context path of /candidate. All endpoints must be are prefixed with this sub-path.

Purpose Method Endpoint
Create Set of Sample Candidates GET /candidate/simulation
Submit New Candidate POST /candidate/candidates
Candidates GET /candidate/candidates
Candidate Summary by Election GET /candidate/candidates/search/findByElectionContains?election={election}&projection=candidateVoterView
Candidate Summary by Election GET /candidate/candidates/summary/{election}
Service Info GET /candidate/info
Service Health GET /candidate/health
Service Metrics GET /candidate/metrics
Other Spring Actuator endpoints GET /candidate/mappings, /candidate/env, /candidate/configprops, etc.
Other HATEOAS endpoints for /candidate/candidates Various DELETE, PATCH, PUT, page sort, size, etc.

The HAL Browser API browser for the hal+json media type is installed alongside the service. It can be accessed at http://localhost:8097/candidate/actuator/.

New Candidate

Adding a new candidate requires an HTTP POST request to the /candidate/candidates endpoint, as follows:

HTTPie

http POST http://localhost:8097/candidate/candidates \
  firstName='Mary' \
  lastName='Smith' \
  politicalParty='Test Party' \
  election='2016 Presidential Election'

cURL

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{ "firstName": "Mary", "lastName": "Smith", "politicalParty": "Test Party", "election": "2016 Presidential Election" }' \
  "http://localhost:8097/candidate/candidates"

wget

wget --method POST \
  --header 'content-type: application/json' \
  --body-data '{ "firstName": "Mary", "lastName": "Smith", "politicalParty": "Test Party", "election": "2016 Presidential Election" }' \
  --no-verbose \
  --output-document - http://localhost:8097/candidate/candidates

Sample Output

Using HTTPie command line HTTP client.

http http://localhost:8097/candidate/simulation

{
    "message": "Simulation data created!"
}

http http://localhost:8097/candidate/candidates/summary/2016%20Presidential%20Election

{
    "candidates": [
        {
            "election": "2016 Presidential Election",
            "fullName": "Darrell Castle",
            "politicalParty": "Constitution Party"
        },
        {
            "election": "2016 Presidential Election",
            "fullName": "Hillary Clinton",
            "politicalParty": "Democratic Party"
        },
        {
            "election": "2016 Presidential Election",
            "fullName": "Gary Johnson",
            "politicalParty": "Libertarian Party"
        }
    ]
}

http http://localhost:8097/candidate/candidates

{
    "_embedded": {
        "candidates": [
            {
                "_links": {
                    "candidate": {
                        "href": "http://localhost:8097/candidate/candidates/590549471b8ebf721accc36b{?projection}",
                        "templated": true
                    },
                    "self": {
                        "href": "http://localhost:8097/candidate/candidates/590549471b8ebf721accc36b"
                    }
                },
                "election": "2012 Presidential Election",
                "firstName": "Rocky",
                "fullName": "Rocky Anderson",
                "lastName": "Anderson",
                "politicalParty": "Justice Party"
            },
            {
                "_links": {
                    "candidate": {
                        "href": "http://localhost:8097/candidate/candidates/590549471b8ebf721accc36c{?projection}",
                        "templated": true
                    },
                    "self": {
                        "href": "http://localhost:8097/candidate/candidates/590549471b8ebf721accc36c"
                    }
                },
                "election": "2016 Presidential Election",
                "firstName": "Darrell",
                "fullName": "Darrell Castle",
                "lastName": "Castle",
                "politicalParty": "Constitution Party"
            }
        ]
    },
    "_links": {
        "profile": {
            "href": "http://localhost:8097/candidate/profile/candidates"
        },
        "search": {
            "href": "http://localhost:8097/candidate/candidates/search"
        },
        "self": {
            "href": "http://localhost:8097/candidate/candidates"
        }
    },
    "page": {
        "number": 0,
        "size": 20,
        "totalElements": 12,
        "totalPages": 1
    }
}

http POST http://localhost:8097/candidate/candidates \ firstName='John' \ lastName='Doe' \ politicalParty='Test Party' \ election='2016 Presidential Election'


    "_links": {
        "candidate": {
            "href": "http://localhost:8097/candidate/candidates/59054a341b8ebf721accc378{?projection}",
            "templated": true
        },
        "self": {
            "href": "http://localhost:8097/candidate/candidates/59054a341b8ebf721accc378"
        }
    },
    "election": "2016 Presidential Election",
    "firstName": "John",
    "fullName": "John Doe",
    "lastName": "Doe",
    "politicalParty": "Test Party"
}

Continuous Integration

The project's source code is continuously built and tested on every commit to GitHub, using Travis CI. If all unit tests pass, the resulting Spring Boot JAR is pushed to the build-artifacts branch of the candidate-service GitHub repository. The JAR's filename is incremented with each successful build (i.e. candidate-service-0.3.18.jar).

Spring Profiles

The Candidate service includes several Spring Boot Profiles, in a multi-profile YAML document: src/main/resources/application.yml. The profiles are default, docker-development, docker-production, and aws-production. You will need to ensure your MongoDB instance is available at that host address and port of the profile you choose, or you may override the profile's properties.

endpoints:
  enabled: true
  sensitive: false
info:
  java:
    source: "${java.version}"
logging:
  level:
    root: INFO
management:
  info:
    build:
      enabled: true
    git:
      mode: full
server:
  port: 8097
  context-path: /candidate
spring:
  data:
    mongodb:
      database: candidates
      host: localhost
      port: 27017
  rabbitmq:
    host: localhost
---
spring:
  data:
    mongodb:
      host: mongodb
  rabbitmq:
    host: rabbitmq
  profiles: docker-local
---
---
endpoints:
  enabled: false
  health:
    enabled: true
  info:
    enabled: true
  sensitive: true
logging:
  level:
    root: WARN
management:
  info:
    build:
      enabled: false
    git:
      enabled: false
spring:
  data:
    mongodb:
      host: "10.0.1.6"
  rabbitmq:
    host: "10.0.1.8"
  profiles: aws-production
---
endpoints:
  enabled: false
  health:
    enabled: true
  info:
    enabled: true
  sensitive: true
logging:
  level:
    root: WARN
management:
  info:
    build:
      enabled: false
    git:
      enabled: false
spring:
  data:
    mongodb:
      host: mongodb
  rabbitmq:
    host: rabbitmq
  profiles: docker-production

All profile property values may be overridden on the command line, or in a .conf file. For example, to start the Candidate service with the aws-production profile, but override the mongodb.host value with a new host address, you might use the following command:

java -jar <name_of_jar_file> \
  --spring.profiles.active=aws-production \
  --spring.data.mongodb.host=<new_host_address>
  -Dlogging.level.root=DEBUG \
  -Djava.security.egd=file:/dev/./urandom

References

Docker Pull Command
Owner
garystafford
Source Repository