
منذ ثلاث سنوات ، أعلنا عن إطلاق CUBA 6 . أصبح هذا الإصدار ثوريًا: بدلاً من ترخيص ملكية مغلقة ، بدأنا في توزيع الإطار بحرية ، بموجب ترخيص Apache 2.0. في ذلك الوقت ، لم يكن بإمكاننا حتى الحصول على فكرة عن كيفية تأثير ذلك على تطوير الإطار على المدى الطويل. بدأ مجتمع CUBA ينمو بشكل كبير ، وصادفنا كل الطرق الممكنة (وأحيانًا المستحيل) لاستخدام الإطار. نعرض الآن CUBA 7 . نأمل أن يجعل هذا الإصدار التطوير أكثر سهولة ومتعة لجميع أفراد المجتمع: من المبتدئين الذين تعرفوا للتو على CUBA و Java ، إلى المطورين ذوي الخبرة الذين لديهم أكثر من مشروع مكتمل على مستوى شركة كبيرة.
أدوات التطوير
يعود الفضل في نجاح CUBA إلى CUBA Studio . سهلت بيئة التطوير هذه بشكل كبير تنفيذ المهام النموذجية التي يتم تنفيذها في كل مشروع Java ، مما أدى إلى تقليل تكويناتها البسيطة في المصممين المرئيين. لا تحتاج إلى معرفة كل سمات التعليق التوضيحي لـ Persistence API أو بناء جملة Gradle أو التفاصيل الدقيقة لتكوين Spring لتطوير تطبيق CRUD كامل وغني بالميزات - تتولى CUBA Studio إنشاء الشفرة النموذجية.

كان Studio عبارة عن تطبيق ويب منفصل ، مما تسبب في عدد من القيود الهامة:
- أولاً ، لم يكن Studio عبارة عن IDE كامل ، لذلك كان على المطورين التبديل بين Studio و IntelliJ IDEA أو Eclipse من أجل تطوير منطق العمل وفي نفس الوقت استخدام التنقل المريح وإكمال التعليمات البرمجية وغيرها من الأشياء الضرورية التي كانت مزعجة إلى حد ما.
- ثانياً ، بنيت كل هذه البساطة السحرية على قدر كبير من العمل الذي أنفقناه على كتابة خوارزميات لتحليل وتوليد شفرة المصدر. إن تنفيذ وظائف أكثر تطوراً يعني الانتقال إلى تطوير بيئة تطوير متكاملة متكاملة - مهمة طموحة للغاية بالنسبة لنا.
قررنا الاعتماد على عملاق آخر للتغلب على هذه القيود وبناء الاستوديو على أساس IntelliJ IDEA. يمكنك الآن تثبيت Studio كتطبيق مستقل (IntelliJ IDEA Bundle) ، وكبرنامج إضافي لـ IDEA.

وهذا يعطينا فرصا جديدة:
- دعم لغات JVM الأخرى (وفوق كل ذلك Kotlin)
- متفوقة الساخنة نشر
- سهولة التنقل على مستوى المشروع
- تلميحات أكثر ذكاء ومولدات الشفرة
حاليًا ، نعمل على تطوير إصدار جديد من Studio - ننقل وظائف من الإصدار القديم ونضيف أشياء جديدة باستخدام وظيفة النظام الأساسي IntelliJ. في المستقبل القريب - ترجمة المحررين المعنيين بـ CUBA إلى مكونات IntelliJ وتحسين التنقل من خلال رمز المشروع.
تحديث كومة التكنولوجيا
حسب التقاليد ، تم تحديث الحزمة التقنية في قلب CUBA إلى الإصدارات الجديدة: Java 8/11 ، Vaadin 8 ، Spring 5.
افتراضيًا ، تستخدم المشروعات الجديدة Java 8 ، ولكن يمكنك تحديد إصدار Java بإضافة التعليمة البرمجية التالية إلى ملف build.gradle:
subprojects { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 }
كانت هناك مشكلة كبيرة بشكل خاص تتمثل في الترقية إلى Vaadin 8 ، حيث تغيرت واجهة برمجة تطبيقات ربط البيانات كثيرًا. لحسن الحظ ، تحمي CUBA المطورين من المكونات الداخلية لـ Vaadin ، وتلفهم في واجهة برمجة التطبيقات الخاصة بها. قام فريق CUBA بعمل رائع في تحديث المكونات الداخلية دون تغيير واجهة برمجة تطبيقات CUBA. هذا يعني أن التوافق يتم الحفاظ عليه تمامًا ، ويمكنك الاستفادة من جميع الميزات الجديدة لبرنامج Vaadin 8 فور انتقال المشروع إلى CUBA 7 ، دون القيام بأي إعادة بيع.
قائمة كاملة من التبعيات المحدثة متوفرة في قائمة التغيير .
شاشات جديدة API
قد يطلق على هذا القسم "واجهة برمجة التطبيقات للشاشة الأولى" ، لأن CUBA لم يكن لها واجهة برمجة تطبيقات للشاشة تم الإعلان عنها رسميًا في وحدة عميل الويب. حدث هذا تاريخيا ، بما في ذلك بسبب بعض الافتراضات التي نشأت في المرحلة الأولية:
- أسلوب موجه بشكل تعريفي - يجب الإعلان عن كل شيء يمكن وصفه بشكل تعريفي في واصف الشاشة ، وليس في رمز وحدة التحكم.
- قدمت الشاشات القياسية (المتصفح والمحرر) وظيفة عامة معينة ، ولم تكن هناك حاجة لتغييرها.

