MenuBar

Kata Mutiara

"Keberhasilan merupakan tetesan dari jeri-payah perjuangan, luka, pengorbanan dan hal-hal yang mengejutkan. Kegagalan merupakan tetesan dari kemalasan, kebekuan, kelemahan, kehinaan dan kerendahan"

ANIMASI TULISAN BERJALAN

Wednesday, February 26, 2025

Mengapa API Harus Dienkripsi?

 Mengapa API Harus Dienkripsi?

1. Pendahuluan

API (Application Programming Interface) adalah jembatan komunikasi antara berbagai aplikasi dan layanan. Dalam era digital yang semakin terhubung, API digunakan untuk mentransfer data sensitif seperti informasi pengguna, transaksi keuangan, dan kredensial login. Oleh karena itu, keamanan API menjadi sangat penting, dan salah satu cara utama untuk melindungi API adalah dengan enkripsi.

2. Apa Itu Enkripsi API?

Enkripsi API adalah proses mengamankan data yang dikirim melalui API dengan mengubahnya menjadi format yang tidak dapat dibaca tanpa kunci enkripsi yang benar. Ini memastikan bahwa data tetap aman saat dalam perjalanan dari klien ke server atau antar layanan.

3. Mengapa API Harus Dienkripsi?

a. Mencegah Penyadapan Data (Man-in-the-Middle Attack)

Tanpa enkripsi, data yang dikirim melalui API bisa disadap oleh pihak yang tidak bertanggung jawab. Dengan enkripsi, hanya penerima yang memiliki kunci yang dapat membaca data tersebut.

b. Melindungi Data Sensitif

Banyak API menangani data pribadi, seperti nama, alamat, dan informasi pembayaran. Jika data ini tidak dienkripsi, maka berisiko dicuri oleh peretas.

c. Memenuhi Regulasi Keamanan

Banyak regulasi seperti GDPR, HIPAA, dan PCI-DSS mengharuskan perusahaan untuk mengenkripsi data yang dikirim melalui jaringan publik untuk melindungi privasi pengguna.

d. Mencegah Pemalsuan Permintaan (API Spoofing)

Tanpa enkripsi yang baik, seorang penyerang bisa memalsukan permintaan API untuk mengakses atau memodifikasi data secara ilegal.

e. Melindungi Integritas Data

Enkripsi juga memastikan bahwa data tidak diubah selama proses transmisi. Dengan mekanisme seperti digital signatures dan HMAC (Hash-based Message Authentication Code), integritas data tetap terjaga.

4. Cara Mengenkripsi API dengan Benar

a. Gunakan HTTPS (TLS/SSL)

  • SSL/TLS (Transport Layer Security) adalah standar utama untuk mengenkripsi komunikasi API.

  • Pastikan API hanya dapat diakses melalui HTTPS untuk mencegah serangan eavesdropping.

b. Implementasi Enkripsi Payload

  • Untuk keamanan tambahan, data yang dikirim bisa dienkripsi menggunakan AES (Advanced Encryption Standard) atau RSA sebelum dikirim melalui API.

c. Gunakan OAuth 2.0 dan JWT untuk Autentikasi

  • OAuth 2.0 memungkinkan akses API yang aman melalui token.

  • JSON Web Token (JWT) dapat dienkripsi untuk memastikan keamanan tambahan saat mengirimkan data autentikasi.

d. Hindari Menyimpan Data Sensitif dalam URL

  • Jangan pernah mengirim data sensitif seperti token atau password dalam URL, karena bisa terekam dalam log server dan browser.

e. Validasi dan Filter Input

  • Gunakan input sanitization untuk mencegah serangan SQL Injection atau Cross-Site Scripting (XSS).

5. Kesimpulan

Enkripsi API sangat penting untuk memastikan keamanan data selama transmisi. Dengan menerapkan HTTPS, enkripsi payload, OAuth 2.0, dan validasi input, API bisa lebih terlindungi dari ancaman keamanan seperti penyadapan, peretasan, dan manipulasi data. Dalam dunia yang semakin digital, melindungi API dengan enkripsi bukanlah pilihan, tetapi keharusan!

Cloudflare Waiting Room: Solusi Anti-Crash Saat Trafik Membludak! 🚀

 Cara Kerja Cloudflare Waiting Room

Cloudflare Waiting Room adalah fitur yang digunakan untuk mengelola lonjakan lalu lintas ke situs web dengan mengantri pengunjung saat kapasitas server hampir penuh. Ini berguna untuk mencegah crash akibat lonjakan traffic, seperti saat peluncuran produk atau event besar.


Bagaimana Cloudflare Waiting Room Bekerja?

  1. Pengunjung Mengakses Website

    • Saat pengguna membuka situs web, request mereka akan melewati Cloudflare terlebih dahulu.
  2. Cloudflare Memeriksa Kapasitas Server

    • Jika server masih dalam batas kapasitas yang aman, pengunjung langsung diarahkan ke situs.
    • Jika server sudah hampir penuh, pengunjung dimasukkan ke dalam waiting room.
  3. Waiting Room Menampilkan Estimasi Waktu Tunggu

    • Pengguna yang masuk ke waiting room akan melihat halaman antrian yang berisi perkiraan waktu tunggu.
    • Cloudflare secara otomatis memperbarui status antrian berdasarkan kapasitas yang tersedia.
  4. Akses Diberikan Secara Bertahap

    • Saat ada slot kosong di server, Cloudflare mengeluarkan pengguna dari waiting room secara bergelombang berdasarkan urutan mereka masuk antrian.

