Implementar un micro-servicio API REST, utilizando JAVA con VertX y RX (ReactiveX) frameworks. Quiero aplicar las mejores practicas y ultimas tecnologias para la construccion de micro-servicios.
En cuanto a diseño y arquitectura, utilizamos SOLID, KISS y Domain Driven Design (DDD), desarrollando niveles de abstracción por capas de afuera hacia adentro.
Desarrollo esta pensado, en que el dĂa de manana tenemos que modificar la capa de web/framework Vertx lo podemos cambiar, y el CORE
queda intacto, al igual si queremos implementar otra base de datos, por ejemplo una relacional, podrĂamos hacerlo sin afectar el CORE
El centro vendria ser el core del sistema, es por lo que el servicio existe va a ser lo más importante y lo que tendrĂamos que tener más foco.
Capa (Layer) | package |
---|---|
Entities | core.domain |
Use Cases | core.action |
Interface, Adapters | core.domain |
Repositories | core.infrastructure |
Domain Service | core.infrastructure.services.converter |
API http | delivery.http |
- En la entidad de TRACK, se tomo en cuenta el campo en duracion siempre en segundos, lo que si queremos una duracion formateada no tenemos que guardar el campo dos veces en la base de datos, con crear una funciona format tenemos.
- Se Genero un error de tracks y album devolverá algunos campos en null, se creó un ticket intencionalmente para cerrar el ciclo de desarrollo y manejo de tickets en git.
- En caso de alto trafico y concurrencias, se recomienda crear subdominios y gneerar un servicio CQRS para manejar comandos y eventos, Vertx tiene un event bus con el que podemos comunicarnos por eventos entre los subdominios.
- En cuanto a infra, se puede pensar ya que tenemos esto separado por subdominios independientes, podriamos crear un servicio por cada subdominio y escalarlo segun su trafico.
Name | Version |
---|---|
JRE/Java | 8u261 |
Gradle | 6.3.0 |
Vertx | 3.8.3 |
RxKotlin | 2.2.20 |
Desde un terminal busca la carpeta raiz del proyecto y ejecuta lo siguiente:
docker build --rm -t acetato .
Para ejecutarlo:
docker run -p 8080:8080 -e REPOSITORY=MONGO -e MONGO_URI=mongodb+srv://acetato_user:kxrxdZctDlLz23CJ@cluster-serviberza.zburx.mongodb.net/acetato?retryWrites=true&w=majority -t acetato acetato
Nota: Las credenciales expuestas en la variable de entorno MONGO_URI
son solo para fines de esta prueba, luego seran removidas, por seguridad.
Desde un terminal busca la carpeta raiz del proyecto y ejecuta lo siguiente:
./gradlew run
Para correr test, como lo mencionamos anteriormente, desde la terminal en la raĂz del proyecto ejecuta lo siguiente:
./gradlew test
Si queremos buildear el proyecto podremos ejecutar lo siguiente:
./gradlew jar
Para ejecutar el proyecto recien buildeado, ejecutamos lo siguiente:
export REPOSITORY="MONGO"
export MONGO_URI="mongodb+srv://acetato_user:kxrxdZctDlLz23CJ@cluster-serviberza.zburx.mongodb.net/acetato?retryWrites=true&w=majority"
java -jar build/libs/acetato-1.0.0.jar
Nota: Las credenciales expuestas en la variable de entorno MONGO_URI
son solo para fines de esta prueba, luego seran removidas, por seguridad.
Metodo | Endpoint | Descripcion |
---|---|---|
GET | /artists | Lista todos los artistas |
GET | /artist/:artistId | Obtiene uno por id |
POST | /artist | Agrega un artistas |
DELETE | /artist/:artistId | Elimina uno por id |
PUT | /artist | Actualiza un artista |
curl -X GET 'http://localhost:8080/artists'
[
{
"artist_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
},
{
"artist_id": "5f95c5b96836a96cdf1721db",
"name": "Elvis"
},
{
"artist_id": "5f96296d2f590315aeeccbd8",
"name": "Shakira, Jr."
}
]
curl -X GET 'http://localhost:8080/artist/:artistId'
{
"artist_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
}
Status code : 404
{
"error": "Artist Not Found"
}
curl -X POST 'http://localhost:8080/artists' \
--header 'Content-Type: application/json' \
-d '{
"name": "Metallica"
}'
Status code : 201
Sin cuerpo
curl -X DELETE 'http://localhost:8080/artist/:artistId'
Status code : 204
Sin cuerpo.
curl -X PUT 'http://localhost:8080/artist' \
--header 'Content-Type: application/json' \
-d '{
"_id": "5f96296d2f590315aeeccbd8",
"name": "Shakira, Jr."
}'
Parametro obligatorio: _id
Status code : 201
Sin cuerpo.
Status Code: 400
{
"error": "Parameter: _id is required."
}
Metodo | Endpoint | Descripcion |
---|---|---|
GET | /albums | Lista todos los albums |
GET | /album/:albumId | Obtiene uno por id |
POST | /album | Agrega un album |
DELETE | /album/:albumId | Elimina uno por id |
PUT | /album | Actualiza un album |
curl -X GET 'http://localhost:8080/albums'
[
{
"album_id": "5f9a331472ab0a5e3519465c",
"title": "No es verdad",
"release_date": 1603759420,
"artists": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
},
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Brame Jack Jr."
}
],
"tracks": [
{
"_id": "",
"title": "You are Beautiful",
"album": null,
"artists": null,
"duration": null,
"disc_number": null,
"track_number": null
}
],
"type": "ALBUM"
}
]
curl -X GET 'http://localhost:8080/album/:albumId'
{
"album_id": "5f9a331472ab0a5e3519465c",
"title": "No es verdad",
"release_date": 1603759420,
"artists": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
},
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Brame Jack Jr."
}
],
"tracks": [
{
"_id": "",
"title": "You are Beautiful",
"album": null,
"artists": null,
"duration": null,
"disc_number": null,
"track_number": null
}
],
"type": "ALBUM"
}
Status code : 404
{
"error": "Album Not Found"
}
curl -X POST 'http://localhost:8080/albums' \
--header 'Content-Type: application/json' \
-d '{
"title": "No es verdad",
"release_date": 1603759420,
"artists": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
}
],
"tracks": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"title": "You are Beautiful"
}
],
"type": "ALBUM"
}'
Status code : 201
Sin cuerpo
curl -X DELETE 'http://localhost:8080/album/:albumId'
Status code : 204
Sin cuerpo.
curl -X PUT 'http://localhost:8080/album' \
--header 'Content-Type: application/json' \
-d '{
"_id": "5f9a331472ab0a5e3519465c",
"title": "No es verdad",
"release_date": 1603759420,
"artists": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
}
],
"tracks": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"title": "You are Beautiful"
}
],
"type": "ALBUM"
}'
Parametro obligatorio: _id
Status code : 201
Sin cuerpo.
Status Code: 400
{
"error": "Parameter: _id is required."
}
Metodo | Endpoint | Descripcion |
---|---|---|
GET | /tracks | Lista todos los tracks |
GET | /track/:trackId | Obtiene uno por id |
POST | /track | Agrega un track |
DELETE | /track/:trackId | Elimina uno por id |
PUT | /track | Actualiza un track |
curl -X GET 'http://localhost:8080/tracks'
[
{
"_id": "5f9a3d189ac58a6d51d57087",
"title": "Track Nro. 11",
"album": {
"_id": "5f9a331472ab0a5e3519465c",
"title": "No es verdad",
"release_date": null,
"artists": null,
"tracks": null,
"type": "ALBUM"
},
"artists": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
},
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Brame Jack Jr."
}
],
"duration": 120,
"disc_number": 1,
"track_number": 11
}
]
curl -X GET 'http://localhost:8080/track/:trackId'
{
"_id": "5f9a3d189ac58a6d51d57087",
"title": "Track Nro. 11",
"album": {
"_id": "5f9a331472ab0a5e3519465c",
"title": "No es verdad",
"release_date": null,
"artists": null,
"tracks": null,
"type": "ALBUM"
},
"artists": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
},
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Brame Jack Jr."
}
],
"duration": 120,
"disc_number": 1,
"track_number": 11
}
Status code : 404
{
"error": "Track Not Found"
}
curl -X POST 'http://localhost:8080/tracks' \
--header 'Content-Type: application/json' \
-d '{
"title": "Track Nro. 1",
"album": {
"_id": "5f9a331472ab0a5e3519465c",
"title": "No es verdad",
"type": "ALBUM"
},
"artists": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
},
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Brame Jack Jr."
}
],
"duration": 120,
"disc_number": 1,
"track_number": 11
}'
Status code : 201
Sin cuerpo
curl -X DELETE 'http://localhost:8080/track/:trackId'
Status code : 204
Sin cuerpo.
curl -X PUT 'http://localhost:8080/track' \
--header 'Content-Type: application/json' \
-d '{
"_id": "5f9a331472ab0a5e3519465c",
"title": "Track Nro. 1",
"album": {
"_id": "5f9a331472ab0a5e3519465c",
"title": "No es verdad",
"type": "ALBUM"
},
"artists": [
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Jaime Jack Jr."
},
{
"_id": "5f95c35b5f72bf2dceb4916e",
"name": "Brame Jack Jr."
}
],
"duration": 120,
"disc_number": 1,
"track_number": 11
}'
Parametro obligatorio: _id
Status code : 201
Sin cuerpo.
Status Code: 400
{
"error": "Parameter: _id is required."
}