بحلول الوقت الذي انضم فيه أول ألف عضو إلى مجتمعنا ، أدركنا عدد المتطلبات المختلفة التي يتم وضعها على شاشات CRUD "القياسية". وكانت كل هذه المتطلبات أبعد من الوظيفة الأولية. ومع ذلك ، يمكننا تلبية طلبات تنفيذ سلوك الشاشة غير النموذجي لفترة طويلة دون تغيير واجهة برمجة التطبيقات - وذلك بفضل مبدأ معماري آخر تم وضعه في المرحلة الأولية: فتح الوراثة. في الحقيقة ، تعني Open الوراثة أنه يمكنك إعادة كتابة أي طريقة عامة أو محمية للفئة الرئيسية لتخصيص سلوكها وفقًا لاحتياجاتك. قد يبدو هذا بمثابة دواء معجزة ، لكن في الواقع لا يمكنك الاعتماد عليه حتى في المدى القصير. ماذا لو تم إعادة تسمية أو إلغاء أو إلغاء استخدام طريقة تم تجاوزها في الإصدارات المستقبلية للإطار؟
لذلك استجابةً لمتطلبات المجتمع المتزايدة ، قررنا تقديم واجهة برمجة تطبيقات جديدة للشاشة. توفر واجهة برمجة التطبيقات هذه (بدون أي سحر خفي) ، نقاط امتداد مرنة وسهلة الاستخدام مضمونة بعدم التغيير لفترة طويلة.
إعلان الشاشة
في CUBA 7 ، يكون إعلان الشاشات بسيطًا للغاية:
@UiController("new-screen")
يوضح المثال أعلاه أن معرف الشاشة معرّف بشكل صريح أعلى إعلان فئة وحدة التحكم مباشرةً. بمعنى آخر ، يطابق معرف الشاشة وفئة جهاز التحكم الآن بعضهما البعض بطريقة فريدة. لذلك ، لدينا بعض الأخبار الجيدة: الآن يمكنك الوصول بأمان إلى الشاشات مباشرة حسب نوع وحدة التحكم:
@Inject private ScreenBuilders screenBuilders; @Subscribe private void onBeforeClose(BeforeCloseEvent event) { screenBuilders.screen(this) .withScreenClass(SomeConfirmationScreen.class) .build() .show(); }
يصبح واصف الشاشة جزءًا اختياريًا من الشاشة. يمكن إنشاء واجهة المستخدم برمجياً أو التصريح بها على أنها واصف شاشة xml ، والتي يتم تعريفها بواسطة التعليق التوضيحي @UiDescriptor
على فئة وحدة التحكم. هذا يجعل من السهل قراءة وفهم أدوات التحكم والترميز - هذا النهج مشابه جدًا للمنهج المستخدم في تطوير Android.
في السابق ، كان من الضروري أيضًا تسجيل مقبض شاشة في ملف web-screens.xml وتعيين معرف له. في CUBA 7 ، تم حفظ هذا الملف لأغراض التوافق ، ولكن الطريقة الجديدة لإنشاء الشاشات لا تتطلب هذا التسجيل.
دورة حياة الشاشة
يقدم API الجديد أحداث دورة حياة الشاشة بسيطة وواضحة:
- التهيئة
- AfterInit
- BeforeShow
- Aftershow
- BeforeClose
- AfterClose
يمكنك الاشتراك في جميع الأحداث في CUBA 7 على النحو التالي:
@UiController("new-screen") public class NewScreen extends Screen { @Subscribe private void onInit(InitEvent event) { } @Subscribe private void onBeforeShow(BeforeShowEvent event) { } }
مقارنةً بالطريقة القديمة ، تُظهر واجهة برمجة التطبيقات الجديدة أننا لا نتداخل مع أساليب ربط تسمى ضمنيًا عند التهيئة ، ولكننا نعرّف بوضوح منطق معالجة حدث دورة حياة محدد ومحدّد.
التعامل مع الحدث والمندوبين الوظيفيين
في القسم السابق ، تعلمنا كيفية الاشتراك في أحداث دورة الحياة ، ولكن ماذا عن المكونات الأخرى؟ هل لا يزال من الضروري صب جميع المستمعين الضروريين في نفس الكومة عند تهيئة الشاشة ، في طريقة init () ، كما كانت في الإصدارات 6.x؟ واجهة برمجة التطبيقات الجديدة متناسقة إلى حد ما ، بحيث يمكنك الاشتراك في أحداث أخرى بنفس طريقة الأحداث على الشاشة.
النظر في مثال بسيط مع عنصرين واجهة المستخدم: زر وحقل لعرض مبلغ من المال في عملة معينة ؛ سيبدو واصف XML بالشكل التالي:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd" caption="msg://caption" messagesPack="com.company.demo.web"> <layout> <hbox spacing="true"> <currencyField id="currencyField" currency="$" currencyLabelPosition="LEFT"/> <button id="calcPriceBtn" caption="Calculate Price"/> </hbox> </layout> </window>
عند النقر فوق الزر ، ندعو الخدمة من الواجهة الخلفية ، والتي تُرجع رقماً ، نكتبه في حقل المبلغ. يجب أن يغير هذا الحقل النمط اعتمادًا على قيمة السعر.
@UiController("demo_MyFirstScreen") @UiDescriptor("my-first-screen.xml") public class MyFirstScreen extends Screen { @Inject private PricingService pricingService; @Inject private CurrencyField<BigDecimal> currencyField; @Subscribe("calcPriceBtn") private void onCalcPriceBtnClick(Button.ClickEvent event) { currencyField.setValue(pricingService.calculatePrice()); } @Subscribe("currencyField") private void onPriceChange (HasValue.ValueChangeEvent<BigDecimal> event) { currencyField.setStyleName(getStyleNameByPrice(event.getValue())); } private String getStyleNameByPrice(BigDecimal price) { ... } }
في المثال أعلاه ، نرى معالجين للأحداث: واحد يسمى عند الضغط على الزر ، والآخر يتم تشغيله عندما يغير حقل العملة قيمته - كل شيء بسيط.
الآن تخيل أننا بحاجة إلى التحقق من السعر والتأكد من أن قيمته إيجابية. يمكن القيام بذلك "الجبين" - إضافة أداة التحقق أثناء تهيئة الشاشة:
@UiController("demo_MyFirstScreen") @UiDescriptor("my-first-screen.xml") public class MyFirstScreen extends Screen { @Inject private CurrencyField<BigDecimal> currencyField; @Subscribe private void onInit(InitEvent event) { currencyField.addValidator(value -> { if (value.compareTo(BigDecimal.ZERO) <= 0) throw new ValidationException("Price should be greater than zero"); }); } }
في التطبيقات الحقيقية ، بعد مرور بعض الوقت ، ستكون طريقة التهيئة عبارة عن فوضى من أدوات التهيئة والمصدّقين والمستمعين وما إلى ذلك. لحل هذه المشكلة ، لدى CUBA تعليق توضيحي مفيد @Install
. دعونا نرى كيف يمكن أن تساعد في حالتنا:
@UiController("demo_MyFirstScreen") @UiDescriptor("my-first-screen.xml") public class MyFirstScreen extends Screen { @Inject private CurrencyField<BigDecimal> currencyField; @Install(to = "currencyField", subject = "validator") private void currencyFieldValidator(BigDecimal value) { if (value.compareTo(BigDecimal.ZERO) <= 0) throw new ValidationException("Price should be greater than zero"); } }
في الواقع ، نقوم بتفويض منطق التحقق من صحة حقل العملة إلى طريقة currencyFieldValidator في الشاشة. قد يبدو هذا الأمر معقدًا قليلاً للوهلة الأولى ، ولكن من المفاجئ أن المطورين اعتادوا بسرعة على هذه الطريقة لإضافة وظائف وبدأوا في استخدامها على الفور.
بناة الشاشة ، والإخطارات ، ومربعات الحوار