Fitur Utama Cloudflare Waiting Room

✅ Auto-Scaling → Menyesuaikan antrian sesuai kapasitas server.
✅ Estimasi Waktu Tunggu → Memberikan pengalaman pengguna yang lebih baik.
✅ Prioritas Akses → Bisa mengatur siapa yang mendapat prioritas lebih dulu.
✅ Konfigurasi Fleksibel → Bisa disesuaikan dengan jumlah pengunjung maksimal dan batas antrian.
✅ Integrasi Cloudflare CDN → Memastikan loading halaman tetap cepat.


Kapan Harus Menggunakan Cloudflare Waiting Room?

🔹 Saat lonjakan trafik tiba-tiba (contoh: flash sale, pendaftaran event).
🔹 Untuk melindungi server dari overload tanpa menambah infrastruktur mahal.
🔹 Jika ingin memberikan pengalaman pengguna yang lebih terkontrol daripada hanya sekadar error 503 (server penuh).

Cloudflare Waiting Room cocok untuk website e-commerce, tiket event, kampanye digital, dan aplikasi yang sering mengalami lonjakan pengguna! 🚀

Mengatasi Express.js Boros CPU & RAM: Penyebab dan Solusi!🚀

 Berikut cara melakukan profiling Express.js menggunakan Node.js Performance Hooks dan clinic.js untuk mengetahui penyebab penggunaan CPU dan RAM yang tinggi.


1. Profiling dengan Node.js Performance Hooks

Node.js menyediakan modul perf_hooks untuk mengukur waktu eksekusi fungsi dan request.

Langkah 1: Tambahkan Performance Hooks di Express.js

Buat middleware untuk mengukur waktu eksekusi setiap request.

const express = require("express");
const { performance, PerformanceObserver } = require("perf_hooks");

const app = express();
const port = 3000;

// Middleware untuk mengukur waktu request
app.use((req, res, next) => {
    const start = performance.now();
    res.on("finish", () => {
        const duration = performance.now() - start;
        console.log(`Request ${req.method} ${req.url} selesai dalam ${duration.toFixed(2)} ms`);
    });
    next();
});

app.get("/", (req, res) => {
    res.send("Hello World!");
});

app.listen(port, () => {
    console.log(`Server berjalan di http://localhost:${port}`);
});

Langkah 2: Jalankan Server dan Lihat Output

node server.js

Kemudian akses beberapa endpoint, misalnya http://localhost:3000/. Console akan menampilkan durasi eksekusi setiap request.


2. Profiling dengan Clinic.js

clinic.js adalah alat yang lebih kuat untuk menganalisis CPU, RAM, dan event loop.

Langkah 1: Install clinic.js

npm install -g clinic

Langkah 2: Jalankan Profiling dengan Clinic.js

clinic doctor -- node server.js

Lalu akses beberapa endpoint dan tekan Ctrl + C untuk menghentikan proses. Clinic.js akan membuat laporan HTML yang bisa dibuka di browser.

Langkah 3: Analisis Hasil

Buka laporan yang dibuat Clinic.js untuk melihat:

  • Memory Leak → jika penggunaan RAM terus naik tanpa turun.
  • Event Loop Blocking → jika ada proses yang menghambat performa.
  • CPU Usage → jika terlalu tinggi karena proses berat.

Kesimpulan

  1. Gunakan Performance Hooks untuk analisis cepat.
  2. Gunakan Clinic.js untuk laporan lebih mendalam.
  3. Optimasi berdasarkan hasil profiling, misalnya:
    • Kurangi query database yang berat.
    • Gunakan caching (Redis).
    • Optimalkan middleware yang tidak perlu.
    • Gunakan PM2 cluster mode untuk load balancing.

Coba jalankan profiling di proyekmu dan kasih tahu hasilnya, biar kita bisa optimasi lebih lanjut! 🚀

Mengatasi Express.js Boros CPU & RAM: Penyebab dan Solusi!🚀

 Express.js sendiri cukup ringan karena bersifat minimalis dan unopinionated, tetapi ada beberapa faktor yang bisa menyebabkan penggunaan CPU dan RAM meningkat secara drastis, seperti:

1. Beban Request yang Tinggi

  • Jika aplikasi menerima banyak request secara bersamaan, terutama dengan proses berat seperti enkripsi atau manipulasi gambar, ini bisa menyebabkan lonjakan CPU dan RAM.
  • Solusi:
    • Gunakan load balancing (Nginx, PM2 cluster mode)
    • Optimalkan middleware dan hindari pemrosesan berat di server

2. Memory Leak

  • Jika kode tidak menangani objek, event listener, atau koneksi database dengan benar, ini bisa menyebabkan memory leak, di mana RAM terus bertambah tanpa dilepas kembali.
  • Solusi:
    • Gunakan profiling tools seperti Chrome DevTools atau Node.js heapdump
    • Pastikan semua koneksi database ditutup setelah digunakan
    • Hindari menyimpan data besar di global scope

3. Query Database yang Tidak Efisien

  • Jika menggunakan ORM seperti Sequelize/Mongoose, query yang tidak optimal bisa membuat server lambat dan RAM naik karena hasil query disimpan dalam cache.
  • Solusi:
    • Gunakan pagination dan indexing di database
    • Optimalkan query menggunakan EXPLAIN ANALYZE

