Apa yang baru di CUBA 7
Tiga tahun yang lalu kami mengumumkan versi utama kedua dari kerangka tersebut. CUBA 6 adalah versi pengubah permainan - lisensi diubah dari proprietary menjadi Apache 2.0. Hari-hari itu kami bahkan tidak bisa menebak di mana ia akan membawa kerangka kerja dalam jangka panjang. Komunitas CUBA mulai tumbuh secara eksponensial, jadi kami telah belajar banyak cara yang mungkin (dan kadang-kadang tidak mungkin) tentang bagaimana pengembang menggunakan kerangka kerja. Sekarang kami dengan senang hati mengumumkan CUBA 7 , yang, kami harap, akan membuat pengembangan lebih koheren dan menyenangkan bagi semua anggota masyarakat dari mereka yang baru memulai perjalanan mereka di CUBA dan Jawa kepada pengembang perusahaan yang terampil dan pakar Jawa.

Jelas, sebagian besar dari kesuksesan CUBA kami berutang kepada CUBA Studio . Ini sangat menyederhanakan rutinitas perusahaan Java yang terlalu padat, di banyak tempat menghentikannya untuk membuat konfigurasi sepele pada desainer visual: tidak perlu tahu Persistence API atau Gradle atau bahkan Spring untuk mengembangkan aplikasi CRUD yang lengkap dan kaya fitur - Studio akan melakukannya untukmu
Studio adalah aplikasi web yang terpisah dan fakta ini menyebabkan beberapa batasan signifikan:
- Pertama-tama, Studio bukan IDE yang berfitur lengkap, sehingga pengembang harus beralih antara Studio dan IntelliJ IDEA atau Eclipse untuk mengembangkan logika bisnis dan mendapat manfaat dari navigasi yang mudah, penyelesaian kode dan hal-hal penting lainnya, yang menjengkelkan.
- Kedua, kesederhanaan ajaib ini dibangun di atas parsing dan generasi kode sumber besar. Meningkatkan kemampuan pembuatan kode berarti bergerak menuju pengembangan IDE berfitur lengkap - suatu usaha yang terlalu ambisius.
Kami memutuskan untuk bersandar di bahu raksasa lain untuk mengatasi keterbatasan ini. Studio digabung menjadi IntelliJ IDEA oleh JetBrains. Sekarang Anda dapat menginstalnya sebagai plugin untuk IntelliJ IDEA Anda atau unduh sebagai bundel mandiri terpisah.

Ini membuka cakrawala baru:
- Dukungan bahasa JVM lainnya (dan Kotlin di tempat pertama)
- Peningkatan penyebaran panas
- Navigasi intuitif melalui seluruh proyek
- Petunjuk yang lebih cerdas dan generator kode
Saat ini Studio baru sedang dalam pengembangan aktif: kami porting fitur dari versi lama. Rencana jangka pendek juga untuk mengimplementasikan kembali desainer berbasis web menggunakan UI IntelliJ asli dan meningkatkan pengalaman navigasi proyek.
Upgrade tumpukan
Secara tradisional, tumpukan yang mendasarinya juga telah ditingkatkan secara besar-besaran, misalnya Java 8/11, Vaadin 8, Spring 5.