يحتوي CUBA 7 على مجموعة من المكونات المفيدة مع واجهة برمجة تطبيقات ملائمة:
- يجمع ScreenBuilders بين المصانع المتقنة لإنشاء شاشات قياسية للعرض والتحرير ، وكذلك الشاشات المخصصة. يوضح المثال التالي كيف يمكنك فتح شاشة من أخرى. لاحظ أن الأسلوب build () يُرجع فورًا شاشة النوع المرغوب دون الحاجة إلى ممثلون:
CurrencyConversions currencyConversions = screenBuilders.screen(this) .withScreenClass(CurrencyConversions.class) .withLaunchMode(OpenMode.DIALOG) .build(); currencyConversions.setBaseCurrency(Currency.EUR); currencyConversions.show();
- يوفر مكون الشاشة مستوى أقل من التجريد لإنشاء شاشات وعرضها ، على عكس واجهة برمجة تطبيقات ScreenBuilders . كما يوفر الوصول إلى المعلومات حول جميع الشاشات المفتوحة في تطبيق CUBA الخاص بك ( شاشات # getOpenedScreens ) ، إذا كنت بحاجة فجأة إلى استعراضها جميعًا في دورة واحدة.
- توفر مكونات الإخطارات ومربعات الحوار واجهة برمجة تطبيقات ملائمة وذاتية التوثيق. فيما يلي مثال على إنشاء وعرض مربع حوار وإخطار:
dialogs.createOptionDialog() .withCaption("My first dialog") .withMessage("Would you like to thank CUBA team?") .withActions( new DialogAction(DialogAction.Type.YES).withHandler(e -> notifications.create() .withCaption("Thank you!") .withDescription("We appreciate all community members") .withPosition(Notifications.Position.MIDDLE_CENTER) .withHideDelayMs(3000) .show()), new DialogAction(DialogAction.Type.CANCEL) ) .show();
ربط البيانات
توفر CUBA تطويرًا سريعًا للغاية لواجهة المستخدم للمكتب الخلفي ، ليس فقط مع أدوات التطوير المرئي المتقدمة ونظام توليد الشفرات القوي ، ولكن أيضًا بمجموعتها الغنية من المكونات المتوفرة مباشرة من الصندوق. تحتاج هذه المكونات فقط إلى معرفة البيانات التي تعمل معها ، وسيتم تنفيذ الباقي تلقائيًا. على سبيل المثال ، القوائم المنسدلة ، والتقويمات ، والجداول التي تحتوي على عمليات CRUD المضمنة ، وما إلى ذلك.
قبل الإصدار 7 ، تم تنفيذ ربط البيانات من خلال مصدر بيانات ما يسمى - الكائنات التي التفاف واحد أو أكثر من الكيانات لربطها التفاعلي للمكونات. لقد نجح هذا النهج بشكل جيد للغاية ، ولكن من حيث التنفيذ ، كان متراصة. عادة ما تكون البنية المتجانسة مشكلة في التكوين ، لذلك في CUBA 7 تم تقسيم هذا الحصوه الضخم إلى ثلاثة مكونات للعمل مع البيانات:
- أداة تحميل البيانات هي مزود بيانات لحاويات البيانات. لا يقوم الجرافة بتخزين البيانات ، بل يقوم ببساطة بتمرير جميع معلمات الاستعلام الضرورية إلى مستودع البيانات ويضع البيانات الناتجة في حاويات البيانات.
- تقوم حاوية البيانات بحفظ البيانات التي تم تحميلها (كيان أو أكثر) وتزويدهم بمكونات البيانات: يتم نقل جميع التغييرات في هذه الكيانات إلى المكونات المقابلة ، والعكس بالعكس ، ستؤدي جميع التغييرات في المكونات إلى تغييرات مقابلة في الكيانات التي تقع في حاوية البيانات.
- Datacontext (سياق البيانات) هو فصل يتتبع التغييرات ويخزن كل الكيانات التي تم تغييرها. يتم تمييز الكيانات التي تتم مراقبتها على أنها متسخة كلما تغيرت سماتها ، ويحفظ DataContext المثيلات المتسخة على البرامج الوسيطة عند استدعاء طريقة الالتزام () الخاصة به.
وبالتالي ، هناك مرونة في العمل مع البيانات. مثال مصطنع: يمكن للمحمّل تحديد البيانات في واجهة المستخدم من RDBMS ، ويمكن للسياق حفظ التغييرات في خدمة REST.
في الإصدار CUBA 6.x ، ستحتاج إلى كتابة مصدر البيانات الخاص بك لهذا الأمر ، والذي يمكنه العمل مع كل من RDBMS و REST. في CUBA 7 ، يمكنك أن تأخذ محملًا قياسيًا يمكنه العمل مع قاعدة البيانات وكتابة تطبيق السياق الخاص به فقط للعمل مع REST.
يمكن تعريف مكونات العمل مع البيانات في واصفات الشاشة أو إنشاؤها برمجيًا باستخدام مصنع متخصص - DataComponents.
آخر
Uff ... يتم وصف الأجزاء الأكثر أهمية من واجهة برمجة التطبيقات الجديدة التي تظهر على الشاشة ، لذلك دعونا ندرج بإيجاز الوظائف المهمة الأخرى على مستوى عميل الويب:
- تاريخ URL والتنقل . تحل هذه الوظيفة مشكلة SPA شائعة جدًا - سلوك الزر الخلفي في متصفح الويب ليس صحيحًا دائمًا. يوفر الآن طريقة سهلة لتعيين طرق لشاشات التطبيقات ويسمح لواجهة برمجة التطبيقات بعرض الحالة الحالية للشاشة في عنوان URL.
- نموذج بدلاً من FieldGroup . FieldGroup هو مكون لعرض وتغيير حقول كيان واحد. يعرض واجهة المستخدم للحقل في وقت التشغيل. بمعنى آخر ، إذا كان لدى الكيان حقل تاريخ ، فسيتم عرضه كحقل تاريخ . ومع ذلك ، إذا كنت ترغب في العمل مع هذا الحقل برمجيًا ، فستحتاج إلى إدخاله في وحدة تحكم الشاشة وإلقاءه يدويًا على النوع الصحيح ( DateField في مثالنا ). إذا قمنا في وقت لاحق بتغيير نوع الحقل إلى حقل آخر ، فسيتم تعطيل تطبيقنا في وقت التشغيل. يحل النموذج هذه المشكلة بإعلان نوع الحقل بشكل صريح. يمكن العثور على مزيد من المعلومات حول المكون هنا .
- يتم دمج مكونات جافا سكريبت التابعة لجهة خارجية بشكل كبير ؛ اقرأ الوثائق الخاصة بتضمين مكونات جافا سكريبت المخصصة في تطبيق CUBA.
- يمكن الآن تعريف سمات HTML / CSS بسهولة مباشرةً من واصف شاشة xml أو تعيينها برمجيًا. يمكن الاطلاع على مزيد من المعلومات هنا .
ميزات جديدة للوحدة الخلفية
تبين أن القسم السابق على واجهة برمجة التطبيقات الجديدة التي تظهر على الشاشة هو أكثر مما كنت أتوقع ، لذلك في هذا القسم سأكون مختصراً.
حدث تغيير الكيان
حدث Entity Changed هو حدث في تطبيق Spring يطلق النار عندما يدخل كيان إلى مخزن بيانات ، ويوضع فعليًا ، ويبعُد خطوة واحدة عن الالتزام. عند معالجة هذا الحدث ، يمكنك تكوين عمليات فحص إضافية (على سبيل المثال ، التحقق من توفر البضائع في المستودع قبل تأكيد الطلب) وتغيير البيانات (على سبيل المثال ، إعادة حساب الإجماليات) مباشرة قبل أن تكون مرئية لمعاملات أخرى (بالطبع ، إذا كان لديك مستوى قراءة العزلة التي ارتكبت). قد يكون هذا الحدث أيضًا الفرصة الأخيرة لإجهاض المعاملة عن طريق طرح استثناء ، والذي قد يكون مفيدًا في بعض الحالات الصعبة.
هناك أيضًا طريقة للتعامل مع حدث تغيير الكيان مباشرةً بعد الالتزام.
يمكنك إلقاء نظرة على مثال في هذا الفصل من الوثائق .
مدير بيانات المعاملات
عند تطوير تطبيق ما ، عادة ما نعمل مع كيانات منفصلة - تلك التي ليست في سياق أي معاملة. ومع ذلك ، فإن العمل مع الكيانات المنفصلة ليس ممكنًا دائمًا ، خاصةً عندما تحتاج إلى الامتثال الكامل لمتطلبات ACID - وهذا هو الحال عندما يمكنك استخدام مدير بيانات المعاملات. إنه يشبه إلى حد كبير المدير العادي ، لكنه يختلف في الجوانب التالية:
- يمكنه الانضمام إلى معاملة موجودة (يتم استدعاؤها في سياق هذه المعاملة) أو إنشاء المعاملة الخاصة به.
- لا يحتوي على طريقة التزام ، ولكن هناك طريقة حفظ لا تلتزم على الفور ، لكنها تنتظر الالتزام بالمعاملة الحالية.
هنا مثال على استخدامه.
رد الفعل JPA
أخيرًا ، تدعم CUBA 7 عمليات الاسترجاعات JPA. من أجل عدم تكرار المواد المعروفة لما يمكن أن تستخدمه عمليات الاسترجاعات هذه ، أترك رابطًا هنا. في هذه المادة ، يتم الكشف عن موضوع عمليات الاسترجاعات بالكامل.
ماذا عن التوافق؟

سؤال عادل لأي إصدار رئيسي ، خاصة عندما يكون هناك الكثير من التغييرات الهامة! قمنا بتطوير كل هذه الميزات وواجهات برمجة التطبيقات الجديدة مع التوافق مع الإصدارات السابقة:
- يتم دعم واجهة برمجة التطبيقات القديمة في CUBA 7 ويتم تنفيذها من خلال واجهة المستخدم الجديدة تحت غطاء محرك السيارة :)
- كما قدمنا محولات لربط البيانات من خلال واجهة برمجة التطبيقات القديمة. ستعمل هذه المحولات بشكل مثالي للشاشات التي تم إنشاؤها وفقًا للمخطط القديم.
والخبر السار هو أن عملية الترحيل من الإصدار 6 إلى 7 يجب أن تكون بسيطة للغاية.
استنتاج
في ختام المراجعة الفنية ، أود أن أشير إلى أن هناك ابتكارات مهمة أخرى ، لا سيما في مجال الترخيص:
- تتم الآن إزالة حد الكيان 10 لـ Studio
- أصبحت الوظائف الإضافية لإعداد التقارير و BPM والمخططات والخرائط والبحث عن النص الكامل مجانية ومفتوحة المصدر.
- يضيف الإصدار التجاري من Studio إلى الراحة من خلال مساعدة المصممين المرئيين للكيانات والشاشات والقوائم وعناصر النظام الأساسي الأخرى ، وتركز النسخة المجانية على العمل باستخدام الكود.
- يرجى ملاحظة أنه بالنسبة للإصدارات 6.x والإصدارات السابقة ، تظل شروط ترخيص النظام الأساسي و Studio كما هي!
أخيرًا ، اسمحوا لي مرة أخرى أن أشكر المجتمع على دعمهم وتعليقاتهم. أتمنى أن تحب الإصدار 7! المعلومات الكاملة متاحة تقليديا على سجل التغيير الرسمي.