iFlow Pertama: Hello World dalam Tiga Tahap

Mengisi iFlow pertama secara bertahap (balasan tetap, membaca request dengan Groovy, lalu menangani error dengan Exception Subprocess) dan mengujinya tanpa sistem luar.

Daftar isi11 bagian

Di Toko Nusantara, kerangka IF_ERP2BTP_HelloWorld_Sync sudah ada sejak artikel Tur Layar, tapi masih kosong. Saya ingin iFlow ini menerima JSON berisi nama pelanggan dan membalas dengan sapaan.

Godaan pertama saya: langsung menulis Groovy yang mengerjakan semuanya. Ternyata lebih enak bertahap, supaya kalau gagal, saya tahu bagian mana yang salah.

Kenapa penting

Tiga tahap ini adalah pola yang akan dipakai di hampir semua iFlow seri ini: balasan sederhana, logika di script, lalu penanganan error. Di ABAP, urutannya mirip dengan menulis program kecil: tampilkan output dulu, tambahkan logika, baru bungkus dengan TRY ... CATCH.

Konsep

Alur akhirnya seperti ini:

Bagian

Step

Fungsi

Pengirim

HTTPS sender

Menerima request dari Postman di address /erp/helloworld

Tahap 1

CM_SetHelloReply (Content Modifier)

Membalas teks tetap

Tahap 2

GS_BuildGreeting (Groovy Script)

Membaca nama dari request, membangun balasan

Tahap 3

EXS_HandleError (Exception Subprocess)

Mengubah error menjadi balasan JSON yang rapi

Nama step mengikuti pola <PREFIX>_<Verb><Object>.

IF_ERP2BTP_HelloWorld_Sync /erp/helloworldStartedJeda
SuksesBody {}Body kosong

ikut terkirim

{"customer":
 "Pelanggan Demo 01"}
1/3Postman mengirim nama pelanggan.
Ikuti satu pesan melewati iFlow di artikel ini. Pilih skenario di atas, atau klik titik langkah untuk berhenti di satu tahap.

Langkah

Persiapan: sender HTTPS

Buka iFlow, klik Edit. Hapus dulu kotak Receiver dari kerangka: iFlow ini sinkron, jadi balasannya kembali ke pengirim lewat koneksi yang sama dan tidak ada sistem tujuan. Receiver baru kita pakai di Series 2 saat CPI memanggil API lain. Lalu hubungkan Sender ke Start dan pilih adapter HTTPS. Di tab Connection, isi Address dengan /erp/helloworld. Pengaturan lain biarkan default dulu; soal CSRF Protected kita bahas di artikel berikutnya saat memanggil iFlow dari Postman.

Cara menguji tanpa deploy: Simulation

Setiap tahap diuji dengan Simulation di editor, tanpa deploy. Untuk ABAPer, ini mirip menjalankan function module di SE37: logikanya dites tanpa harus dipanggil dari luar. Caranya sama untuk ketiga tahap:

  1. Pastikan dalam mode Edit, lalu Save.

  2. Klik panah setelah Start, pilih Add Simulation Start Point. Klik panah sebelum End, pilih Add Simulation End Point. Ikon ▶ di toolbar baru aktif setelah keduanya terpasang.

  3. Kalau tahap itu butuh input, klik penanda start point dan isi Body.

  4. Klik ▶ untuk menjalankan.

  5. Klik ikon amplop di end point. Panel bawah menampilkan isi pesan di titik itu: tab Headers, Properties, dan Body.

Tahap 1: balasan tetap

Tambahkan Content Modifier di antara Start dan End, beri nama CM_SetHelloReply.

  • Tab Message Header: tambahkan Content-Type dengan nilai application/json.

  • Tab Message Body: tipe Constant, isi {"message": "Halo dari Toko Nusantara!"}. Isinya teks tetap tanpa variabel, jadi Constant sudah cukup.

Uji: jalankan Simulation tanpa input. CM_SetHelloReply tidak membaca body yang masuk; body itu ditimpa dengan teks tetap tadi, jadi input kosong tidak masalah.

Input body

Hasil di tab Body

(kosong)

{"message": "Halo dari Toko Nusantara!"}

Tahap 2: baca request dengan Groovy

Ganti CM_SetHelloReply dengan Groovy Script bernama GS_BuildGreeting, lalu buat script baru BuildGreeting.groovy:

Groovy
import com.sap.gateway.ip.core.customdev.util.Message
import groovy.json.JsonOutput
import groovy.json.JsonSlurper

def Message processData(Message message) {
    def bodyText = message.getBody(java.io.Reader)?.text
    if (!bodyText?.trim()) {
        throw new IllegalArgumentException("Body request kosong")
    }

    def request = new JsonSlurper().parseText(bodyText)
    def customer = request?.customer

    if (!customer) {
        throw new IllegalArgumentException("Field 'customer' wajib diisi")
    }

    // Catatan kurir: dipakai di dalam iFlow saja
    message.setProperty("p_customer", customer)

    // Custom header di Message Processing Log, supaya pesan bisa dicari per pelanggan
    def messageLog = messageLogFactory.getMessageLog(message)
    messageLog?.addCustomHeaderProperty("Log_Customer", customer.toString())

    def reply = [message: "Halo ${customer}, salam dari Toko Nusantara!".toString()]
    message.setBody(JsonOutput.toJson(reply))
    message.setHeader("Content-Type", "application/json")
    return message
}