4. Penggunaan Middleware Berlebihan

  • Terlalu banyak middleware seperti morgan, helmet, express-session bisa membebani server, terutama jika digunakan tanpa konfigurasi yang benar.
  • Solusi:
    • Gunakan middleware hanya jika perlu
    • Hindari logging detail di produksi

5. Tidak Menggunakan PM2 atau Worker Threads

  • Express.js berjalan dalam single-threaded mode, sehingga request berat bisa membuat blocking dan menyebabkan CPU usage tinggi.
  • Solusi:
    • Gunakan PM2 cluster mode untuk menjalankan multiple instances
    • Gunakan Worker Threads atau Child Process untuk tugas berat

Jika Express.js menyebabkan CPU dan RAM naik drastis, coba profiling dulu menggunakan Node.js Performance Hooks atau clinic.js untuk melihat sumber masalah sebelum optimasi lebih lanjut! 🚀

Tuesday, February 18, 2025

Malware&Jenis-jenisnya

 Detail Windows Malware Development

📌 Apa Itu Windows Malware Development?

Windows Malware Development adalah proses pembuatan perangkat lunak berbahaya (malware) yang dirancang untuk mengeksploitasi kelemahan sistem operasi Windows. Malware ini dapat mencuri data, menginfeksi perangkat, atau mengontrol sistem target tanpa izin pengguna.

Catatan: Informasi ini disediakan untuk tujuan edukasi dan kesadaran keamanan siber. Pembuatan, distribusi, atau penggunaan malware untuk aktivitas ilegal adalah tindakan melanggar hukum.


🛠️ Jenis-Jenis Malware Windows

Berikut adalah beberapa jenis malware yang umum dikembangkan di lingkungan Windows:

1️⃣ Virus

📌 Deskripsi:

  • Malware yang menyebar dengan menempel pada file eksekusi (.exe, .dll).
  • Memerlukan interaksi pengguna untuk menyebar (misalnya, membuka file yang terinfeksi).
  • Bisa merusak file, mencuri data, atau mematikan sistem.

📌 Contoh:

  • Michelangelo Virus
  • CIH (Chernobyl Virus)

2️⃣ Worm

📌 Deskripsi:

  • Bisa menyebar secara otomatis tanpa interaksi pengguna.
  • Memanfaatkan kelemahan jaringan dan sistem untuk replikasi.
  • Dapat menyebabkan kelebihan lalu lintas jaringan dan overload sistem.

📌 Contoh:

  • WannaCry (2017) – Menggunakan eksploitasi SMBv1.
  • Morris Worm – Salah satu worm pertama yang menyerang sistem komputer.

3️⃣ Trojan Horse

📌 Deskripsi:

  • Malware yang menyamar sebagai perangkat lunak yang sah.
  • Biasanya digunakan untuk backdoor, keylogger, atau mencuri informasi sensitif.

📌 Contoh:

  • Zeus Trojan – Mengincar informasi perbankan.
  • Emotet – Trojan modular yang sering digunakan dalam serangan lanjutan.

4️⃣ Ransomware

📌 Deskripsi:

  • Mengenkripsi file pengguna dan meminta tebusan untuk mendekripsinya.
  • Biasanya menyebar melalui phishing atau eksploitasi sistem.

📌 Contoh:

  • WannaCry – Ransomware global yang memanfaatkan SMB exploit.
  • Ryuk – Sering digunakan untuk menyerang perusahaan besar.

5️⃣ Spyware & Keylogger

📌 Deskripsi:

  • Spyware: Mencuri informasi pengguna secara diam-diam.
  • Keylogger: Merekam input keyboard untuk mencuri kredensial.

📌 Contoh:

  • DarkComet RAT – Remote Access Trojan (RAT) untuk memata-matai pengguna.
  • HawkEye Keylogger – Digunakan untuk mencuri kredensial login.

6️⃣ Rootkit

📌 Deskripsi:

  • Beroperasi di level kernel dan sulit dideteksi oleh antivirus.
  • Memungkinkan akses sistem tanpa izin pengguna.

📌 Contoh:

  • TDSS Rootkit – Menyembunyikan keberadaan malware lainnya.
  • Alureon (TLD4) – Mengincar sistem Windows untuk mencuri data.

7️⃣ Adware

📌 Deskripsi:

  • Menampilkan iklan berlebihan dan dapat mengalihkan browser ke situs berbahaya.
  • Biasanya terpasang sebagai bundled software.

📌 Contoh:

  • Fireball Adware – Mengubah pengaturan browser pengguna tanpa izin.

🔍 Teknik Pengembangan Malware di Windows

1️⃣ Bahasa Pemrograman yang Digunakan

Malware Windows dapat dikembangkan menggunakan berbagai bahasa pemrograman, termasuk:

  • C/C++ → Untuk malware tingkat rendah dan eksploitasi kernel.
  • Python → Cepat dikembangkan dan dapat dikompilasi menggunakan PyInstaller.
  • PowerShell → Banyak digunakan dalam serangan berbasis script karena dapat berjalan tanpa terdeteksi.
  • Assembly (x86/x64) → Untuk eksploitasi sistem dan rootkit tingkat lanjut.
  • C# / .NET → Digunakan dalam malware fileless yang memanfaatkan API Windows.

2️⃣ Metode Penyebaran

📌 Metode umum yang digunakan untuk menyebarkan malware di Windows:

  1. Phishing Email → Menggunakan lampiran berbahaya (.docx, .exe, .pdf).
  2. Exploit Kits → Memanfaatkan kerentanan seperti EternalBlue untuk menyebarkan malware.
  3. Social Engineering → Menipu pengguna untuk mengunduh malware.
  4. USB AutoRun → Malware menyebar melalui perangkat eksternal.
  5. Drive-By Download → Menginfeksi pengguna melalui situs web berbahaya.