Secara default, proyek baru menggunakan Java 8, tetapi Anda dapat menentukan versi Java dengan menambahkan klausa berikut ke file build.gradle:
subprojects { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 }
Memutakhirkan ke Vaadin 8 adalah tantangan besar karena perubahan besar pada API pengikatan data Vaadin. Untungnya, CUBA mengabstraksi pengembang dari Vaadin internal dengan membungkusnya ke dalam lapisan APInya sendiri. Tim CUBA melakukan pekerjaan luar biasa dalam mengimplementasikan internal menjaga APInya sendiri tidak tersentuh. Ini berarti kompatibilitas sepenuhnya disimpan dan Anda dapat mengambil manfaat dari Vaadin 8 segera setelah memigrasi proyek ke CUBA 7 tanpa refactoring apa pun.
Daftar lengkap dependensi yang diperbarui tersedia di catatan rilis resmi.
API Layar Baru
Bagian ini juga dapat dinamai "API layar pertama" - karena CUBA tidak pernah memiliki API yang dinyatakan secara resmi di tingkat klien web. Itu berasal dari sejarah kerangka kerja dan asumsi-asumsi tertentu yang dibuat pada tahap pertama:
- Pendekatan deklaratif-sentris - segala sesuatu yang dapat dideskripsikan secara deklaratif, harus dinyatakan dalam deskriptor layar dan tidak diberi kode pada pengontrolnya
- Layar standar (Browser dan Editor) menyediakan fungsionalitas umum yang konkret dan tidak perlu memodifikasinya
Sejak seribu anggota pertama bergabung dengan komunitas kami, kami menyadari betapa beragamnya persyaratan untuk layar CRUD "standar" - jauh melampaui serangkaian fitur yang awalnya dirancang. Namun demikian, untuk waktu yang lama kami dapat menangani permintaan untuk perilaku khusus bahkan tanpa lapisan API - berkat asumsi tahap pertama lainnya - Open Inheritance. Warisan Terbuka yang Efektif berarti bahwa Anda dapat mengganti metode umum atau terlindung dari kelas dasar untuk menyesuaikan perilakunya dengan apa yang Anda butuhkan. Ini mungkin terdengar seperti obat untuk semua penyakit, tetapi pada kenyataannya itu tidak memberi Anda bahkan kontrak jangka pendek: bagaimana jika metode yang diganti akan diganti namanya, dihapus atau tidak pernah digunakan dalam versi kerangka kerja yang akan datang?

Jadi, sebagai tanggapan terhadap meningkatnya permintaan dari komunitas, kami memutuskan untuk memperkenalkan API layar baru. API menyediakan titik ekstensi yang jelas dan jangka panjang tanpa sihir deklaratif tersembunyi, fleksibel, dan sangat mudah digunakan.
Deklarasi layar
Dalam deklarasi layar CUBA 7 sangat sederhana:
@UiController("new-screen") // screen id public class NewScreen extends Screen { }
Dari contoh di atas kita dapat melihat bahwa pengenal layar didefinisikan secara eksplisit tepat di atas kelas controller. Dengan kata lain, id layar dan kelas pengontrol sekarang secara unik berhubungan satu sama lain. Jadi, kabar baiknya, sekarang layar dapat diatasi secara langsung oleh kelas pengontrolnya dengan cara yang aman:
@Inject private ScreenBuilders screenBuilders; @Subscribe private void onBeforeClose(BeforeCloseEvent event) { screenBuilders.screen(this) .withScreenClass(SomeConfirmationScreen.class) .build() .show(); }
Deskriptor layar menjadi bagian pelengkap alih-alih wajib. Layout dapat dibuat secara terprogram atau dideklarasikan sebagai deskriptor layar xml, yang ditentukan oleh penjelasan @UiDescriptor pada kelas controller. Ini membuat pengontrol dan tata letak lebih mudah dibaca dan dipahami - pendekatan ini sangat mirip dengan yang digunakan dalam pengembangan Android.
Sebelumnya, itu juga diperlukan untuk mendaftarkan deskriptor layar di file web-screens.xml dan menetapkan pengenal untuk itu. Dalam CUBA 7 file ini disimpan karena alasan kompatibilitas, namun membuat layar dengan cara baru tidak memerlukan pendaftaran tersebut.
Layar siklus hidup
API baru memperkenalkan acara siklus hidup layar yang jelas dan jelas:
- Init
- Setelah itu
- Di depan
- Entah bagaimana
- Sebelum ditutup
- Setelah ditutup
Semua acara terkait layar di CUBA 7 dapat berlangganan sebagai berikut:
@UiController("new-screen") public class NewScreen extends Screen { @Subscribe private void onInit(InitEvent event) { } @Subscribe private void onBeforeShow(BeforeShowEvent event) { } }
Membandingkan API baru dengan pendekatan lama, Anda dapat melihat bahwa kami tidak mengesampingkan metode kait, yang secara tidak jelas disebut dalam hierarki kelas induk, tetapi mendefinisikan logika dalam poin yang sudah ditentukan sebelumnya dari siklus hidup layar.
Penanganan Acara dan Delegasi Fungsional
Pada bagian sebelumnya, kami belajar cara berlangganan acara siklus hidup, jadi, bagaimana dengan komponen lain? Haruskah kita masih menyebarkan semua pendengar yang diperlukan pada inisialisasi layar seperti dalam versi 6.x? API baru sangat seragam, jadi berlangganan ke acara lain benar-benar mirip dengan siklus hidup.
Mari kita ambil contoh sederhana dengan dua elemen UI: tombol dan bidang mata uang, sehingga deskriptor xmlnya terlihat seperti:
<?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>
Dengan mengklik tombol, kami memanggil layanan middleware mengembalikan nomor, yang masuk ke bidang mata uang. Bidang mata uang harus berubah gaya tergantung pada nilai harga.
@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) { BigDecimal price = pricingService.calculatePrice(); currencyField.setStyleName(getStyleNameByPrice(price)); } private String getStyleNameByPrice(BigDecimal price) { ... } }
Dalam contoh di atas kita dapat melihat dua pengendali acara: satu dipanggil ketika tombol diklik dan satu lagi dieksekusi ketika bidang mata uang mengubah nilainya - sesederhana itu.
Sekarang, mari kita bayangkan bahwa kita perlu memvalidasi harga kita dan memeriksa apakah nilainya positif. Cara mudah adalah menambahkan validator saat inisialisasi layar:
@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"); }); } }
Dalam aplikasi dunia nyata, titik masuk layar biasanya dipenuhi dengan inisialisasi elemen layar semacam ini. Untuk mengatasi masalah ini, CUBA memberikan penjelasan berguna @Install
. Mari kita lihat bagaimana ini dapat membantu dalam kasus kami:
@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"); } }
Bahkan kami mendelegasikan logika validasi dari bidang mata uang kami ke metode currencyFieldValidator di layar kami. Ini mungkin terlihat agak rumit, namun, pengembang mengadopsi fitur ini secara mengejutkan cepat.
Pembuat Layar / Pemberitahuan / Dialog

