This project repository implements a Vehicles API using Java and Spring Boot that communicates with separate location and pricing services. The project is designed to provide REST API capabilities that explore the main HTTP verbs and features. It also includes Eureka server, Redis Cache in Memory, MySQL relational database, Docker container, custom API error handling using ControllerAdvice, springdoc-openapi documentation, HTTP WebClient, MVC Test, and Automatic model mapping.
- REST API exploring the main HTTP verbs and features
- Eureka Server.
- Redis Cache in Memory
- MySql relational Database
- Docker container.
- Custom API Error handling using ControllerAdvice
- springdoc-openapi documentation
- HTTP WebClient
- MVC Test
- Automatic model mapping
To run the project, you can choose to run it either as java applications or as docker containers. Note that all three applications should be running simultaneously for full operation.
Check each component to see its details and instructions. Below are the steps to run the project:
To run the project as a java application or jar files, you must have Mysql server local instance and Redis installed on your device.
- Go to the root directory of each component and uncomment the necessary configurations, such as the database URL and Eureka client service URL.
- Comment out the unnecessary configurations.
- Run each component as a java application or jar file.
To run the project as docker containers, you should have Docker installed on your device.
- Navigate to the root directory of the project.
- Run the docker compose file using the command:
docker-compose -f dockercompose.yaml up
.
The project requires the use of Maven and Spring Boot, along with Java v11.
This component launches the Vehicles API as a Spring Boot application. Additionally, it initializes a few car manufacturers to place in the database, as well as creating the web clients to connect to the Maps and Pricing services.
This component handles the format of a GET request to the pricing-service WebClient to get pricing data.
This component handles the format of a GET request to the map-service WebClient to get location data.
This component declares a few quick methods to return errors and other messages from the Vehicles API.
This component is the actual REST controller for the application. It implements what happens when GET, POST, PUT, and DELETE requests are received (using methods in the CarService).
This component helps to handle any invalid arguments fed to the API.
This component declares a class for use with the MapsClient also to use it with Redis in-memory cache.
This component declares a class for use with the PriceClient also to use it with Redis in-memory cache.
This component handles the format of a GET request to the map-service WebClient to get location data. Each time there is a call to map-service, it first checks if the address already stored in memory. If it does not exist, it makes a REST call to map-service.
This component handles the format of a GET request to the pricing-service WebClient to get pricing data. Each time there is a call to price-service, it first checks if the price already stored in memory. If it does not exist, it makes a REST call to the pricing-service.
This component enumerates the available values for the condition of a car (New or Used).
This component declares information about the location of a vehicle. This is not the exact same as the Address class used by the map-service - its primary use is related to the storage of latitude and longitude values. Because the data, such as address, gathered from map-service is annotated as @Transient, this data is not stored until the next time map-service is called.
This component declares additional vehicle details, primarily about the car build itself, such as fuel type and mileage.
This component declares the Manufacturer class, primarily made of an ID code and the name of the manufacturer.
This component declares certain information about a given vehicle, mostly that more about the car entry itself (such as CreatedAt). Note that a separate class, Details, also stores additional details about the car that is more specific to things like make, color, and model. Note that similar to Location with data like address, this uses a @Transient tag with price, meaning the Pricing Service must be called each time a price is desired.
This component provides a type of data persistence while the web service runs.
This component provides a type of data persistence while the web service runs, primarily to store manufacturer information like that initialized in VehiclesApiApplication.
This component provides CRUD operation to store address in memory.
This component provides CRUD operation to store pricein memory.
This component is a service registry for the microservices that are part of the application. It helps to manage the registration, discovery, and monitoring of microservices.
This in-memory cache is used by the application to store frequently accessed data, reducing the number of calls made to external services. The data stored is address and price data, which is retrieved from the map-service and pricing-service, respectively.
This component is a relational database used to store data, such as manufacturer and car information.
This component is used to make HTTP requests to external services, such as the map-service and pricing-service. It is used to retrieve data necessary for the Vehicles API component.
This component is used to test the REST API endpoints and functionality of the application.
This component is used to map the data between the domain model and the DTO (Data Transfer Object) model. It uses the ModelMapper library to automatically map the data between the two models, reducing the amount of boilerplate code needed.
Swagger UI: http://localhost:8761/swagger-ui/index.html
POST
/cars
{
"condition":"USED",
"details":{
"body":"sedan",
"model":"Impala",
"manufacturer":{
"code":101,
"name":"Chevrolet"
},
"numberOfDoors":4,
"fuelType":"Gasoline",
"engine":"3.6L V6",
"mileage":32280,
"modelYear":2018,
"productionYear":2018,
"externalColor":"white"
},
"location":{
"lat":40.73061,
"lon":-73.935242
}
}
GET
/cars/{id}
This feature retrieves the Vehicle data from the database and access the Pricing Service and Boogle Maps to enrich the Vehicle information to be presented
PUT
/cars/{id}
{
"condition":"USED",
"details":{
"body":"sedan",
"model":"Impala",
"manufacturer":{
"code":101,
"name":"Chevrolet"
},
"numberOfDoors":4,
"fuelType":"Gasoline",
"engine":"3.6L V6",
"mileage":32280,
"modelYear":2018,
"productionYear":2018,
"externalColor":"white"
},
"location":{
"lat":40.73061,
"lon":-73.935242
}
}
DELETE
/cars/{id}