To build and run the application from gradle:
gradle clean bootRun
To run integration tests from gradle:
gradle clean test
- API supports HAL format and includes HAL explorer for easy navigation through the endpoints: http://localhost:8080
- Health check is available via Actuator at http://localhost:8080/actuator/health
- Application includes embedded H2 database as a data store
- H2 console is available at http://localhost:8080/h2-console/
- H2 JDBC URL is
jdbc:h2:mem:testdb
, by default H2 stores data in memory, it can be configured to persist data by using file-based storege via this setting inapplication.properties
:
spring.datasource.url=jdbc:h2:file:/data/demo
- Swagger UI is available at http://localhost:8080/swagger-ui.html#/
- Test cURL requests to play with:
curl -i localhost:8080
curl -i -X POST -H "Content-Type:application/json" -d '{"name": "Test Product 1", "price": 1.1}' http://localhost:8080/products
curl -i -X POST -H "Content-Type:application/json" -d '{"name": "Test Product 2", "price": 1.1}' http://localhost:8080/products
curl -i -X POST -H "Content-Type:application/json" -d '{"name": "Test Product 3", "price": 1.3}' http://localhost:8080/products
curl -i -X POST -H "Content-Type:application/json" -d '{"name": "Test Product 4", "price": 1.4}' http://localhost:8080/products
curl -i -X DELETE http://localhost:8080/products/4
curl -i -X PUT -H "Content-Type:application/json" -d '{"name": "Test", "price": 1.2}' http://localhost:8080/products/2
curl -i -X PATCH -H "Content-Type:application/json" -d '{"name": "Test Product 2"}' http://localhost:8080/products/2
curl -i localhost:8080/products
curl -i -X POST -H "Content-Type: application/json" -d '{"email": "test1@email", "products": ["http://localhost:8080/products/1"]}' http://localhost:8080/orders
curl -i -X POST -H "Content-Type: application/json" -d '{"email": "test2@email", "products": ["http://localhost:8080/products/1", "http://localhost:8080/products/2"]}' http://localhost:8080/orders
curl -i -X POST -H "Content-Type: application/json" -d '{"email": "test3@email", "products": ["http://localhost:8080/products/1", "http://localhost:8080/products/2", "http://localhost:8080/products/3"]}' http://localhost:8080/orders
curl -i -X POST -H "Content-Type: application/json" -d '{"email": "test4@email"}' http://localhost:8080/orders
curl -i -X POST -H "Content-Type: text/uri-list" -d $'http://localhost:8080/products/1\nhttp://localhost:8080/products/2\nhttp://localhost:8080/products/3' http://localhost:8080/orders/8/products
curl -i localhost:8080/orders
curl -i localhost:8080/orders/search/findByCreatedBetween?from=2020-03-23&to=2020-03-25
- In order to make it within the given time constraints of 2 hours I decided to implement solution by reusing functionality provided by Spring framework with as little custom code written as possible. Swagger API is entirely auto-generated by Spring Boot, this could easily be changed by supplying own documentation in overriden repository methods.
- Unfortunately
@RepositoryRestResource
does not support input validation out of the box and I stuck to that since I decided to go that route. An easy work around it would be adding@RestController
with custom API - Tests only include integration tests as there's no/very little custom code implementing business logic (mocking requires
@Autowired
services) - Generated documentation concerning adding an
Order
with relatedProducts
is misleading as the list of products needs to include the list of URI identifiers rather then JSON representation ofProduct
, like so:
curl -i -X POST -H "Content-Type: application/json" -d '{"email": "test@email", "products": ["http://localhost:8080/products/1"]}' http://localhost:8080/orders
- I had an idea to take top-down asynchronous approach with WebFlux and R2DBC API, but R2DBC does not have support for relations, therefore I gave up on this as it would require writing more custom code.