CUBA 7 juga memperkenalkan serangkaian komponen yang berguna dengan API yang lancar:
ScreenBuilders menggabungkan pabrik yang fasih untuk menghasilkan pencarian standar, editor dan layar khusus. Contoh di bawah ini menunjukkan bagaimana Anda dapat membuka satu layar dari yang lain. Perhatikan, bahwa metode build () mengembalikan instance layar dari tipe yang tepat, tanpa perlu membuangnya dengan tidak aman.
CurrencyConversions currencyConversions = screenBuilders.screen (ini)
.withScreenClass (CurrencyConversions.class)
.withLaunchMode (OpenMode.DIALOG)
.build ();
currencyConversions.setBaseCurrency (Currency.EUR);
currencyConversions.show ();
Komponen layar memberikan abstraksi tingkat yang lebih rendah untuk membuat dan menampilkan layar daripada ScreenBuilders . Ini juga menyediakan akses ke informasi tentang semua layar yang dibuka di aplikasi CUBA Anda ( Layar # getOpenedScreens ) jika Anda perlu mengulanginya.
Komponen Notifikasi dan Dialog sama-sama memperkenalkan antarmuka self-explanatory yang nyaman. Berikut adalah contoh untuk membuat dan menampilkan dialog dan pemberitahuan:
dialogs.createOptionDialog ()
.withCaption ("Dialog pertamaku")
.withMessage ("Apakah Anda ingin berterima kasih kepada tim CUBA?")
.withActions (
DialogAction baru (DialogAction.Type.YES) .withHandler (e ->
notification.create ()
.withCaption ("Terima kasih!")
.withDescription ("Kami menghargai semua anggota komunitas")
.withPosition (Notifications.Position.MIDDLE_CENTER)
.withHideDelayMs (3000)
.show ()),
DialogAction baru (DialogAction.Type.CANCEL)
)
.show ();
Pengikatan data
CUBA memungkinkan pengembangan UI backoffice yang sangat cepat tidak hanya dengan menyediakan alat visual canggih dengan kemampuan generasi kode yang luas, tetapi juga oleh serangkaian komponen yang sadar data yang tersedia langsung di luar kotak. Komponen semacam itu hanya perlu mengetahui data apa yang mereka kerjakan dan sisanya akan dikelola secara otomatis, misalnya daftar pencarian, bidang pemilih, berbagai kisi dengan operasi CRUD dan sebagainya.
Sebelum versi 7 pengikatan data dilaksanakan melalui apa yang disebut sumber data - objek yang membungkus satu entitas atau kumpulan entitas untuk secara reaktif mengikatnya dengan komponen yang sadar data. Pendekatan ini bekerja dengan sangat baik, namun, implementasi-bijaksana itu adalah monolit. Arsitektur monolitik biasanya menyebabkan masalah dengan kustomisasi, sehingga dalam CUBA 7 batu padat ini dibagi menjadi 3 komponen data:
- Pemuat data adalah penyedia data untuk wadah data. Pemuat data tidak menyimpan data, mereka hanya meneruskan semua parameter kueri yang diperlukan ke penyimpanan data dan umpan data wadah dengan set data yang dihasilkan.
- Wadah data menjaga data yang dimuat (entitas tunggal atau sejumlah entitas) dan memberikannya kepada komponen yang sadar data secara reaktif: semua perubahan entitas yang dibungkus terkena komponen UI yang sesuai dan sebaliknya, semua perubahan dalam komponen UI akan mengarah pada perubahan terkait dalam wadah datanya.
- Konteks data adalah manajer modifikasi data yang kuat yang melacak perubahan dan melakukan semua entitas yang dimodifikasi. Suatu entitas dapat digabungkan ke dalam konteks data, sehingga akan memberikan salinan entitas asli dengan perbedaan satu-satunya, tetapi sangat penting: semua modifikasi dari entitas yang dihasilkan dan semua entitas yang dirujuk (termasuk koleksi) akan dilacak, disimpan, dan berkomitmen sesuai.
Komponen data dapat dideklarasikan dalam deskriptor layar atau instantiated secara terprogram menggunakan pabrik khusus - DataComponents .
Lain-lain
Ufff, bagian terpenting dari layar API baru dijelaskan, jadi izinkan saya mendaftar secara singkat fitur-fitur penting lainnya di tingkat klien web:
- Riwayat URL dan Navigasi . Fitur ini memecahkan masalah SPA yang sangat umum dengan tombol "kembali" di peramban web, menyediakan cara mudah untuk menetapkan rute ke layar aplikasi dan memungkinkan API untuk mencerminkan keadaan layar saat ini di URL-nya.
- Bentuk bukan FieldGroup . FieldGroup adalah komponen yang sadar data untuk menampilkan dan memodifikasi bidang satu entitas. Itu menyimpulkan UI aktual yang ditunjukkan untuk bidang dalam runtime. Dengan kata lain, jika Anda memiliki bidang Tanggal di entitas Anda itu akan ditampilkan sebagai DateField . Namun, jika Anda ingin mengoperasikan bidang ini secara terprogram, Anda harus menyuntikkan bidang ini ke pengontrol layar dan melemparkannya ke jenis yang tepat secara manual ( DateField dalam contoh kami ). Kemudian kami mengubah jenis bidang kami ke yang lain dan aplikasi kami macet saat runtime ... Formulir mengatasi masalah ini dengan deklarasi jenis bidang eksplisit. Temukan informasi lebih lanjut tentang komponen baru ini di sini .
- Integrasi komponen JavaScript pihak ketiga sangat disederhanakan, ikuti dokumentasi untuk menyematkan komponen JavaScript khusus ke dalam aplikasi CUBA.
- Atribut HTML / CSS sekarang dapat dengan mudah didefinisikan langsung dari deskriptor layar xml atau diatur secara terprogram. Temukan informasi lebih lanjut di sini .
Fitur Middleware
Blok sebelumnya tentang API layar baru lebih besar dari yang saya harapkan, jadi di bagian ini saya akan mencoba untuk menjadi rapi!
Entitas Berubah Peristiwa
Entity Changed Event adalah acara aplikasi Musim Semi yang dipecat ketika entitas Anda menuju penyimpanan data, dimasukkan secara fisik dan dalam satu inci komitmen. Di sini Anda dapat memberikan beberapa cek tambahan (mis. Memeriksa ketersediaan produk dalam stok sebelum mengonfirmasi pesanan) dan memodifikasinya (mis., Menghitung ulang total) tepat sebelum itu akan terlihat untuk transaksi lain (tentu saja dengan tingkat isolasi yang sudah dilakukan). Anda juga dapat menggunakan acara ini sebagai kesempatan terakhir untuk menghentikan transaksi yang tidak dilakukan dengan melemparkan pengecualian - yang mungkin berguna dalam beberapa kasus sudut.
Ada juga cara untuk menangkap Peristiwa Berubah Entitas tepat setelah komit terjadi.
Ikuti bab dokumentasi ini untuk melihat contoh.
Manajer Data Transaksional
Saat mengembangkan aplikasi, kami biasanya beroperasi dengan entitas terpisah - yang tidak dikelola oleh transaksi apa pun. Namun, bekerja dengan entitas terpisah tidak selalu mungkin, terutama ketika mencoba memenuhi persyaratan ACID - ini adalah kasus ketika Anda dapat menggunakan manajer data transaksional. Itu terlihat sangat mirip dengan manajer data biasa, tetapi berbeda dalam aspek-aspek berikut:
- Itu dapat bergabung dengan transaksi yang sudah ada (dalam kasus itu disebut dalam konteks transaksional) atau membuat transaksi sendiri.
- Tidak memiliki metode komit , tetapi ada metode save, yang tidak mengarah pada komit langsung, tetapi menunggu sampai transaksi terlampir akan dilakukan.
Temukan contoh menggunakannya di sini .
Callback Siklus Hidup JPA
Akhirnya, CUBA 7 mendukung panggilan balik siklus hidup JPA. Untuk tidak mereplikasi informasi yang ditulis dengan baik tentang apa yang dapat digunakan untuk callback ini, izinkan saya berbagi saja tautan ini , yang sepenuhnya mencakup subjek.
Bagaimana dengan kompatibilitas?

Sebuah pertanyaan yang wajar untuk rilis besar apa pun, terutama ketika ada begitu banyak perubahan yang tampaknya menghancurkan! Kami telah merancang semua fitur dan API baru ini dengan mengingat kompatibilitas ke belakang:
- API layar lama didukung dalam CUBA 7 dan diimplementasikan melalui yang baru di bawah tenda :)
- Kami juga telah menyediakan adaptor untuk pengikatan data lama, yang tetap berfungsi untuk layar kuno.
Jadi, kabar baiknya, jalur migrasi dari versi 6 ke 7 seharusnya cukup mudah.
Kesimpulan
Kesimpulan tinjauan teknis ini saya ingin menyebutkan bahwa ada inovasi penting lainnya, terutama dengan lisensi:
- Batas 10 entitas untuk Studio sekarang hilang
- Pelaporan, BPM, Bagan, dan Peta serta add-on pencarian teks lengkap sekarang gratis dan open source.
- Versi komersial Studio menghadirkan kenyamanan pengembangan ekstra dengan desainer visual untuk entitas, layar, menu, dan elemen platform lainnya, sementara versi gratisnya berfokus pada bekerja dengan kode
- Harap jangan mengatakan bahwa untuk 6.x dan versi yang lebih lama dari persyaratan lisensi Platform dan Studio tetap sama!
Akhirnya, izinkan saya berterima kasih kepada anggota masyarakat lagi atas semua dukungan dan umpan baliknya. Saya harap Anda akan menyukai versi 7! Daftar lengkap perubahan secara tradisional tersedia di catatan rilis .