REST API handled by Spring Boot
The main SpringBoot application is OffersApplication with a controller defined in OfferController
To run the application, from command line simply use mvn spring-boot:run
ℹ️ Running mvn package will run integration tests, as well as creating an executable JAR.
Once the JAR has been packaged, running java -jar target/offer-service-0.0.1-SNAPSHOT.jar from the command line will also run the application.
The following endpoints are defined for this service:
| Method | Endpoint | Description | Example |
|---|---|---|---|
| GET | /offers/{code} | Gets the offer matching the input code | /offers/ABC123 returns an offer matching code ABC123, or throws a 404 NOT FOUND exception if there is nothing matching |
| PUT | /offers/{code}/cancel | Cancels an existing offer matching the input code | /offers/ABC123/cancel deactivates the offer matching code ABC123 |
| POST | /offers/ | Creates a new Offer from the request body | /offers/ with valid JSON in the request body will create a new offer |
Several design decisions were made while creating this application:
- The
Offerclass is very simple - an offer code, a brief description, and an expiration date/time.- I've added an active flag to the Offer class, figuring that for auditing purposes it would probably not be a good idea to actually delete offers, rather just to mark them as inactive.
- Cancelling an Offer uses
PUTrather thanDELETEfor this reason - the entity is being updated, rather than completely deleted. - The date handling is fairly basic, mostly for reasons of simplicity.
- Handling of JSON requests and responses is also left as the basic out-of-the-box functionality for reasons of simplicity.
- Spring Boot was used as a quick and easy way to get a running application.
- Also to make things run quickly and easily, the Offers are held in memory. This would be a very bad idea in a real system, where a database would be the most obvious approach.
- It would probably have been worth creating a data layer for the
OfferHandlerto call out to to further separate out the code, however for this small example it didn't seem entirely worthwhile (and I ran out of time 😉).
- It would probably have been worth creating a data layer for the
- No validation is done for the input parameters so any code/description are accepted - this is probably unwise in a real application.
- I've used separate exceptions for each possible error scenario - trying to get or update an offer that is not found, one that is
expired, or one that has been cancelled. In a real world system it would probably be worth handling these errors differently, however to
make things quicker here they all return an empty response body.
- I would probably keep most of the responses the same. For security reasons doing a GET on an expired offer, a cancelled offer, or a non-existent one, should all give the same response... otherwise you're potentially giving away information about offers that exist.
- I nearly wrote a custom error handler using Spring
@ExceptionHandler, which can be used to create a custom response body with error messages taken from the different types of exception thrown, however to keep it simple (and for the security reasons mentioned above) I figured it wasn't really necessary for this example.