Spring Reactive MongoDB ile Reactive Uygulama Geliştirme
Spring Reactive Mongo ile birlikte MongoDB’yi reactive uygulamalarımızı geliştirirken kullanabiliyoruz. NoSQL yapılar, R2DBC yapılara göre reactive programlamanın production ortamlarında kullanımına çok daha uygun gözüküyor.
Spring Data Mongo Reactive bize reactive bir uygulama geliştirebilmemiz için reactive mongoDB connector’ü sağlıyor. Böylece yapacağımız işlemler asenkron ve non-blocking bir şekilde MongoDB üzerinde gerçekleşebiliyor.
Ön Hazırlık
Reactive MongoDB’nin yanı sıra daha önce değindiğim ve bu yazıda kullanacağımız yapıları, yazıyı daha iyi anlamak için; teoriden başlayarak, reactive endpointler — Mono ve Flux, son olarak da reactive web client(test için) yazılarını ve ilginizi çeker ise Reactive Reloational Database konusunu okumanızı öneririm.
Bu yazıda Spring Data Mongo Reactive ile birlikte uçtan uca bir user servisi geliştireceğiz. Spring WebFlux üzerinde Functional End-pointler kullanarak Controller
katmanımızı hazırlayacak, servis katmanımızda ise hem ReactiveMongoTemplate
kullanarak kendi custom sorgularımızı hem de ReactiveMongoRepository
kullanarak hazır metotları uygulamış olacağız. Tüm kodlara Github repository üzerinden ulaşabilirsiniz.
Projenin Bağımlılıkları ve Ortam Hazırlama
Her zaman dile getirdiğimiz gibi bir reactive uygulama geliştiriyorsanız bunun bütün parçaları reactive olmalıdır.
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
MongoDB’yi hazırlamak için bir docker-compose.yaml
oluşturabiliriz. Böylece kullanabileceğimiz bir MongoDB’yi ayağa kaldırabiliriz.
version: '3.7'
services:
mongodb_container:
image: mongo:latest
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: mongopw
ports:
- 27017:27017
volumes:
- mongodb_data_container:/data/db
volumes:
mongodb_data_container:
Projemizin MongoDB ile birlikte çalışabilmesi için docker-compose up
komutunu koşmamız mongoDB’mimizin ayağa kalkması için yeterli olacaktır.
MongoDB ile Reactive Uygulama Geliştirme
İlk olarak Reactive MongoDB’mizin, ayağa kaldırdığımız veritabanına ulaşmasını sağlayacak ayarları yazmalıyız. AbstractReactiveMongoConfiguration
sınıfından extend ettiğimiz MongoConfiguration
sınıfı ile birlikte Reactive bir veritabanı bağlantısı kurabiliriz. Burada @EnableMongoRepositories
diyerek Spring’e biz MongoDB ile işlemler yapacağız diyoruz. Ayarlarda @Override
ettiğimiz metotlardan biri veritabanı bilgisini diğeri ise kullanacağımız MongoClient
’ı veriyor. MongoClient oluşturmak için statik factory metotlarından yararlanarak .create(connectionString)
için gerekli usename:password
bilgisi ile ip:port
bilgilerini girmiş oluyoruz.
Veritabanına bağlantımızı kuracak yapımızı hazırlamış olduk. Şimdi veritabanımızda oluşacak nesnemizi oluşturmaya geldi. MongoDB’de oluşturduğumuz veriler Document
adı verilen yapılarda tutulmaktadır. Şimdi daha önce R2DBC yazımdaki örneğin aynısı üzerinden gidebiliriz.
@Document
public class User {
@Id
private String id;
@NotBlank
private String name;
private Integer score;
//Getter, Setter, hashCode etc..
Artık veritabanımızla bağlantılı olacak document
’i oluşturmuş olduk. Şimdi bu document
üzerinden işlem yapabilmek için gerekli olan Repository’imizi oluşturabiliriz.UserRepository
’imizi ReactiveMongoRepository
extend ederek oluşturabilir ve böylece sağladığı (findAll
, findById
, save
and delete
gibi) CRUD metotları kullanabiliriz.
Neredeyse hazırız ilk olarak bütün işlemleri yönetebileceğimiz bir servis oluşturalım. Bu servisimize UserRepository
’i inject edebiliriz. Hatta örneklerini gösterebilmek için ReactiveMongoTemplate
‘ide servisimizde kullanılabilir hale getirelim. Ama ilk önce UserRepository
’i nasıl kullandığımıza bakalım. Tüm CRUD operasyonları gerçekleştirebiliyoruz ve her biri Mono
ya da Flux
olacak şekilde User
objesi(ler)ini içeriyor.
Bütün sorgu alt yapısını kendimiz yönetmek istiyorsak, o zaman ReactiveMongoTemplate
devreye giriyor. Hali hazırda servisimizde kullanabilir hale getirdiğimiz ReactiveMongoTemplate
tüm operasyonları kendimizin yönetebileceği bir altyapı sunuyor.
@Override
public Mono<Long> deleteByName(String name) {
return template.remove(query(where("name").is(name)), User.class).map(DeleteResult::getDeletedCount);
}
Örnekte görülebileceği üzere reactiveTemplate
ile birlikte remove
metodunu kullandık. Böylece gelen parametrenin değerine eşit olan isimleri (name
alanı) silen ve sildiklerinin sayısını dönen bir metot yazmış olduk. Bu şekilde istediğimiz sorguları betimleyebiliyoruz.
Şimdi tüm servis metotlarımız için, isteklerimizi karşılayabilecek Functional-endpointlerimizi hazırlayalım. İlk olarak UserHandler
componentimizi hazırlamak için routing hariç tüm request ve response objelerimizi içerecek şekilde geliştirebiliriz.
Kodlardan daha iyi görüleceği üzere bütün yapımız hazır. Şimdi routing işlemlerini RouterFunction
’lar ile birlikte endpointler haline getirebiliriz.
Arık isteklerimizi yönlendirebileceğimiz bir yapı elde etmiş olduk ve uçtan uca MongoDB’yi kullanan reactive bir uygulamamız var.
Hızlı bir unit test yapısı hazırlamak istersek WebTestClient
’ı kullanabilir ve veritabanı yapılarımızı mocklayabiliriz.
Tüm süreçleri tamamladığımıza göre servisimizi ayağa kaldırıp istekler atabilir ve sonuçlarına göz atabiliriz.
POST http://localhost:8083/api/v1/users
Content-Type: application/json
{
"name": "Zühtü",
"score": 52
}
Bir user oluşturma isteği attığımızda aldığımız yanıt 201 Created ve nesnenin id ile birlikte dönen bilgileri olacaktır.
{
"id": "61ed90c1d656605b62e19acd",
"name": "Zühtü",
"score": 52
}
Son olarak;
Reactive programlama ile daha az sayıda thread kullanarak non-blocking ve asenkron işlemleri çok daha az donanım kaynağıyla gerçekleştirebiliyor. Biz bunun yanına MongoDB gibi güçlü bir NoSQL veritabanı koyduk ve bunu da reactive connector ile destekleyip uçtan uca reactive bir uygulama elde ettik. R2DBC veritabanı yapılarının aksine bence MongoDB ile gerçekleştirilen uygulamalar production ortamına daha hazır gözüküyor.
Tüm kodlara Github repository üzerinden ulaşabilirsiniz.
— Bana ulaşmak için: Twitter, Linkedin
— 1:1 görüşmeler için: Superpeer
— Kodlar konuşsun: Github