Bir siparişi onaylamak bu örnekte iki değişikliktir: siparişin durumunu APPROVED yapmak ve ürün stoğunu azaltmak. Bunlardan yalnız biri kalıcılaşırsa veri tutarsız olur. Transaction, bu değişikliklerin birlikte kalıcılaşmasını (commit) veya birlikte geri alınmasını (rollback) sağlar.
Örnek proje bu işlemi approveOrder API’sinden çağırır. Önceki bölümde iptal ettiğiniz ORD-2001 yerine aşağıdaki yeni siparişleri kullanın.
1. Başarılı onayı deneyin
- getStock → COFFEE-01 ile başlangıç stoğunun
8olduğunu doğrulayın. - createOrder üzerinden şu siparişi ekleyin:
{"orderId":"ORD-3001","customerId":"C-100","sku":"COFFEE-01","quantity":3}
- approveOrder → Try it açın. Target → Running project, orderId = ORD-3001, failAfterWrite = false ve Response content type (Accept) → No preference seçip Send kullanın.
200,status: APPROVED,version: 1bekleyin.- Ayrı getOrder ve getStock istekleriyle siparişin onaylandığını ve stoğun
5olduğunu doğrulayın.
Aynı siparişi yeniden onaylamaya çalışın: 409 / ORDER_NOT_NEW gelir, stok tekrar azalmaz.
2. Stok yetmediğinde geri almayı görün
createOrder ile dokuz adetlik ikinci siparişi oluşturun:
{"orderId":"ORD-3002","customerId":"C-100","sku":"COFFEE-01","quantity":9}
approveOrder içinde orderId = ORD-3002, failAfterWrite = false gönderin. 422 / INSUFFICIENT_STOCK bekleyin.

Ardından iki ayrı okuma yapın:
| Okuma | Beklenen değer |
|---|---|
| getOrder → ORD-3002 | status: NEW, version: 0 |
| getStock → COFFEE-01 | available: 5 |
Akış önce siparişi onaylamayı denediği halde son durumda sipariş NEW kalır. Bu, transaction içindeki ilk yazmanın da geri alındığını gösterir. Yalnız hata yanıtını görmek yeterli değildir.

3. İki yazmadan sonra teknik hata üretin
createOrder ile üçüncü siparişi ekleyin:
{"orderId":"ORD-3003","customerId":"C-100","sku":"COFFEE-01","quantity":2}
approveOrder içinde orderId = ORD-3003, failAfterWrite = true gönderin. Bu alan örneğe özel bir hata anahtarıdır: sipariş ve stok güncellendikten sonra bilinçli exception üretir. Yanıt 500 / APPROVAL_FAILED olur.
Ayrı okumalarda ORD-3003 hâlâ NEW / version: 0, kahve stoğu hâlâ 5 olmalıdır. İki yazma da geri alınır. Sonra aynı siparişi failAfterWrite = false ile onaylayın: 200, APPROVED / version: 1 ve stok 3 bekleyin.
Kendi iş akışınıza taşırken bu gösterim parametresini sözleşmeden ve ona bağlı hata dalını akıştan kaldırın.
4. Transaction sınırını inceleyin
Source → approve.camel.yaml → Designer içinde iki akış vardır:
approve-order, API isteğini alır ve alt işlemi çağırır. Teknik hata varsa kullanıcıya güvenli bir hata yanıtı verir.approve-transaction, Transacted ile başlayıp bütün veritabanı değişikliklerini aynı transaction içinde yürütür.
İki akış direct:approveTransaction ile aynı çalışan proje içinde eşzamanlı bağlanır. Bu bağlantı yeni HTTP isteği veya bağımsız mesaj kuyruğu değildir. Teknik hatanın yanıta çevrilmesi transaction’ı yürüten çağrıdan sonra, dıştaki Catch içinde yapılır; hata içeride başarıya çevrilip yarım işin commit edilmesine izin verilmez.
database.camel.yaml içindeki bağlantı ve transaction ayarı:
- beans:
- name: ordersDb
type: '#class:org.apache.commons.dbcp2.BasicDataSource'
properties:
driverClassName: org.postgresql.Driver
url: '{{orders.jdbc.url}}'
username: '{{secret:help-order-lab-db/username}}'
password: '{{secret:help-order-lab-db/password}}'
maxTotal: 4
maxWaitMillis: 5000
validationQuery: SELECT 1
- name: ordersTransactionManager
type: '#class:org.springframework.jdbc.datasource.DataSourceTransactionManager'
properties:
dataSource: '#bean:ordersDb'
- name: ordersRequired
type: '#class:org.apache.camel.spring.spi.SpringTransactionPolicy'
properties:
transactionManager: '#bean:ordersTransactionManager'
propagationBehaviorName: PROPAGATION_REQUIRED
SQL adımları ile transaction manager aynı ordersDb nesnesini kullanır. Sadece aynı sunucu adresini yazmak veya iki ayrı bağlantıya aynı adı vermek işlemleri otomatik birleştirmez. ordersRequired, çağrıda bu yöneticiye ait bir transaction varsa ona katılır; yoksa yeni transaction açar.
Transaction’ın giriş adımı:
- transacted:
ref: ordersRequired
Tam akış dosyası indirilen projededir. Designer içinde Transacted, SQL, Choice ve Rollback adımlarını; Code içinde bütün kapsamı birlikte inceleyebilirsiniz.
5. Aynı anda gelen siparişlerde stoğu koruyun
Örnek siparişi SELECT … FOR UPDATE ile okur. Aynı siparişi onaylamak isteyen başka işlem, ilk transaction bitene kadar o satırın kilidini bekler; sonra yeni durumu görür.
Stok azaltma ve yeterlilik kontrolü tek SQL ifadesindedir:
UPDATE products
SET available = available - :#${exchangeProperty.selectedOrder[quantity]}
WHERE sku = :#${exchangeProperty.selectedOrder[sku]}
AND available >= :#${exchangeProperty.selectedOrder[quantity]}
Bu adım CamelSqlUpdateCount = 0 döndürürse stok ayrılamamıştır. Akış 422 yanıtını hazırlayıp transaction’ı geri alınacak olarak işaretler:
- rollback:
markRollbackOnly: true
Önce stoğu okuyup, daha sonra koşulsuz düşmek eşzamanlı isteklerde fazla satışa yol açabilir. Bu örnekte koşul ve azaltma aynı veritabanı işleminde yapılır. Sipariş satırının kilidi ve transaction bitişi arasına uzun HTTP çağrıları veya kullanıcı bekleyişi koymayın.
6. Geri almanın kapsamadığı işleri ayırın
Bu transaction yalnızca tek veritabanında, aynı bağlantı yöneticisine katılan SQL işlemlerini kapsar. Gönderilmiş e-postayı, başka sistemin kabul ettiği HTTP isteğini veya bağımsız bir kuyruğa bırakılmış mesajı geri çekmez. Message Monitor kayıtları da iş tablolarıyla birlikte silinmez; başarısız denemeyi araştırabilmeniz için ayrı tutulur.
Sipariş onaylandıktan sonra dış sisteme bildirim gerekiyorsa “veritabanı commit oldu, bildirim gönderilemedi” durumunu ayrıca tasarlayın. Örneğin gönderilecek işi aynı transaction içinde bir görev tablosuna kaydedip sonradan teslim etmek bu boşluğu yönetmenin bir yoludur; dış alıcıda tekrar teslimata dayanıklılık yine gerekir. Bu örnek dağıtık transaction veya bildirim teslimi kurmaz.
Sonraki adım: Tekrar denemeye karar verin ve hatanın izini bulun.