Bu bölümde yeni bir sipariş oluşturacak, aynı isteği tekrar gönderecek ve güncelleme sırasında eski veriyi ezmeyi önleyeceksiniz. Örnek projenin çalışıyor olması gerekir.
1. Yeni sipariş ekleyin
API design → createOrder → Try it açın. Target → Running project, Request content type → application/json ve Response content type (Accept) → No preference seçin. Gövdeyi şöyle hazırlayıp Send kullanın:
{"orderId":"ORD-2001","customerId":"C-100","sku":"TEA-01","quantity":2}
201 ile birlikte kaydedilen nesne gelir. status alanı NEW, version alanı 0 olur. İstek adları orderId/customerId, bu örneğin veritabanı ve yanıt adları order_id/customer_id biçimindedir; SQL adımı bu eşlemeyi yapar.

getOrder ile ORD-2001 okuyarak kaydın bulunduğunu ayrıca kontrol edin. getStock → TEA-01 hâlâ 20 göstermelidir; sipariş oluşturmak stok ayırmaz.
2. Verinin yazma adımına nasıl geldiğini inceleyin
Source → write.camel.yaml → Designer içinde create-order akışını açın. İlk adımlar JSON metnini nesneye dönüştürür, ilk isteği saklar ve iş kimliğini izlemeye hazırlar:
- unmarshal:
json:
library: Jackson
- setProperty:
name: orderRequest
simple: '${body}'
- setProperty:
name: lunex.monitor.applicationId
simple: '${body[orderId]}'
- to:
uri: 'sql:INSERT INTO orders(order_id, customer_id, sku, quantity) VALUES (:#orderId, :#customerId, :#sku, :#quantity) ON CONFLICT (order_id) DO NOTHING'
parameters:
dataSource: '#ordersDb'
:#quantity gibi adlar, bu adımda body içindeki alanlardan alınır. Sayı 2, string "2" ve boş değer aynı şey değildir. API sözleşmesi miktarı pozitif tam sayı olarak sınırlar; veritabanında da miktar ve ürün ilişkisi kontrol edilir.
CamelSqlUpdateCount, yazma işleminin kaç satırı değiştirdiğini bildirir. Akış bu değeri bir sonraki SQL işleminden önce kontrol eder; sonraki işlem header’ı değiştirebilir. Ardından kaydı yeniden SELECT ile okuyup JSON yanıtını üretir. SQL adımından sonra body’nin hâlâ ilk istek olduğunu varsaymaz.
3. Aynı siparişi ikinci kez gönderin
Aynı gövdeyi yeniden gönderin. 409 / ORDER_EXISTS bekleyin. Miktarı 9 yapıp aynı orderId ile tekrar gönderdiğinizde de mevcut kayıt değiştirilmez; getOrder miktarı 2 gösterir.
Burada korumayı veritabanındaki benzersiz anahtar ve ON CONFLICT (order_id) DO NOTHING sağlar. Önce SELECT yapıp “yoksa INSERT” yapmak, eşzamanlı iki isteğin arasındaki yarışı tek başına önlemez.
Bu davranış aynı siparişin ikinci kez yaratılmasını engeller; ilk başarılı HTTP yanıtını saklayıp tekrar döndüren tam bir idempotency düzeni değildir. İstemci 409 aldığında mevcut kaydı okuyup kendi gönderdiği iş bilgileriyle karşılaştırmalıdır. Zaman aşımında yeni bir sipariş numarası üretip yeniden göndermek çift sipariş yaratabilir.
4. Bir siparişi eski veriyi ezmeden iptal edin
Önce getOrder → ORD-2001 ile NEW / version: 0 gördüğünüzü doğrulayın. Sonra cancelOrder → Try it içinde orderId = ORD-2001 ve aşağıdaki gövdeyi gönderin:
{"expectedVersion":0}
Başarılı yanıt 200, yeni durum CANCELLED, yeni sürüm 1 olur. Akışın güncellemesi şöyledir:
UPDATE orders
SET status = 'CANCELLED', version = version + 1
WHERE order_id = :#${header.orderId}
AND version = :#expectedVersion
AND status = 'NEW'
“Ben okuduğum sürümü değiştiriyorum” koşulu, arada başka bir işlem kaydı güncellediyse bu isteğin onu sessizce ezmesini önler. Buna iyimser kilitleme denir. WHERE hem doğru kaydı hem beklenen durumu ve sürümü sınırlar.
Aynı expectedVersion: 0 ile yeniden deneyin: 409 / ORDER_NOT_CHANGED gelir. Akış sıfır satır değişmesini başarı saymaz. Kayıt bulunmamış, sürüm değişmiş veya durum artık NEW olmayabilir; getOrder ile okuyup karar verin. Sürümü otomatik artırarak körlemesine tekrar denemeyin.
Bu örnek yalnızca yeni siparişleri iptal eder. Onaylanmış siparişi iptal edip stoğu geri koymak ayrı bir iş akışıdır; yalnız status değerini değiştirerek stok iadesi yapmış olmazsınız.
5. Hatalı girdiyi de deneyin
| Deneme | Beklenen sonuç | Kontrol |
|---|---|---|
Yeni kimlik ve quantity: 2 | 201 | Kaydı ayrı bir okuma isteğiyle bulun |
| Aynı kimliği tekrar gönderme | 409 / ORDER_EXISTS | İlk kaydın miktarı değişmemiş olmalı |
quantity: 0 | 400, minimum kuralı | Veritabanına yeni kayıt yazılmamalı |
quantity: "2" | 400, type kuralı | JSON string yerine sayı gönderin |
Eksik customerId | 400, required kuralı | Eksik alanı tamamlayın |
| Eski sürümle iptal | 409 / ORDER_NOT_CHANGED | Son durum ve sürümü yeniden okuyun |
400 sonucundaki Request contract checks, girdinin neden reddedildiğini gösterir. Şemadan geçen bir isteğin iş açısından mutlaka geçerli olduğu anlamına gelmez; stok yeterliliği bir sonraki bölümde çalışma anında kontrol edilir.
Sonraki adım: Sipariş ve stoğu aynı transaction içinde değiştirin.