3️⃣ Teknik Evasion (Menghindari Deteksi)

📌 Malware modern menggunakan teknik berikut untuk menghindari deteksi oleh antivirus dan sistem keamanan Windows:

  1. Packing & Obfuscation → Menggunakan packer seperti UPX untuk menyamarkan kode.
  2. Fileless Malware → Berjalan langsung di memori tanpa menyimpan file di disk.
  3. Code Injection → Menyuntikkan kode berbahaya ke dalam proses sah (explorer.exe, svchost.exe).
  4. Process Hollowing → Memanipulasi proses Windows yang sah untuk menjalankan malware.
  5. Hooking API → Mencegah antivirus membaca aktivitas malware.

🛡️ Proteksi dan Pencegahan terhadap Windows Malware

📌 Langkah-langkah penting untuk melindungi sistem Windows dari malware:

  1. Gunakan Antivirus & EDR → Seperti Windows Defender, Malwarebytes, atau SentinelOne.
  2. Patch dan Update Sistem → Hindari eksploitasi terhadap kerentanan yang belum diperbaiki.
  3. Nonaktifkan Macro di Office → Mencegah eksekusi malware berbasis dokumen.
  4. Gunakan Firewall & Network Monitoring → Untuk mendeteksi lalu lintas mencurigakan.
  5. Edukasi Keamanan Siber → Hindari klik tautan mencurigakan atau mengunduh file dari sumber tidak terpercaya.

📌 Kesimpulan

Windows Malware Development adalah bidang kompleks yang mencakup berbagai jenis malware, teknik penyebaran, dan metode penghindaran deteksi. Dengan memahami bagaimana malware bekerja, administrator keamanan dan profesional IT dapat lebih efektif dalam mendeteksi, mencegah, dan merespons ancaman siber.

Monday, February 17, 2025

Spring Webflux + MongoDB : Panduan CRUD Reactive untuk Pemula

 database mongodb : 

Langkah 1: Membuat database testdb

MongoDB tidak memerlukan perintah eksplisit untuk membuat database. Database akan dibuat secara otomatis saat kamu pertama kali menyimpan data ke dalamnya.

Namun, untuk memastikan bahwa kamu bekerja dengan database testdb, gunakan perintah:

----------------

use testdb

----------------

nama database : testdb

nama tabel : movie

entity :

    int id;
    String plot;
    List<String> genres;
    String title;

example data :

{

  "_id": 1,

  "plot": "A great movie plot",

  "genres": [

    "Action",

    "Drama"

  ],

  "title": "My Movie",

  "_class": "com.joko.springwebflux.model.Movie"

}

-------

{

  "_id": 2,

  "plot": "Junior Youth-hen Episode 8",

  "genres": [

    "Sport",

    "Anime"

  ],

  "title": "Captain Tsubasa Season 2",

  "_class": "com.joko.springwebflux.model.Movie"

}

-------

pom.xml :

<?xml version="1.0" encoding="UTF-8"?>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.joko</groupId>
    <artifactId>SpringWebFlux</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringWebFlux</name>
    <description>SpringWebFlux</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <image>
                        <builder>paketobuildpacks/builder-jammy-base:latest</builder>
                    </image>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

application.properties : 

server.port=8085

#mongo db config
port=27017
dbname=testdb

#logging.level.org.springframework=DEBUG

aplikasi Spring Boot dengan spring-boot-properties.

server.port=8085 adalah pengaturan untuk menentukan port yang digunakan untuk server aplikasi (dalam hal ini, 8085).

port=27017 adalah pengaturan untuk menentukan port Mongo DB yang digunakan (dalam hal ini, 27017).

dbname=testdb adalah pengaturan untuk menentukan nama database yang digunakan (dalam hal ini, testdb).


model : Movie.java

package com.joko.springwebflux.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.List;

@Document
public class Movie {

    @Id
    int id;
    String plot;
    List<String> genres;
    String title;

    public Movie() {
    }

