الوحدة في هذا المقال: Integration Flow Helper
تعبيرات Camel Simple في SAP CPI: الترويسات والخصائص و${…} بالأمثلة
كيف تعمل تعبيرات Camel Simple في SAP CPI: ${header.x} و${property.x} و${in.body} والتواريخ، وترتيب Content Modifier، وشروط Router، والأخطاء التي تُرجع قيمة فارغة.

تُكتب كل قيمة ديناميكية تقريبًا في iFlow على SAP Cloud Integration (SAP CPI) بلغة التعبيرات Simple الخاصة بـ Apache Camel: ترويسة في عنوان المستقبِل، وخاصية في Content Modifier، وتاريخ في اسم ملف، وشرط في Router. الصيغة قصيرة، ${…}، ومن السهل أن تخطئ فيها خطأً بسيطًا دون أن تلاحظ.
يتناول هذا المقال التعبيرات التي ستستخدمها كل يوم، والترتيب الذي يقيّمها به Content Modifier، والفرق بين الترويسات وخصائص التبادل (exchange properties)، والأخطاء التي تجعل التعبير يُرجع قيمة فارغة بصمت.
ما هو تعبير Simple في SAP CPI
يشغّل SAP Integration Suite كل iFlow على Apache Camel. وعند تنفيذ خطوة ما، يستبدل Camel كل ${…} في الحقل بقيمة من الرسالة الحالية: ترويسة، أو خاصية تبادل، أو جسم الرسالة، أو دالة مدمجة مثل التاريخ الحالي. أما النص المحيط بالتعبير فيبقى كما هو، فيصبح Order-${header.orderId}.xml على سبيل المثال Order-4711.xml.
يمكنك كتابة تعبيرات Simple في قيم Content Modifier من النوع Expression وفي جسم الرسالة، وفي حقلي العنوان والاستعلام في كثير من محوّلات المستقبِل، وفي شروط Router وFilter من النوع Non-XML، وفي حقول مثل عنوان البريد أو اسم ملف SFTP. تبدو المعاملات الخارجية (externalized parameters) مشابهة لكنها مختلفة: فـ {{receiverHost}} يُستبدل مرة واحدة عند نشر الـ iFlow، بينما يُقيَّم ${…} مع كل رسالة.
التعبيرات التي ستستخدمها كل يوم
تكفي حفنة من التعبيرات لمعظم iFlows، ويمكن مزجها بحرية مع النص العادي. فجسم الرسالة في Content Modifier، مثلًا، يستطيع بناء مستند XML كامل من الترويسات والخصائص والدوال:
<Order>
<Id>${property.orderId}</Id>
<Customer>${header.customerId}</Customer>
<ReceivedOn>${date:now:yyyy-MM-dd}</ReceivedOn>
<Flow>${camelId}</Flow>
<MessageLog>${property.SAP_MessageProcessingLogID}</MessageLog>
</Order>| التعبير | ما يُرجعه |
|---|---|
${header.orderId} | ترويسة الرسالة orderId |
${property.orderId} | خاصية التبادل orderId (ويقبل Camel أيضًا ${exchangeProperty.orderId}) |
${in.body} أو ${body} | جسم الرسالة الحالي كنص |
${date:now:yyyy-MM-dd} | تاريخ اليوم بنمط التاريخ المحدد في Java |
${camelId} | اسم تدفق التكامل (integration flow) الجاري تشغيله |
${property.SAP_MessageProcessingLogID} | معرّف سجل معالجة الرسالة الحالية |
${header.CamelHttpResponseCode} | رمز الحالة الذي أعاده آخر استدعاء HTTP |
كيف يقيّم Content Modifier الترويسات والخصائص وجسم الرسالة
يمرّ Content Modifier على تبويباته بترتيب ثابت: جدول Message Header أولًا، ثم جدول Exchange Property، ثم Message Body. وداخل كل جدول تُنفَّذ الصفوف من الأعلى إلى الأسفل.
هذا الترتيب يحدد ما يستطيع التعبير رؤيته. فصف الخاصية يستطيع قراءة ترويسة أُنشئت قبله في Content Modifier نفسه، وجسم الرسالة يستطيع استخدام الاثنين. أما صف الترويسة فلا يستطيع قراءة خاصية ينشئها Content Modifier نفسه، لأن الخاصية لا تكون موجودة بعد عند تقييم الترويسة، فيقرأ قيمة فارغة بدلًا منها. وإذا احتجت إلى ذلك، فاضبط الخاصية في Content Modifier سابق، أو انقل القيمة إلى جدول الترويسات الذي يسبقها.
- نوع المصدر Expression: القيمة تعبير Simple، مثل
${date:now:yyyyMMdd}-${header.orderId}. - نوع المصدر Header أو Property: ينسخ ترويسة أو خاصية أخرى باسمها، دون
${…}حوله. - نوع المصدر XPath: يقرأ قيمة من جسم XML (انظر مقال XPath المرتبط أدناه).
- أنواع المصدر Constant وLocal Variable وGlobal Variable وNumber Range تغطي القيم الثابتة والقيم المخزّنة.
الترويسات أم خصائص التبادل: أيهما تستخدم
الترويسة تنتقل مع الرسالة. تستطيع محوّلات المستقبِل تمرير الترويسات إلى النظام الذي تستدعيه، والترويسات تعبر استدعاء ProcessDirect إلى iFlow آخر. أما خاصية التبادل فتبقى داخل exchange الخاص بالـ iFlow الحالي، ولا تُرسَل إلى أي مستقبِل من تلقاء نفسها.
تفصيلتان تسببان معظم المفاجآت. أسماء الترويسات لا تميّز بين الأحرف الكبيرة والصغيرة، فـ ${header.OrderID} و${header.orderid} يقرآن الترويسة نفسها. أما أسماء خصائص التبادل فتميّز بينها، فـ ${property.OrderID} و${property.orderId} خاصيتان مختلفتان، وقد لا تكون الثانية موجودة أصلًا.
- استخدم خاصية للقيم التي يحتاجها هذا الـ iFlow وحده: المعرّفات والعدّادات والأعلام والنسخ المحفوظة من الحمولة.
- استخدم ترويسة للقيم التي يجب أن يستلمها محوّل أو الـ iFlow التالي، واحذف الترويسات التي لا ينبغي أن تغادر المستأجر (tenant).
- أبقِ القيم الكبيرة خارج الترويسات: فهي تنتقل مع كل استدعاء.
شروط Simple في Router وFilter
في مسار Router أو في Filter من النوع Non-XML، يكون الشرط تعبير Simple يُقارَن بقيمة. والعوامل المعتادة هي = و!= و> و>= و< و<= وcontains وin وregex، وتُربط بـ and أو or. وتوضع القيم النصية بين علامتي اقتباس مفردتين:
${header.orderType} = 'EXPRESS'
${property.amount} > 1000 and ${header.country} in 'DE,AT,CH'
${header.CamelHttpResponseCode} != '200'إذا كانت الترويسة أو الخاصية في الشرط غير موجودة، يصبح الشرط ببساطة false وتسلك الرسالة مسارًا آخر، وكثيرًا ما يكون المسار الافتراضي. ويبيّن مقال الترويسات والخصائص غير المعروفة كيف تكتشف ذلك قبل أن يصل إلى بيئة الإنتاج.
كيف يساعدك Kitegra
Kitegra إضافة للمتصفح تعمل في مصمم SAP Integration Suite. اكتب ${ أو $ في أحد حقول المصمم، فتعرض الأسماء المناسبة لتلك النقطة من الـ iFlow: الترويسات والخصائص المضبوطة في Content Modifier وفي سكربتات Groovy وJavaScript وفي مواضع أخرى من الـ iFlow، والترويسات والتعبيرات القياسية في SAP وCamel، ومعاملات {{…}}، والمتغيرات، وأسماء Data Store. والاسم الذي يُضبط في بعض المسارات فقط يُعلَّم بعبارة «يُعيَّن في بعض المسارات فقط».
وتنبّهك لوحة الفحص (lint) فيها إلى ${ غير مغلق، والمسافات الزائدة داخل التعبير، والترويسات أو الخصائص التي لا يضبطها شيء في الـ iFlow. ولصفوف XPath، يمنحك نموذج الحمولة اقتراحات للمسارات أيضًا، كما يشرح مقال XPath. ولا تحفظ الإضافة محتوى أي iFlow ولا تنشره ولا تعدّله أبدًا، ولا يتغير المستأجر إلا عندما تنقر أحد أربعة إجراءات محددة بالاسم يمكن إيقافها.
لترى القيم التي تُنتجها تعبيراتك فعلًا، تتبّع الرسالة خطوة بخطوة واقرأ الترويسات والخصائص قبل كل خطوة.
بلا حساب تعمل الإضافة على 5 iFlows لكل وحدة. وتغطي خطة Free حتى 50، وخطة Starter حتى 100، وخطة Pro حتى 300. وفي خطط الفرق يحصل كل عضو على Pro، مع 300 iFlow لكل وحدة في خطة Startup Team، وبلا حد في خطتي Growth Team وScale Team. وطوال فترة إطلاق Kitegra، تتاح كل الأدوات لكل من سجّل الدخول، حتى على خطة Free. قارن بين الخطط.
جرّبها في الـ iFlow التالي
تعرّف على ما يفعله Kitegra في مصمم SAP Integration Suite، أو اطّلع عليه مع بقية وحدات Kitegra.
الأسئلة الشائعة
ما الفرق بين ${header.x} و${property.x} في SAP CPI؟
يقرأ ${header.x} ترويسة رسالة، وهي تنتقل مع الرسالة ويمكن أن تصل إلى المستقبِلات وإلى iFlows أخرى. أما ${property.x} فيقرأ خاصية تبادل، وهي تبقى داخل الـ iFlow الحالي.
هل تميّز أسماء الترويسات والخصائص بين الأحرف الكبيرة والصغيرة؟
أسماء الترويسات لا تميّز: فـ ${header.OrderID} و${header.orderid} يقرآن الترويسة نفسها. أما أسماء خصائص التبادل فتميّز، لذا فإن ${property.OrderID} و${property.orderId} خاصيتان مختلفتان.
لماذا تكون الترويسة فارغة عندما أضبطها من خاصية في Content Modifier نفسه؟
يقيّم Content Modifier جدول الترويسات أولًا، ثم جدول الخصائص، ثم جسم الرسالة. فلا تستطيع الترويسة قراءة خاصية أُنشئت في الخطوة نفسها؛ اضبط الخاصية في خطوة سابقة.
كيف أضع تاريخ اليوم في اسم ملف أو في حقل؟
استخدم ${date:now:yyyy-MM-dd} مع أي نمط تاريخ في Java، مثل ${date:now:yyyyMMddHHmmss} للحصول على طابع زمني.
هل {{parameter}} تعبير Simple؟
لا. يشير {{…}} إلى معامل خارجي يُستبدل مرة واحدة عند نشر الـ iFlow. أما ${…} فيقيّمه Camel مع كل رسالة.
ماذا يحدث إذا ذكر التعبير ترويسة غير موجودة؟
يُرجع قيمة فارغة دون أي خطأ، فتظهر المشكلة لاحقًا في صورة مسار خاطئ أو حقل فارغ. ويكتشفها فحص lint أو خطوة حماية في وقت أبكر.