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 ReactiveMongoTemplatedevreye 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

https://gokhana.dev

— Kodlar konuşsun: Github

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Gökhan Ayrancıoğlu

Gökhan Ayrancıoğlu

Software Engineer @Yemeksepeti • #Java • #Spring Boot • #Kotlin • #Spark • #Microservices • https://gokhana.dev