To build the application requires:
- Java 11
- Maven 3
To build a .jar file with Maven, from the project directory, use
mvn clean install
This will run all tests, including integration tests. To skip these, use:
mvn clean install -DskipTests
To run the resulting service locally, use:
java -Dparking.rate.location=<location-of-startup-rates>.json -jar <path-to-jar-file>/<jar-file-name>.jar
For example, if running from the project directory:
java -Dparking.rate.location=src/main/resources/rates.json -jar target/parking-service-1.0.0.jar
If no location is provided for an initial file of rates, it will be loaded from src/main/resources/rates.json if possible.
- Docker
First build the .jar file as above. Then (from the project directory) build a docker image using:
docker build -t <repo/image-name:tag> .
For example:
docker build -t test/parking:latest .
To run the built container use:
docker run -d --name <container-name> -p 5000:5000 <repo/image-name:tag>
For example:
docker run -d --name parking -p 5000:5000 test/parking:latest
Both of these examples will use the initial rates.json file in src/main/resources. It can be replaced using the API.
All endpoints are relative to:
http://localhost:5000/
There are two endpoints for rates.
GET /rates
returns a JSON representation of current rates, for example:
{
"rates": [
{
"days" : "mon,tues,thurs",
"times" : "0900-2100",
"tz" : "America/Chicago",
"price" : 1500
},
{
"days" : "fri,sat,sun",
"times" : "0900-2100",
"tz" : "America/Chicago",
"price" : 2000
},
{
"days" : "wed",
"times" : "0600-1800",
"tz" : "America/Chicago",
"price" : 1750
},
{
"days" : "mon,wed,sat",
"times" : "0100-0500",
"tz" : "America/Chicago",
"price" : 1000
},
{
"days" : "sun,tues",
"times" : "0100-0700",
"tz" : "America/Chicago",
"price" : 925
}
]
}
To replace existing rates, PUT to the same resource:
PUT /rates
Content-type: application/json
{
"rates": [
{
"days" : "mon,tues,thurs",
"times" : "0900-2200",
"tz" : "America/New_York",
"price" : 1500
},
{
"days" : "fri,sat,sun",
"times" : "0900-2200",
"tz" : "America/New_York",
"price" : 2100
},
{
"days" : "wed",
"times" : "0600-1800",
"tz" : "America/Chicago",
"price" : 1750
},
{
"days" : "mon,wed,sat",
"times" : "0100-0500",
"tz" : "America/Chicago",
"price" : 750
},
{
"days" : "sun,tues",
"times" : "0100-0700",
"tz" : "America/Chicago",
"price" : 900
}
]
}
To find a price for parking:
GET /price?start=<ISO-8601 date/time with offset>&end=<ISO-8601 date/time with offset>
For example:
GET /price?start=2015-07-01T07:00:00-05:00&end=015-07-01T12:00:00-05:00
If a price is found, it is returned as JSON with status 200 OK
{'price': 1750}
If a price cannot be determined, the following is returned with status 404 Not Found
unavailable
Since
+in a URL (including a query parameter) will be turned into a space and result in a400 Bad Requestresult, characters must be percent-encoded as%2B.For example:
2015-07-04T20:00:00+05:00must be encoded to2015-07-04T20:00:00%2B05:00
- If a given date/time range spans more than one day, the price will be unavailable
- If more than one price would match, the price will be unavailable
- Otherwise, if a given date/time range would be completely encompassed by one of the rates, it will be returned. This is based on date/times representing the same instant in time once the offset is applied.
Prometheus-style metrics are available at:
GET /actuator/prometheus
In addition to a set of default JVM metrics, we can find count and timing information for endpoint requests. For example:
http_server_requests_seconds_countis the total number of requests the application received at this endpointhttp_server_requests_seconds_sumis the sum of the duration of every request the application received at this endpointhttp_server_requests_seconds_maxis the maximum request duration during a time window (default window is 2 minutes)http_server_requests_secondswith the tagquantile="0.95"is the slowest duration that 95% of requests are seeing
Example output for the prometheus metrics endpoint itself look like this:
http_server_requests_seconds_count{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",} 3.0
http_server_requests_seconds_sum{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",} 0.047001569
http_server_requests_seconds_max{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",} 0.027652642
http_server_requests_seconds{exception="None",method="GET",outcome="SUCCESS",status="200",uri="/actuator/prometheus",quantile="0.95",} 0.027262976
Tags show:
- the exception, if any
- the method (GET, PUT, etc.)
- the outcome
- the returned HTTP status code
- the URI
In conjunction with Prometheus (and Grafana for visualization) you can use the tags to view only the metrics you wish (such as the number of errors, etc.)
Swagger API definitions are available in JSON at:
http://localhost:5000/v3/api-docs
or in YAML at:
http://localhost:5000/v3/api-docs.yaml
A Swagger UI is available at:
http://localhost:5000/swagger-ui