128 lines
5.9 KiB
Markdown
128 lines
5.9 KiB
Markdown
# 🚀 Dynamic SOA Mapper (Configuration-Driven Payload Engine)
|
|
|
|
## 📖 Apa itu Dynamic SOA Mapper?
|
|
Dalam sistem integrasi perbankan/Enterprise, memetakan data internal ke format JSON yang diminta oleh *Service Oriented Architecture* (SOA) seringkali memakan waktu. Jika ada 120+ jenis transaksi (Kotran), dan setiap Kotran memiliki puluhan field hingga struktur *Array*, melakukan *hardcode* di Java akan menghasilkan *spaghetti code* yang sulit di-*maintain*.
|
|
|
|
**Dynamic SOA Mapper** memecahkan masalah ini dengan pendekatan **Metadata-Driven Architecture**.
|
|
Seluruh aturan transformasi, operasi matematika, pembentukan JSON berjenjang (*nested*), hingga pembuatan **JSON Array** diserahkan 100% kepada konfigurasi di tabel Database menggunakan **Spring Expression Language (SpEL)**.
|
|
|
|
---
|
|
|
|
## ✨ Fitur Utama
|
|
1. **100% Dynamic Rules:** Menggunakan **SpEL** untuk manipulasi data (*string concatenation*, matematika, *ternary operator*, format tanggal) langsung dari teks di database tanpa *deploy* ulang (*Zero Downtime*).
|
|
2. **Global Configuration:** Mendukung Kotran `GLOBAL` untuk mendefinisikan *Header* atau *field* statis yang otomatis digabungkan (*merged*) ke seluruh request Kotran lainnya. Sangat *DRY (Don't Repeat Yourself)*!
|
|
3. **Auto Nested-JSON (Dot Notation):** Cukup gunakan titik pada konfigurasi (contoh: `header.message.id`), *engine* otomatis merakit struktur JSON bertingkat.
|
|
4. **JSON Array Support:** Mendukung pembuatan *Array of Objects* (List of Maps) secara dinamis hanya dari satu baris konfigurasi teks.
|
|
5. **High Performance:** Aturan SpEL di-*parse* dan di-*cache* (*ConcurrentHashMap*). Eksekusi *mapping* berjalan dalam hitungan mikrosekon (O(1)).
|
|
6. **Resilient & Fail-Safe:** Dilengkapi dengan fitur *Safe Navigation* (mencegah NPE), *Default Value* (*fallback*), dan validasi *Mandatory Field*.
|
|
|
|
---
|
|
|
|
## 🏗️ Arsitektur & Cara Kerja
|
|
|
|
Saat *endpoint* API dipanggil (misal: Kotran `1001`):
|
|
1. **Data Aggregation:** Sistem menarik data (`Transaction`, `Payment`) dan menyimpannya ke `StandardEvaluationContext`.
|
|
2. **Fetch & Merge Configuration:** Sistem mengambil aturan `GLOBAL` dan aturan spesifik `1001` dari tabel `SOA_MAPPING_CONFIG`, lalu menggabungkannya.
|
|
3. **SpEL Evaluation:** *Engine* mengeksekusi `expression_rule` terhadap *Context* data sumber.
|
|
4. **JSON Assembly:** Hasil diekstrak menjadi *Map* dan *List* (termasuk *nested*), lalu dikembalikan sebagai JSON utuh.
|
|
|
|
---
|
|
|
|
## 💻 Panduan Penggunaan & Konfigurasi
|
|
|
|
### 1. Struktur Tabel Konfigurasi (`SOA_MAPPING_CONFIG`)
|
|
Ini adalah jantung dari *mapping engine* ini.
|
|
|
|
| Kolom | Penjelasan | Contoh Pengisian |
|
|
| :--- | :--- | :--- |
|
|
| `KOTRAN` | Kode transaksi. Gunakan `GLOBAL` untuk rule yang berlaku di semua Kotran. | `GLOBAL`, `1001`, `1304` |
|
|
| `TARGET_FIELD_NM` | Nama *key* JSON tujuan. Gunakan titik (`.`) untuk *nested object*. | `messageHeader.tellerId` |
|
|
| `TARGET_FIELD_TYPE` | Tipe data target (saat ini sebagai referensi dokumentasi). | `String`, `Number`, `List` |
|
|
| `EXPRESSION_RULE` | **Aturan SpEL** untuk mengambil/mengubah data. | `#transaction.amount * 100` |
|
|
| `DEFAULT_VALUE` | Nilai *fallback* jika hasil evaluasi *rule* bernilai `null`. | `0`, `NO_DATA` |
|
|
| `IS_MANDATORY` | `1` (Wajib). Jika evaluasi dan default *null*, sistem akan *throw Error*. | `1`, `0` |
|
|
|
|
### 2. Cheatsheet Penulisan Expression Rule (SpEL)
|
|
Objek yang tersedia di dalam *Context* saat ini adalah: `#transaction` dan `#payment`.
|
|
|
|
* **Mapping Langsung:** `#payment.debitAccountNo`
|
|
* **Hardcode Value:** `'PT BUMI MAKMUR'` *(Gunakan kutip satu)*
|
|
* **Matematika & Logika:** `#transaction.amount * 15000`
|
|
* **Format Tanggal:** `new java.text.SimpleDateFormat('yyyyMMdd').format(#transaction.effectiveDate)`
|
|
* **Ternary (If-Else):** `#transaction.status == 'SUCCESS' ? '00' : '99'`
|
|
* **Safe Navigation (Anti-NPE):** `#transaction?.promoCode`
|
|
|
|
### 3. Panduan Membuat JSON Array (Array of Objects)
|
|
Jika SOA meminta format JSON Array seperti ini:
|
|
```json
|
|
"property": [
|
|
{ "key": "teller", "value": "811" },
|
|
{ "key": "trxId", "value": "TRX-123" }
|
|
]
|
|
```
|
|
Gunakan sintaks **Inline List of Maps** dari SpEL (Kurung kurawal di dalam kurung kurawal):
|
|
* **Expression Rule:** `{ {'key': 'teller', 'value': '811'}, {'key': 'trxId', 'value': #transaction.id} }`
|
|
|
|
---
|
|
|
|
## 🚀 Cara Menjalankan Aplikasi Lokal
|
|
|
|
### Prasyarat:
|
|
* Java 17+
|
|
* Maven 3.x
|
|
* Database Oracle (Sesuaikan URL/Credential di `application.yaml`)
|
|
|
|
### Langkah-langkah:
|
|
1. Pastikan database Oracle menyala.
|
|
2. Jalankan perintah:
|
|
```bash
|
|
./mvnw spring-boot:run
|
|
```
|
|
3. Saat *startup* pertama, `DataSeeder.java` akan menyuntikkan data *dummy* dan konfigurasi.
|
|
|
|
---
|
|
|
|
## 🎯 Uji Coba (API Testing)
|
|
|
|
Gunakan Postman atau *browser* untuk menembak *endpoint* berikut:
|
|
|
|
**Test Kotran 1001 (Global + Mapping + Math + Array):**
|
|
```http
|
|
GET http://localhost:8080/api/v1/soa/generate-payload?transactionId=TRX-555&kotran=1001
|
|
```
|
|
|
|
*Output yang diharapkan:*
|
|
```json
|
|
{
|
|
"RequestHeader": {
|
|
"MessageSender": "TPS_CORE",
|
|
"MessageType": "JSON",
|
|
"ChannelId": "116",
|
|
"GlobalTimestamp": "2026-02-28 06:15:00"
|
|
},
|
|
"TLBF_ACC": "1234567890",
|
|
"TLBF_AMT": 5000.0,
|
|
"TLBF_CCY": "USD",
|
|
"messageHeader": {
|
|
"property": [
|
|
{
|
|
"propertyKey": "tellerId",
|
|
"propertyValue": "8119852"
|
|
},
|
|
{
|
|
"propertyKey": "transactionCode",
|
|
"propertyValue": "TRX-555"
|
|
},
|
|
{
|
|
"propertyKey": "currency",
|
|
"propertyValue": "USD"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔒 Error Handling & Worklist Integration
|
|
Aplikasi ini di-desain *Fail-Safe*. Jika ada *mandatory field* yang gagal terpetakan (bernilai `null` setelah *fallback*), `MappingEngineService` akan melempar `RuntimeException`. Di arsitektur *Production*, *exception* ini akan ditangkap oleh *Orchestrator* untuk kemudian disimpan ke tabel **Worklist** agar bisa diperbaiki konfigurasinya dan di-*retry* secara manual tanpa kehilangan transaksi. |