    public Movie(int id, String plot, List<String> genres, String title) {
        this.id = id;
        this.plot = plot;
        this.genres = genres;
        this.title = title;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPlot() {
        return plot;
    }

    public void setPlot(String plot) {
        this.plot = plot;
    }

    public List<String> getGenres() {
        return genres;
    }

    public void setGenres(List<String> genres) {
        this.genres = genres;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public String toString() {
        return "Movie{" +
                "id=" + id +
                ", plot='" + plot + '\'' +
                ", genres=" + genres +
                ", title='" + title + '\'' +
                '}';
    }
}


Kode di atas mendefinisikan sebuah model `Movie` yang mewakili entitas "Film" dalam konteks aplikasi berbasis Spring WebFlux dengan MongoDB sebagai penyimpanan datanya.

Berikut adalah penjelasan dari kode tersebut:

 1. Package

```java

package com.joko.springwebflux.model;

```

Kode ini menunjukkan bahwa kelas `Movie` berada di dalam package `com.joko.springwebflux.model`. Package ini digunakan untuk mengelompokkan kelas berdasarkan fungsionalitas yang terkait.

 2. Import Statements

```java

import org.springframework.data.annotation.Id;

import org.springframework.data.mongodb.core.mapping.Document;

import java.util.List;

```

- `@Id`: Anotasi ini digunakan untuk menunjukkan bahwa atribut `id` adalah identifier unik (primary key) untuk objek `Movie`.

- `@Document`: Anotasi ini digunakan untuk memberi tahu Spring bahwa kelas `Movie` akan disimpan sebagai dokumen di MongoDB.

- `List`: Struktur data dari Java yang digunakan untuk menyimpan koleksi elemen (dalam hal ini, genre dari film).


 3. Deklarasi Kelas

```java

@Document

public class Movie {

```

Kelas `Movie` didekorasi dengan anotasi `@Document`, yang mengindikasikan bahwa entitas ini akan disimpan di database MongoDB sebagai sebuah dokumen.

 4. Atribut Kelas

```java

@Id

int id;

String plot;

List<String> genres;

String title;

```

Atribut-atribut berikut terdapat dalam kelas `Movie`:

- `id`: Sebuah integer yang bertindak sebagai identifier unik untuk setiap film.

- `plot`: Sebuah string yang menyimpan ringkasan atau sinopsis dari film.

- `genres`: Sebuah list dari string yang menyimpan genre film (misalnya, "action", "drama", dll).

- `title`: Sebuah string yang menyimpan judul dari film.

 5. Konstruktor

```java

public Movie() {

}


public Movie(int id, String plot, List<String> genres, String title) {

    this.id = id;

    this.plot = plot;

    this.genres = genres;

    this.title = title;

}

```

Terdapat dua konstruktor:

- Konstruktor default (tanpa parameter), yang dibutuhkan oleh framework seperti Spring untuk instansiasi objek.

- Konstruktor yang memiliki parameter untuk menginisialisasi objek `Movie` dengan nilai-nilai tertentu.

 6. Getter dan Setter

Kode ini berisi method getter dan setter untuk setiap atribut kelas:

```java

public int getId() { ... }

public void setId(int id) { ... }

public String getPlot() { ... }

public void setPlot(String plot) { ... }

public List<String> getGenres() { ... }

public void setGenres(List<String> genres) { ... }

public String getTitle() { ... }

public void setTitle(String title) { ... }

```

Getter dan setter digunakan untuk mengambil (get) dan mengubah (set) nilai dari atribut `id`, `plot`, `genres`, dan `title`.

 7. Method `toString()`

```java

@Override

public String toString() {

    return "Movie{" +

            "id=" + id +

            ", plot='" + plot + '\'' +

            ", genres=" + genres +

            ", title='" + title + '\'' +

            '}';

}

```

Method ini digunakan untuk mengubah objek `Movie` menjadi string yang mudah dibaca, yang biasanya berguna untuk debugging atau logging.

Kelas `Movie` ini adalah sebuah entitas yang merepresentasikan film dalam sistem dengan atribut-atribut seperti `id`, `plot`, `genres`, dan `title`. Kelas ini menggunakan anotasi Spring MongoDB (`@Document` dan `@Id`) untuk memetakan objek ini ke dalam dokumen MongoDB.

DAO repository : 

package com.joko.springwebflux.dao;

import com.joko.springwebflux.model.Movie;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Flux;

public interface MovieRepository extends ReactiveMongoRepository<Movie, Integer> {

    @Query("{ 'name': ?0 }")
    Flux<Movie> findByName(final String title);

}

Kode yang diberikan merupakan sebuah repository yang digunakan untuk berinteraksi dengan database MongoDB dalam konteks aplikasi berbasis **Spring WebFlux**. Repository ini menggunakan **ReactiveMongoRepository**, yang mendukung operasi secara **asinkron dan non-blocking** sesuai dengan konsep reaktif di Spring WebFlux.

 1. Package

```java

package com.joko.springwebflux.dao;

```

Kode ini menunjukkan bahwa interface `MovieRepository` berada di dalam package `com.joko.springwebflux.dao`, yang kemungkinan besar digunakan untuk menampung class atau interface yang berfungsi sebagai Data Access Object (DAO).

 2. Import Statements

```java

import com.joko.springwebflux.model.Movie;

import org.springframework.data.mongodb.repository.Query;

import org.springframework.data.mongodb.repository.ReactiveMongoRepository;

import reactor.core.publisher.Flux;

```

- `Movie`: Import model `Movie`, yang merupakan entitas yang disimpan di MongoDB.

- `@Query`: Digunakan untuk menulis query MongoDB secara manual di dalam metode repository.

- `ReactiveMongoRepository`: Interface khusus yang disediakan oleh Spring Data MongoDB untuk menangani operasi CRUD dengan sifat reaktif.

- `Flux`: Tipe data reaktif yang disediakan oleh Project Reactor, yang mewakili aliran data yang bersifat non-blocking. Berbeda dari `Mono` (yang hanya mewakili satu elemen atau kosong), `Flux` dapat mengandung 0 hingga banyak elemen.

 3. Deklarasi Interface

```java

public interface MovieRepository extends ReactiveMongoRepository<Movie, Integer> {

```

- `MovieRepository`: Interface ini merupakan **repository** yang digunakan untuk berinteraksi dengan database MongoDB.

- `extends ReactiveMongoRepository<Movie, Integer>`: Interface ini mewarisi dari `ReactiveMongoRepository`, yang menyediakan implementasi default untuk operasi CRUD yang reaktif (misalnya, `findAll()`, `save()`, `delete()`, dll). 

  - `Movie`: Tipe entitas yang akan dikelola oleh repository ini.

  - `Integer`: Tipe dari ID entitas (`Movie`), yang dalam hal ini adalah tipe `Integer`.

 4. Custom Query Method

```java

@Query("{ 'name': ?0 }")

Flux<Movie> findByName(final String title);

```

- `@Query("{ 'name': ?0 }")`: Mengindikasikan bahwa ini adalah custom query manual untuk MongoDB. Dalam query ini, `'name'` adalah field dalam dokumen MongoDB yang ingin dicari, dan `?0` adalah placeholder untuk parameter pertama dari metode (`title`).

  - Field `'name'` ini diasumsikan ada di dalam dokumen `Movie` di MongoDB. Mungkin ada sedikit kesalahan penamaan di sini karena field yang benar di kelas `Movie` adalah `title`, bukan `name`.

- `Flux<Movie>`: Metode ini mengembalikan hasil pencarian berupa aliran reaktif (`Flux`) yang berisi satu atau lebih objek `Movie`.

- `findByName(final String title)`: Nama metode ini secara semantik berarti "mencari film berdasarkan nama/title". Metode ini menerima sebuah parameter `title` (judul film) dan akan mengembalikan semua film yang cocok dengan judul tersebut.

 Kesimpulan:

- MovieRepository` adalah repository yang digunakan untuk mengakses data `Movie` dari MongoDB.

- ReactiveMongoRepository` menyediakan operasi database dasar yang bersifat reaktif, mengikuti pola non-blocking dari Spring WebFlux.

- Custom query dengan anotasi `@Query` memungkinkan penulisan query MongoDB manual untuk mencari film berdasarkan nama (`name`), meskipun berdasarkan model seharusnya adalah `title`.

- Metode `findByName` mengembalikan `Flux<Movie>`, yang merepresentasikan serangkaian hasil pencarian secara reaktif (dapat berisi 0 atau lebih hasil).

Jika ada kesalahan di query, seperti menggunakan `'name'` alih-alih `'title'`, maka sebaiknya diganti agar sesuai dengan field yang ada di kelas `Movie`.

service :

package com.joko.springwebflux.service;

import com.joko.springwebflux.model.Movie;
import com.joko.springwebflux.dao.MovieRepository;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
public class MovieService implements IMovieService {

    final
    MovieRepository movieRepo;

    public MovieService(MovieRepository movieRepo) {
        this.movieRepo = movieRepo;
    }

    public void create(Movie e) {
        movieRepo.save(e).subscribe();
    }

    public Flux<Movie> findAll() {
        return movieRepo.findAll();
    }
    public Flux<Movie> findByName(String title) {
        return movieRepo.findByName(title);
    }

    public Mono<Movie> findById(Integer id) {
        return movieRepo.findById(id);
    }

    public Mono<Movie> update(Movie e) {
        return movieRepo.save(e);
    }

    public Mono<Void> delete(Integer id) {
        return movieRepo.deleteById(id);
    }

}

Kode yang diberikan adalah implementasi dari **MovieService**, sebuah service layer dalam aplikasi Spring WebFlux. Kelas ini bertanggung jawab untuk mengelola operasi bisnis terkait objek **Movie**, seperti penyimpanan, pengambilan, pembaruan, dan penghapusan data film dalam database MongoDB, menggunakan repository `MovieRepository`.

 1. Package

```java

package com.joko.springwebflux.service;

```

Kode ini menunjukkan bahwa `MovieService` berada di dalam package `com.joko.springwebflux.service`, yang digunakan untuk mengelompokkan service logic.

 2. Import Statements

```java

import com.joko.springwebflux.model.Movie;

import com.joko.springwebflux.dao.MovieRepository;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import reactor.core.publisher.Flux;

import reactor.core.publisher.Mono;

```

- **`Movie`**: Model atau entitas yang merepresentasikan objek film.

- **`MovieRepository`**: Repository yang berinteraksi dengan MongoDB untuk operasi database terkait `Movie`.

- **`@Service`**: Anotasi ini memberi tahu Spring bahwa kelas `MovieService` ini adalah **service** yang akan dikelola oleh container Spring dan memungkinkan dependency injection.

- **`Flux`** dan **`Mono`**: Tipe data reaktif dari Project Reactor.

  - **`Flux`** digunakan untuk mengelola aliran data yang bisa terdiri dari 0 hingga banyak elemen.

  - **`Mono`** digunakan untuk aliran data yang hanya terdiri dari 0 atau 1 elemen.

 3. Deklarasi Kelas dan Dependency Injection

```java

@Service

public class MovieService implements IMovieService {

```

- **`@Service`**: Menandai bahwa `MovieService` adalah kelas service yang akan dikelola oleh Spring, dan dapat digunakan untuk menjalankan operasi terkait logika bisnis.

- **`implements IMovieService`**: Kelas ini mengimplementasikan interface `IMovieService` (yang tidak disediakan di kode ini), kemungkinan besar berisi definisi abstrak dari metode yang digunakan dalam service ini.

```java

final MovieRepository movieRepo;

```

- `movieRepo`: Dependency `MovieRepository` yang dideklarasikan sebagai `final` untuk memastikan bahwa referensi ini tidak akan diubah setelah diinisialisasi.

```java

public MovieService(MovieRepository movieRepo) {

    this.movieRepo = movieRepo;

}

```

- Konstruktor ini melakukan **constructor-based dependency injection**. `MovieRepository` akan diinject oleh Spring saat service ini dibuat, memberikan akses ke metode CRUD MongoDB.

 4. Method `create(Movie e)`

```java

public void create(Movie e) {

    movieRepo.save(e).subscribe();

}

```

- **`movieRepo.save(e)`**: Menyimpan objek `Movie` ke dalam database MongoDB. Karena `save()` mengembalikan `Mono<Movie>`, method ini bersifat reaktif.

- **`.subscribe()`**: Menginisialisasi eksekusi operasi reaktif. Tanpa `subscribe()`, operasi tidak akan dijalankan. Karena ini adalah operasi non-blocking, `subscribe()` memulai penyimpanan objek tanpa menunggu hasilnya.

 5. Method `findAll()`

```java

public Flux<Movie> findAll() {

    return movieRepo.findAll();

}

```

- **`movieRepo.findAll()`**: Mengambil semua objek `Movie` dari database MongoDB. Operasi ini mengembalikan **`Flux<Movie>`**, karena bisa mengembalikan banyak hasil.

 6. Method `findByName(String title)`

```java

public Flux<Movie> findByName(String title) {

    return movieRepo.findByName(title);

}

```

- **`movieRepo.findByName(title)`**: Mengambil objek `Movie` yang memiliki judul tertentu, menggunakan custom query dari repository (`findByName`). Metode ini mengembalikan **`Flux<Movie>`**, karena bisa ada lebih dari satu film dengan judul yang sama.

 7. Method `findById(Integer id)`

```java

public Mono<Movie> findById(Integer id) {

    return movieRepo.findById(id);

}

```

- **`movieRepo.findById(id)`**: Mencari objek `Movie` berdasarkan ID-nya. Karena ID bersifat unik, operasi ini mengembalikan **`Mono<Movie>`** yang akan berisi 0 atau 1 hasil.

 8. Method `update(Movie e)`

```java

public Mono<Movie> update(Movie e) {

    return movieRepo.save(e);

}

```

- **`movieRepo.save(e)`**: Mengupdate objek `Movie` dengan menyimpan perubahan ke database MongoDB. MongoDB secara otomatis melakukan upsert, artinya jika objek sudah ada, maka akan diperbarui, dan jika belum ada, akan ditambahkan. Metode ini mengembalikan **`Mono<Movie>`**, yang berarti operasi ini hanya bekerja dengan satu entitas.

 9. Method `delete(Integer id)`

```java

public Mono<Void> delete(Integer id) {

    return movieRepo.deleteById(id);

}

```

- **`movieRepo.deleteById(id)`**: Menghapus objek `Movie` berdasarkan ID-nya. Metode ini mengembalikan **`Mono<Void>`**, yang menunjukkan bahwa operasi tidak mengembalikan data apa pun, tetapi hanya memberi sinyal ketika penghapusan selesai.

 Kesimpulan:

- **`MovieService`** adalah layer service yang mengelola operasi CRUD untuk entitas `Movie` secara reaktif.

- Service ini menggunakan **ReactiveMongoRepository** untuk operasi non-blocking dengan MongoDB.

- **Flux** digunakan untuk mengembalikan kumpulan data (seperti pada `findAll()` dan `findByName()`), sedangkan **Mono** digunakan untuk operasi yang hanya mengembalikan satu entitas atau tanpa hasil (seperti `findById()`, `update()`, dan `delete()`).


implementasi service : 

package com.joko.springwebflux.service;

import com.joko.springwebflux.model.Movie;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public interface IMovieService {

    void create(Movie e);
    Flux<Movie> findAll();

    Flux<Movie> findByName(String title);

    Mono<Movie> findById(Integer id);

    Mono<Movie> update(Movie e);

    Mono<Void> delete(Integer id);
}

Kode yang diberikan mendefinisikan sebuah interface bernama `IMovieService`, yang menyediakan kontrak atau abstraksi untuk service terkait operasi CRUD (Create, Read, Update, Delete) pada entitas **Movie** dalam aplikasi berbasis **Spring WebFlux**. Interface ini beroperasi secara **reaktif**, memanfaatkan **Flux** dan **Mono** dari Project Reactor untuk menangani data.

Berikut penjelasan lebih detail dari setiap bagian kode tersebut:

 1. Package

```java

package com.joko.springwebflux.service;

```

Package ini menunjukkan bahwa interface `IMovieService` berada di dalam package `com.joko.springwebflux.service`. Ini mengindikasikan bahwa interface ini adalah bagian dari layer **service** dalam aplikasi.

 2. Import Statements

```java

import com.joko.springwebflux.model.Movie;

import reactor.core.publisher.Flux;

import reactor.core.publisher.Mono;

```

- **`Movie`**: Model atau entitas yang merepresentasikan sebuah film.

- **`Flux`**: Tipe reaktif yang dapat berisi 0 hingga banyak elemen. Digunakan ketika ada lebih dari satu hasil yang diharapkan (misalnya, list film).

- **`Mono`**: Tipe reaktif yang mengandung paling banyak 1 elemen (atau kosong). Digunakan untuk operasi yang mengembalikan satu entitas atau untuk operasi yang tidak memerlukan pengembalian data (seperti penghapusan).

 3. Deklarasi Interface

```java

public interface IMovieService {

```

- **`IMovieService`**: Interface ini mendefinisikan kontrak untuk service yang mengelola entitas `Movie`. Semua class yang mengimplementasikan interface ini harus menyediakan implementasi untuk metode-metode yang didefinisikan.

 4. Metode dalam `IMovieService`

 a. `void create(Movie e)`

```java

void create(Movie e);

```

- **Tujuan**: Metode ini digunakan untuk menambahkan objek `Movie` baru ke dalam database.

- **Parameter**: `Movie e` - objek film yang akan disimpan.

- **Return**: Tidak ada nilai yang dikembalikan (`void`), tetapi karena metode yang sebenarnya diimplementasikan akan bersifat reaktif, penyimpanan mungkin akan dilakukan secara asinkron.

 b. `Flux<Movie> findAll()`

```java

Flux<Movie> findAll();

```

- **Tujuan**: Mengambil semua film dari database.

- **Return**: Mengembalikan **`Flux<Movie>`**, yang merupakan aliran reaktif berisi daftar film. `Flux` dapat berisi 0 hingga banyak elemen.


 c. `Flux<Movie> findByName(String title)`

```java

Flux<Movie> findByName(String title);

```

- **Tujuan**: Mencari film berdasarkan judul.

- **Parameter**: `String title` - judul film yang dicari.

- **Return**: Mengembalikan **`Flux<Movie>`**, yang merupakan aliran reaktif berisi daftar film yang cocok dengan judul yang diberikan. Karena bisa ada lebih dari satu film dengan judul yang sama, hasil dikembalikan dalam bentuk `Flux`.

 d. `Mono<Movie> findById(Integer id)`

```java

Mono<Movie> findById(Integer id);

```

- **Tujuan**: Mencari film berdasarkan **ID**.

- **Parameter**: `Integer id` - ID unik dari film yang ingin dicari.

- **Return**: Mengembalikan **`Mono<Movie>`**, yang merupakan aliran reaktif berisi satu film atau kosong jika film dengan ID tersebut tidak ditemukan.

 e. `Mono<Movie> update(Movie e)`

```java

Mono<Movie> update(Movie e);

```

- **Tujuan**: Mengupdate atau memperbarui data film di database.

- **Parameter**: `Movie e` - objek film yang berisi data yang diperbarui.

- **Return**: Mengembalikan **`Mono<Movie>`**, yang berisi film yang diperbarui setelah perubahan disimpan.

 f. `Mono<Void> delete(Integer id)`

```java

Mono<Void> delete(Integer id);

```

- **Tujuan**: Menghapus film berdasarkan **ID** dari database.

- **Parameter**: `Integer id` - ID dari film yang akan dihapus.

- **Return**: Mengembalikan **`Mono<Void>`**, yang menunjukkan bahwa operasi penghapusan sudah selesai, tetapi tidak mengembalikan data.

 Kesimpulan:

- **`IMovieService`** adalah **interface service layer** yang mendefinisikan operasi dasar yang harus diimplementasikan oleh service yang menangani entitas `Movie`.

- Metode-metode yang dideklarasikan bersifat **reaktif**, menggunakan **Flux** dan **Mono** untuk mendukung aliran data secara asinkron dan non-blocking.

- Interface ini berfokus pada operasi CRUD, termasuk menambah film (`create`), mengambil daftar film (`findAll`), mencari film berdasarkan judul atau ID (`findByName`, `findById`), memperbarui film (`update`), dan menghapus film (`delete`).

controller : 

package com.joko.springwebflux.controller;

import com.joko.springwebflux.model.Movie;
import com.joko.springwebflux.service.MovieService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/movie")
public class MovieController {

    @Autowired
    private MovieService movieService;

    @PostMapping(path = "/add", consumes = "application/json")
    @ResponseStatus(HttpStatus.CREATED)
    public void create(@RequestBody Movie movie) {
        movieService.create(movie);
    }

    @GetMapping("/get/{id}")
    @ResponseBody
    public ResponseEntity<Mono<Movie>> findById(@PathVariable("id") Integer id) {
        Mono<Movie> movie = movieService.findById(id);
        return new ResponseEntity<Mono<Movie>>(movie, HttpStatus.OK);
    }

    @GetMapping( "/getByTitle")
    public Flux<Movie> findByName(@RequestParam("title") String title) {
        return movieService.findByName(title);
    }

    @GetMapping("/")
    public Flux<Movie> findAll() {
        Flux<Movie> movies = movieService.findAll();
        return movies;
    }

    @PutMapping("/update")
    @ResponseStatus(HttpStatus.OK)
    public Mono<Movie> update(@RequestBody Movie movie) {
        return movieService.update(movie);
    }

    @DeleteMapping( "/delete/{id}")
    @ResponseStatus(HttpStatus.OK)
    public void delete(@PathVariable("id") Integer id) {
        movieService.delete(id).subscribe();
    }
}

config : 

database config : 

package com.joko.springwebflux.config;

import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;


@Configuration
@EnableReactiveMongoRepositories(basePackages = "com.joko.springwebflux.dao")
public class MongoConfig extends AbstractReactiveMongoConfiguration {
    @Value("${port}")
    private String port;

    @Value("${dbname}")
    private String dbName;

    @Override
    public MongoClient reactiveMongoClient() {
        return MongoClients.create();
    }

    @Override
    protected String getDatabaseName() {
        return dbName;
    }

    @Bean
    public ReactiveMongoTemplate reactiveMongoTemplate() {
        return new ReactiveMongoTemplate(reactiveMongoClient(), getDatabaseName());
    }
}


WebFluxConfig : 

package com.joko.springwebflux.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;

@Configuration
@EnableWebFlux
public class WebFluxConfig implements WebFluxConfigurer {
}

spring application : 

package com.joko.springwebflux;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringWebFluxApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringWebFluxApplication.class, args);
    }

}

iklan

iklan