Beberapa hal yang sengaja saya lakukan:

  • Body diambil dengan message.getBody(java.io.Reader), dibaca jadi teks, dicek tidak kosong, baru di-parse dengan parseText. Alasan saya tidak memakai parse(reader) ada di bagian jebakan.

  • addCustomHeaderProperty menambahkan kolom yang bisa dicari di Monitor. Awalan Log_ menandai bahwa nilai ini khusus untuk pencarian di log; aturan lengkapnya ada di artikel Naming Convention supaya iFlow Mudah Dibaca di akhir Series 1. Untuk ABAPer, ini mirip menambahkan external number di SLG1 supaya log bisa difilter.

  • ?. mencegah error kalau messageLog tidak tersedia, misalnya saat Simulation.

Uji: kali ini input wajib diisi, karena script membaca nama pelanggan dari body. Tanpa input, Simulation berhenti dengan Body request kosong.

Input body

Hasil

{"customer": "Pelanggan Demo 01"}

Body: {"message":"Halo Pelanggan Demo 01, salam dari Toko Nusantara!"}; tab Properties berisi p_customer

Tahap 3: tangani error

Sebelum menambah apa pun, jalankan Simulation tahap 2 sekali lagi dengan input {}. Simulation berhenti dengan error dari GS_BuildGreeting: Field 'customer' wajib diisi. Kalau iFlow ini dipanggil dari luar dalam kondisi begini, pemanggil hanya menerima error teknis yang tidak jelas.

Tambahkan Exception Subprocess di dalam Integration Process, beri nama EXS_HandleError. Di dalamnya, antara Error Start dan End:

  • Content Modifier CM_BuildErrorReply:

    • Header CamelHttpResponseCode = 400

    • Header Content-Type = application/json

    • Body tipe Expression: {"error": "Request tidak valid", "detail": "${exception.message}"}. Kali ini harus Expression, karena ${exception.message} perlu diganti dengan isi pesan error saat itu.

  • Akhiri dengan End Message, supaya pemanggil menerima balasan di atas, bukan error mentah.

Exception Subprocess ini padanan TRY ... CATCH di ABAP: logika utama tetap bersih, penanganan error ada di satu tempat.

Uji: Simulation tidak mendukung Exception Subprocess; ia hanya bisa menjalankan alur utama. Jadi untuk tahap ini kita langsung deploy, lalu membuktikannya dengan pesan sungguhan dari Postman di artikel berikutnya: body {} harus dibalas JSON error dengan status 400.

Deploy

Klik Save as Version dengan komentar Hello World 3 stages, lalu Deploy. Tunggu sampai statusnya Started di Monitor → Manage Integration Content.

Jebakan yang saya temui

  • Constant atau Expression? Di Constant, ${...} tidak diproses: teks ${exception.message} akan tampil apa adanya di balasan. Pakai Expression hanya kalau body memang berisi variabel; untuk teks tetap, Constant lebih jelas maksudnya.

  • Body kosong menghasilkan error yang menyesatkan. Versi pertama script saya langsung memanggil new JsonSlurper().parse(reader). Saat Simulation dijalankan tanpa input, error-nya: "Unable to determine the current character... The current character read is '⋮' with an int value of 0", diikuti deretan karakter kosong. Kedengarannya seperti masalah encoding, padahal body-nya memang kosong. Dengan membaca body jadi teks dulu dan mengecek kosong atau tidak, pesan error-nya berubah jadi jelas: Body request kosong.

  • Simulation tidak mendukung Exception Subprocess. Start point dan end point hanya bisa dipasang di satu alur, jadi penanganan error baru bisa diuji setelah deploy, dengan pesan sungguhan.

  • Tombol Simulation abu-abu. Ikon ▶ di toolbar baru aktif setelah simulation start point dan simulation end point dipasang di panah alur. Tanpa keduanya, Simulation tidak bisa dijalankan sama sekali.

  • Exception Subprocess dengan End Message vs Error End. Pilihannya menentukan apakah pemanggil menerima balasan rapi atau status gagal. Aturan lengkapnya kita bahas di Series 5, artikel End Message atau Error End?.

Ringkasan

  • Bangun iFlow bertahap: balasan tetap, logika di Groovy, lalu penanganan error.

  • Baca body dengan message.getBody(java.io.Reader); tambahkan custom header di MPL untuk memudahkan pencarian.

  • Exception Subprocess dengan End Message adalah TRY ... CATCH versi CPI.

  • Uji alur utama dengan Simulation sebelum memanggil dari luar; penanganan error baru bisa dibuktikan dengan pesan sungguhan.

Berikutnya: iFlow sudah Started. Kita panggil dari Postman memakai service key yang dibuat di artikel kedua, lengkap dengan token OAuth dan urusan CSRF.