O programowaniu reaktywnym już trochę miałem okazje napisać na blogu. W tym miejscu chciałbym skorzystać z możliwości jakie niesie ze sobą Quarkus Reactive Mongo.
Jeśli jesteś ciekawy, jak szybko zintegrować Quarkus z reaktywnym driverem Mongo, to ten artykuł będzie właśnie dla Ciebie.
W dalszej części będziemy rozbudowywać aplikację przygotowaną w artykule Quarkus OpenID Connect z Auth0.
Ponieważ w tej chwili cały świat walczy z pandemią SARS-COV-2 wzbogacimy ją o dodatkową usługę, który będzie zwracała dane statystyczne ze zbioru przygotowanego przez JHU CSSE.
Aktualny kod jest dostępny tutaj:
https://github.com/bchmielewski/quarkus-reactive-mongo
MongoDB
Na początek instalujemy MongoDB ze strony https://www.mongodb.com/download-center/community.
Jeżeli zdecydowałeś się na instalację pakietów zip wówczas warto przygotować pusty katalog dla bazy danych, np. c:\data\db.
Uruchomienie MongoDB jest proste. Wystarczy z katalogu podkatalogu bin wywołać polecenie:
mongod.exe -dbpath="C:\data\db"
Jako zbiór danych możemy wykorzystać udostępniany publicznie do celów edukacyjnych zestaw 2019 Novel Coronavirus COVID-19 (2019-nCoV) Data Repository by Johns Hopkins CSSE.
Do MongoDB najprościej zaimportować go przy użyciu klienta MongoDB Compass dostępnego na stronie https://www.mongodb.com/download-center/compass.
Instalacja rozszerzeń
Do pracy z reaktywnym driverem do mongo potrzebować będziemy kilku rozszerzeń. Będzie to przede wszystkim sam klient MongoDB, biblioteka do obsługi JSON, mutiny do typów reaktywnych oraz wsparcie dla zarządzania zmianami kontekstu wątków.
Zatem do dzieła:
./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-mongodb-client"
./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-jsonb"
./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-resteasy-mutiny"
./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-smallrye-context-propagation"
Dostęp do danych
Na początek zdefiniujemy sobie klasę reprezentującą fragment danych w naszej bazie:
public class CovidEntry {
private String countryRegion;
private String confirmed;
public CovidEntry(String countryRegion, String confirmed) {
this.countryRegion = countryRegion;
this.confirmed = confirmed;
}
public String getCountryRegion() {
return countryRegion;
}
public void setCountryRegion(String countryRegion) {
this.countryRegion = countryRegion;
}
public String getConfirmed() {
return confirmed;
}
public void setConfirmed(String confirmed) {
this.confirmed = confirmed;
}
}
W następnym kroku napiszemy serwis, który pobierze dane z MongoDB. Skorzystamy w tym przypadku z reaktywnego klienta:
@ApplicationScoped
public class CovidStatisticsService {
@Inject
private ReactiveMongoClient mongoClient;
public Uni<List<CovidEntry>> covid19Stats() {
Uni<List<CovidEntry>> stats = mongoClient
.getDatabase("quarkus-demo")
.getCollection("covid-19")
.find()
.map(document -> new CovidEntry(
document.getString("Country_Region"),
document.getString("Confirmed")
))
.collectItems()
.asList();
return stats;
}
}
W przeciwieństwie do rozwiązania dla Mongo w Spring Data tutaj wyraźnie widać, że jesteśmy w stanie w łatwy sposób operować wyborem bazy danych do danego zapytania. W rezultacie dużo łatwiejsze jest np. tworzenie usług zorientowanych na obsługę multitenancy.
Bezsprzecznie jest to rozwiązanie bardzo elastyczne.
Dodamy również dodatkową ścieżkę w naszej aplikacji:
@Path("/covid-19")
public class Covid19StatisticsResource {
@Inject
private CovidStatisticsService covidStatisticsService;
@GET
@Produces(MediaType.APPLICATION_JSON)
public Uni<List<CovidEntry>> stats() {
return covidStatisticsService.covid19Stats();
}
}
Uruchomienie
Jak zawsze korzystamy z trybu developerskiego:
./mvnw quarkus:dev
Sprawdźmy nasz nowy URL http://localhost:8080/covid-19.
Z poprzedniego artykułu pamiętamy, że aplikacja korzysta z Auth0. Z tego wynika, że po uwierzytelnieniu i poprawnym powrocie do naszej aplikacji na ekranie powinien pojawić się zbiór danych:
[
...
{"confirmed":"1051","countryRegion":"Poland"},
{"confirmed":"2995","countryRegion":"Portugal"},
{"confirmed":"537","countryRegion":"Qatar"},
{"confirmed":"906","countryRegion":"Romania"},
{"confirmed":"658","countryRegion":"Russia"}
...
]
Podsumowanie
Hey, wygląda na to, że reaktywne programowanie w Quarkus z pewnością ma się świetnie. Szybka integracja, dobre rozwiązania. Choć faktycznie korzystanie z reaktywnych typów (np. Uni) wydawać się może trochę dziwne, jeśli ktoś przyzwyczajony jest do Mono i Flux ze Springa.
A co Ty o tym myślisz? Quarkus daje radę? A może masz jakieś pytania?
Daj znać w komentarzu lub napisz do mnie na e-mail bartek (at) bartlomiejchmielewski.pl
Będzie mi bardzo miło, jak zapiszesz się na newsletter poniżej 🙂