-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from iplantemn/feature/rest-api
Feature/rest api
- Loading branch information
Showing
12 changed files
with
439 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,98 @@ | ||
# imdb-movies-api | ||
Movies API for the IMDB SmartThings project | ||
Movies API for the IMDB SmartThings project. | ||
|
||
## Building | ||
Movies API is a Spring Boot application backed by a MySQL database. | ||
|
||
| Operating System | Command | | ||
| :--------------- | :---------------- | | ||
| macOS | `./gradlew build` | | ||
| Windows | `gradlew build` | | ||
This API leverages a few packages on top of Spring Boot for ease of development: | ||
* **Project Lombok**: provides annotations to replace boilerplate code in POJOs, such as constructors, getters & setters, etc. | ||
* **Spring Data REST**: automagically implements a fully-fledged RESTful API based on a data `Repository` with simple annotations. | ||
This REST API supports sorting & pagination out of the box. | ||
|
||
## Deploying to Docker | ||
## Build | ||
|
||
Once you've built the application, navigate to the root of the project and run one of these commands: | ||
Movies API uses the Gradle build tool. It is recommended to use the Gradle Wrapper to ensure cross-platform compatibility and enforce | ||
a validated version. | ||
|
||
* For macOS: `./gradlew <task>` | ||
* For Windows: `gradlew <task>` | ||
|
||
Here are the various tasks and how to use them: | ||
|
||
| Gradle task | Description | | ||
| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| `build` | Complete build task - compiles `main` and `test`, runs the test suite and validate coverage, analyzes code with `PMD`, and builds the `.jar` | | ||
| `test` | Compiles the test code, and runs the test suite, validates coverage, and performs `PMD` analysis. | | ||
| `pmdMain` | Analyzes `main` code with `PMD`. | | ||
| `pmdTest` | Analyzes `test` code with `PMD`. | | ||
|
||
You can additionally exclude some parts of a task with the `-x` flag. For example, `gradlew build -x test` will exclude all parts of the `test` task. | ||
|
||
## Deployments | ||
|
||
**Warning**: The first deployment of the application will be slower than the subsequent deployments, because the application will seed the database. | ||
|
||
### Prerequisites | ||
|
||
Before you can deploy the application: | ||
1. the executable `.jar` must be generated by running the `build` Gradle task | ||
1. the database must be deployed to Docker | ||
|
||
### Database | ||
|
||
The database is only meant to be deployed to Docker. The `Dockerfile` and a SQL script to generate the schema are located in `.docker/`. | ||
To deploy the MySQL database to Docker: | ||
1. Ensure that Docker is running on your system | ||
1. From the root of the imdb-movies-api project, run the following command: | ||
```shell script | ||
docker-compose up --build # build image & launch a containers for database and service | ||
docker-compose up movies-db --build # build image & launch container for database only | ||
docker-compose up movies-db --build | ||
``` | ||
|
||
## API versioning | ||
|
||
| Version | Description | | ||
| -------- | :---------- | | ||
| `api/v1` | Completely implemented with Spring Data REST. | | ||
|
||
|
||
## TODO | ||
1. ~~Dockerize app and database~~ | ||
1. ~~Implement Spring Data REST~~ | ||
1. Insert seed data into database | ||
1. ~~Entity - fetch genres & studio~~ | ||
1. Set to api/v1/xyz | ||
1. Implement Swagger & document | ||
1. Create Postman collection | ||
1. Integration tests | ||
1. Implement linter | ||
1. Jacoco coverage | ||
1. ~~Use Lombok for entity~~ | ||
1. ArchUnit tests | ||
### Local API deployment | ||
|
||
Once you have executed the Gradle `build` task and deployed the MySQL database to Docker, you can deploy the Spring Boot application as such: | ||
|
||
```shell script | ||
java -Dspring.profiles.active=local -jar ./build/libs/movies-<version>-.jar | ||
``` | ||
|
||
### Docker API deployment | ||
|
||
Once you have executed the Gradle `build` task, you can deploy the Spring Boot application as such: | ||
|
||
```shell script | ||
|
||
docker-compose up movies-api --build # if the database is already deployed | ||
``` | ||
|
||
## Usage | ||
|
||
The application is accessible at the following base URLs: | ||
|
||
| Environment | Base URL | | ||
| :---------- | :-------------------- | | ||
| Local | https://localhost:8080 | | ||
| Docker | https://localhost:5012 | | ||
|
||
### API Docs | ||
|
||
#### Postman | ||
|
||
For easy interaction with the API, you can import the Postman collection in `./postman`. | ||
|
||
#### HATEOAS | ||
|
||
Spring Data REST publishes its data using HATEOAS, which uses the API responses and hypermedia to deliver a self- | ||
documenting API. You can start with: | ||
|
||
```shell script | ||
curl -X GET https://localhost:8080/api/v1/movies # Local | ||
curl -X GET https://localhost:5012/api/v1/movies # Docker | ||
``` | ||
|
||
#### Spring Boot Actuator | ||
|
||
You can also use the Spring Boot Actuator mappings endpoint to get a list of endpoints: | ||
|
||
```shell script | ||
curl -X GET 'https://localhost:8080/actuator/mappings' # Local | ||
curl -X GET 'https://localhost:5012/actuator/mappings' # Docker |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
{ | ||
"variables": [], | ||
"info": { | ||
"name": "Movies API", | ||
"_postman_id": "3ba62dc1-2ca5-5012-75be-3b5dc4d29831", | ||
"description": "", | ||
"schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" | ||
}, | ||
"item": [ | ||
{ | ||
"name": "GET /movies", | ||
"request": { | ||
"url": "https://localhost:5012/api/v1/movies?size=20&page=0&sort=title=desc", | ||
"method": "GET", | ||
"header": [], | ||
"body": { | ||
"mode": "formdata", | ||
"formdata": [] | ||
}, | ||
"description": "" | ||
}, | ||
"response": [] | ||
}, | ||
{ | ||
"name": "GET /movies by ID", | ||
"request": { | ||
"url": "https://localhost:5012/api/v1/movies/{{movieId}}", | ||
"method": "GET", | ||
"header": [], | ||
"body": { | ||
"mode": "formdata", | ||
"formdata": [] | ||
}, | ||
"description": "Replace {{movieId}} with an actual ID" | ||
}, | ||
"response": [] | ||
}, | ||
{ | ||
"name": "GET /movies/ID/cast", | ||
"request": { | ||
"url": "https://localhost:5012/api/v1/movies/{{movieId}}/cast?size=20&page=0&sort=title=desc", | ||
"method": "GET", | ||
"header": [], | ||
"body": { | ||
"mode": "formdata", | ||
"formdata": [] | ||
}, | ||
"description": "Replace {{movieId}} with an actual ID" | ||
}, | ||
"response": [] | ||
}, | ||
{ | ||
"name": "GET /movies/search/cast", | ||
"request": { | ||
"url": "https://localhost:5013/api/v1/movies/search/castId?castId={{castId}}", | ||
"method": "GET", | ||
"header": [], | ||
"body": { | ||
"mode": "formdata", | ||
"formdata": [] | ||
}, | ||
"description": "Replace {{castId}} with an actual ID" | ||
}, | ||
"response": [] | ||
}, | ||
{ | ||
"name": "POST /movies", | ||
"request": { | ||
"url": "https://localhost:5012/api/v1/movies", | ||
"method": "POST", | ||
"header": [ | ||
{ | ||
"key": "Content-Type", | ||
"value": "application/json", | ||
"description": "" | ||
} | ||
], | ||
"body": { | ||
"mode": "raw", | ||
"raw": "{\n\t\"title\": \"The Hitchhiker's Guide to the Galaxy\",\n\t\"lengthMinutes\": 109,\n\t\"releaseDate\": \"2005-04-29\",\n\t\"genres\": [\"Adventure\", \"Comedy\", \"Sci Fi\"],\n\t\"studios\": [\"Touchstone Pictures\", \"Spyglass Entertainment\"],\n\t\"synopsis\": \"Mere seconds before the Earth is to be demolished by an alien construction crew, journeyman Arthur Dent is swept off the planet by his friend Ford Prefect, a researcher penning a new edition of The Hitchhiker's Guide to the Galaxy.\"\n}" | ||
}, | ||
"description": "" | ||
}, | ||
"response": [] | ||
}, | ||
{ | ||
"name": "PATCH /movies by ID", | ||
"request": { | ||
"url": "https://localhost:5012/api/v1/movies/{{movieId}}", | ||
"method": "PATCH", | ||
"header": [ | ||
{ | ||
"key": "Content-Type", | ||
"value": "application/json", | ||
"description": "" | ||
} | ||
], | ||
"body": { | ||
"mode": "raw", | ||
"raw": "{\n\t\"synopsis\": \"42\"\n}" | ||
}, | ||
"description": "Replace {{movieId}} with an actual ID" | ||
}, | ||
"response": [] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
src/main/java/com/iplante/imdb/movies/configuration/CastApiConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.iplante.imdb.movies.configuration; | ||
|
||
import lombok.Getter; | ||
import lombok.Setter; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.stereotype.Component; | ||
|
||
/** | ||
* Configuration object for the Cast API. | ||
* | ||
* @author Isabelle Plante | ||
* @version 1 | ||
* @since 8/27/20 | ||
*/ | ||
@Getter | ||
@Setter | ||
@Component | ||
@ConfigurationProperties(prefix = "cast-api") | ||
public class CastApiConfiguration { | ||
|
||
/** | ||
* The base URL of the Cast API. | ||
*/ | ||
private String baseUrl; | ||
} |
46 changes: 46 additions & 0 deletions
46
src/main/java/com/iplante/imdb/movies/configuration/RestConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.iplante.imdb.movies.configuration; | ||
|
||
import com.fasterxml.jackson.databind.DeserializationFeature; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import org.springframework.boot.web.client.RestTemplateBuilder; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.hateoas.MediaTypes; | ||
import org.springframework.hateoas.mediatype.hal.Jackson2HalModule; | ||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
import java.util.Collections; | ||
|
||
/** | ||
* Configure {@link RestTemplate} to deserialize HAL JSON automatically. This is necessary because | ||
* Spring Data REST uses HATEOAS delivers data through hypermedia. | ||
* <p> | ||
* See: <a href="https://gist.github.com/ripla/6f1516e3d0c28f4d591303d4060342d4">Source</a> | ||
* | ||
* @author Isabelle Plante | ||
* @version 1 | ||
* @since 8/27/20 | ||
*/ | ||
@Configuration | ||
public class RestConfiguration { | ||
|
||
/** | ||
* Configure {@link RestTemplate} to support HAL JSON. | ||
* | ||
* @param restTemplateBuilder the builder. | ||
* @return configured {@link RestTemplate}. | ||
*/ | ||
@Bean | ||
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { | ||
final var objectMapper = new ObjectMapper(); | ||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); | ||
objectMapper.registerModule(new Jackson2HalModule()); | ||
|
||
final var messageConverter = new MappingJackson2HttpMessageConverter(); | ||
messageConverter.setSupportedMediaTypes(Collections.singletonList(MediaTypes.HAL_JSON)); | ||
messageConverter.setObjectMapper(objectMapper); | ||
|
||
return restTemplateBuilder.messageConverters(messageConverter).build(); | ||
} | ||
} |
Oops, something went wrong.