Your final product should be a backend application for movies and actors management via REST API, described in details in the following sections. Keep in mind that application can be used by multiple clients at the same time and all data needs to be persisted somewhere (H2 database will be ok). UI is not part of this demo project.
- implement HTTP cache mechanisms where is needed
- implement request counter for all REST calls
- protect services with modern authorization mechanisms
- implement movies and actor services as at least two independent deployable services
- support the ability to handle a large number of HTTP GET requests.
- provide (or describe) mechanism how database objects can be initialized
- dockerize services
- provide docker compose file
Movies have properties as title, year, description, list of actors, some pictures, etc. (as identifier use imdbID).
Implement REST operations to support basic UI requirements:
- list all movies
- list movies with pagination support
- search of movie
- CRUD operations
Actors have properties as first name, last name, born date, list of movies, etc.
Implement REST operations to support basic UI requirements:
- list all actors
- list actors with pagination support
- CRUD operations
To run the demo (on Linux), run the build_and_run.sh
script from the project's root folder
./build_and_run.sh
If you can't run the script, give it execute permissions first (and then rerun it):
chmod +x build_and_run.sh
The Actor and the Movies service can be run manually from the project's root by running:
(cd actors && ./gradlew bootRun)
(cd movies && ./gradlew bootRun)
Login credentials:
- Username:
actors
- Password:
actors
HTTP request:
- GET: http://localhost:8081/api/v1/actors - returns a list of all actors in the DB
- supports pagination with
page
andsize
URL params - example: http://localhost:8081/api/v1/actors?size=2&page=1
- supports pagination with
- GET: http://localhost:8081/api/v1/actors/{id} - returns an actor with the given
{id}
if it exists - POST: http://localhost:8081/api/v1/actors - creates a new actor (from the request's body) and returns it if it was
successfully added to the DB (ID doesn't already exist). Example of the request's body:
{ "id": 1, "firstName": "Tom", "lastName": "Hanks", "bornDate": "1956-07-09", "moviesIds": [1] }
- PUT: http://localhost:8081/api/v1/actors/{id} - updates an existing actor (from the request's body, same as in the
POST request) and returns it if it was successfully updated to the DB (valid actor
{id}
was provided) - DELETE: http://localhost:8081/api/v1/actors/{id} - deletes an existing actor with the given
{id}
Login credentials:
- Username:
movies
- Password:
movies
HTTP request:
- GET: http://localhost:8080/api/v1/movies - returns a list of all movies in the DB
- supports pagination with
page
andsize
URL params - example: http://localhost:8080/api/v1/movies?size=2&page=1
- supports pagination with
- GET: http://localhost:8080/api/v1/movies/{id} - returns a movie with the given
{id}
if it exists - GET:
http://localhost:8080/api/v1/movies/find?id={id}&title={title}&yearReleased={yearReleased}&description={description} -
returns a list of all movies (exactly) matching any (number) of the supplied URL params
- Example: find all (3) movies released in 1994: http://localhost:8080/api/v1/movies/find?yearReleased=1994
- POST: http://localhost:8080/api/v1/movies - creates a new movie (from the request's body) and returns it if it was
successfully added to the DB (ID doesn't already exist). Example of the request's body:
{ "id": 1, "title": "The Shawshank Redemption", "yearReleased": 1994, "description": "A former banker convicted of murder befriends a fellow prisoner as he tries to prove his innocence.", "actorsIds": [1, 2, 3] }
- PUT: http://localhost:8080/api/v1/movies/{id} - updates an existing movie (from the request's body, same as in the
POST request) and returns it if it was successfully updated to the DB (valid movie
{id}
was provided) - DELETE: http://localhost:8080/api/v1/movies/{id} - deletes an existing movie with the given
{id}
A lot of various metrics are available on the actuator URL:
- Movies: http://localhost:8080/actuator
- Actors: http://localhost:8081/actuator
Some metrics, such as server requests counts, are available on /actuator/metrics/http.server.requests
URLs.
Note that some URLs might not be available if a request for that URL hasn't been made yet.
List of all received HTTP server requests: http://localhost:8080/actuator/metrics/http.server.requests
More URLs:
- GET all movies: http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:/api/v1/movies
- GET movie by ID: http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:/api/v1/movies/%7Bid%7D
List of all received HTTP server requests: http://localhost:8081/actuator/metrics/http.server.requests
More URLs:
- GET all actors: http://localhost:8081/actuator/metrics/http.server.requests?tag=uri:/api/v1/actors
- GET actor by ID: http://localhost:8081/actuator/metrics/http.server.requests?tag=uri:/api/v1/actors/%7Bid%7D
Server side caches can be checked via the /actuator/caches
URL.
Tests can be run by running the following commands from the project's root:
(cd actors && ./gradlew test)
(cd movies && ./gradlew test)
Or for more info:
(cd actors && ./gradlew test -i | grep -E -v "^Executing |^Creating |^Parsing |^Using |^Merging |^Download |^title=Compiling|^AAPT|^future=|^task=|:app:|V/InstrumentationResultParser:")
(cd movies && ./gradlew test -i | grep -E -v "^Executing |^Creating |^Parsing |^Using |^Merging |^Download |^title=Compiling|^AAPT|^future=|^task=|:app:|V/InstrumentationResultParser:")
- Use more secure login credentials for the DB and the app (quick/test ones were used).
- Actuator endpoints could be narrowed down to just the
/actuator/metrics
URL to prevent excess data exposure (as a security measure). - Lombok's
@Data
annotation could be replaced with Java's record class. - Add more logs to see what's going on in the apps.
- Move common logic to a common lib and introduce some abstraction layers!
- CSRF shouldn't be disabled in a production environment (it's disabled for easier testing).
- If needed, cache headers could be added to HTTP request responses as well.
- Different profiles could be used for testing, dev and prod environments.
- Better code documentation.
- Stricter DB schema (defined in the code) by using
@Column(nullable = false)
and similar annotations. - Better tests, covering various failures like invalid input data and covering the data layer as well.