Saya pikir banyak pengembang Java yang setidaknya sekali menemukan Web-
menggunakan generasi kelas Java
DTO
seperti yang dijelaskan oleh XML Schema
( XSD
) . Jaxb mengatasi ini dengan keras, tidak peduli bagaimana menggunakannya, melalui panggilan xjc
atau wsimport
dari baris perintah, maven atau plugin gradle.
Sangat cepat dan mudah untuk menghasilkan kelas dari skema XSD
. Tapi di sini ada satu masalah - deskripsi yang tersedia di sirkuit asli hilang hampir sepenuhnya!
Dalam praktiknya , karena hanya kelas itu sendiri yang akan memiliki deskripsi Javadoc
, dalam format tetap (di mana Anda tidak dapat memisahkan deskripsi dan fragmen XML
tanpa tetap, misalnya), deskripsi bidang (bidang) sama sekali tidak ada. Dan jika Anda, seperti saya, membutuhkannya juga saat runtime ( runtime
), maka ada masalah .
Anehnya, perlu untuk mengatasi hal ini, tugas itu memakan banyak waktu, dan sebagai hasilnya saya menulis plug-in, yang ingin saya presentasikan dengan harapan dapat menghemat beberapa orang beberapa jam di masa depan.
Sekilas Fitur Jaxb
Jaxb memiliki sejarah panjang dan deskripsi resmi yang baik , termasuk menambahkan perilaku ke kelas yang dihasilkan.
Alat utama untuk memanggil generasi kelas dari baris perintah - xjc juga tidak memiliki jumlah kunci terkecil. Namun, tidak satu pun dari mereka untuk kasus kami.
Tentu saja, Anda tidak bisa tidak menyebutkan -b
, di mana Anda dapat memberikan ikatan Anda sendiri. Dan ini adalah senjata yang sangat kuat, terutama dalam hubungannya dengan beberapa plug-in. Posting blog yang sangat bagus (dalam bahasa Inggris) - Saya sarankan membacanya sebagai pengantar singkat. Tetapi pengikatan untuk sebagian besar terbatas pada nilai-nilai statis dari anthotations yang diberikan atau nama yang diberikan, menunjukkan elemen yang diterapkan. Dalam masalah saya ini tidak membantu.
Plugin Jaxb (XJC)
Sementara saya mencari solusi yang sudah jadi, saya menemukan banyak plugin yang memperluas generasi. Saya kira ulasan mereka berada di luar cakupan posting ini. Yang penting, saya tidak menemukan apa yang benar-benar saya lakukan.
Tetapi kemudian, ketika membaca jawaban dan pertanyaan di http://stackoverflow.com/ , saya menemukan beberapa pertanyaan semacam ini, misalnya:
- Menggunakan JAXB untuk menangani anotasi skema .
- Cara membuat kelas yang dihasilkan berisi Javadoc dari dokumentasi XML Schema
- Bagaimana saya bisa menghasilkan kelas dari mana saya dapat mengambil XML dari sebuah simpul sebagai sebuah String
dan bukan jawaban tunggal yang lengkap, dalam beberapa tahun ini!
Tapi, kembali ke topik peluang, ternyata ada API
untuk menulis plugin! Tingkat rendah, kadang membingungkan, hampir tanpa dokumentasi ... Tetapi saya dapat mengatakan ini sangat maju, yaitu, Anda dapat langsung banyak campur tangan dalam proses apa. Omong-omong, jawabannya sering disebut, untuk banyak kasus non-standar. Yah, saya mencoba menulis sebuah plugin.
Bagi mereka yang tertarik dengan detail proses penulisan plugin mereka, saya dapat merekomendasikan artikel:
Apa yang saya inginkan dan mengapa
Untuk salah satu integrasi kami, pelanggan menyediakan arsip dengan file XSD
, yang menurutnya kami harus membuat model dalam MDM Unidata , yang kami gunakan untuk mengonfigurasi lebih lanjut aturan kualitas.
Saya perhatikan bahwa sistem MDM
itu sendiri adalah milik, tidak mungkin banyak yang mengenalnya, tetapi ini tidak terlalu penting. Intinya adalah bahwa kami harus membuat direktori dan pendaftar dari deskripsi XSD
. Pada saat yang sama, pendaftar memiliki bidang yang menggunakan pengidentifikasi (nama bidang) dan "nama tampilan" - nama yang dapat dimengerti oleh seseorang dalam bahasa Rusia. Analogi sederhana dapat ditarik (dan ini mungkin juga contoh yang berguna untuk aplikasi) dengan RDBMS dalam hal yang kita dapat berasumsi bahwa kita ingin membuat tabel database, tetapi pada saat yang sama memberikan deskripsi ( comment
) untuk setiap kolom untuk digunakan nanti.
Rencana saya adalah ini:
- Menghasilkan kelas
XSD
menggunakan XJC
- Lalu kami mengambil perpustakaan refleksi yang indah dan beralih ke semua objek, secara rekursif menuruni ladang.
Semuanya dengan cepat berhasil untuk nama-nama Latin, yang diambil dari kelas-kelas field
. Tetapi uraian bahasa Rusia yang bisa dibaca manusia itu tidak ada artinya!
Mengedit deskripsi secara manual bukanlah suatu pilihan, karena ada puluhan ribu bidang bersarang.
Upaya pertama adalah menulis parser serupa di Groovy
sendiri, merobek deskripsi dari XSD
. Dan secara umum, itu diterapkan. Tetapi dengan cepat menjadi jelas bahwa ada banyak kasus di mana pemrosesan tambahan diperlukan - panggilan rekursif, dukungan untuk ekstensi XSD
1.1 dalam bentuk restriction
/ extension
(dengan dukungan untuk warisan dan penggantian), berbagai jenis yang menghasilkan bidang kelas seperti <element>
dan <attribute>
, <sequence>
, <choose>
dan banyak hal kecil lainnya. Implementasinya ditumbuhi tambahan, tetapi dia tidak meningkatkan harmoni.
Sebagai hasilnya, saya kembali ke ide untuk menulis plugin xjc-dokumentasi-annotation-plugin , yang saya sajikan kepada Anda, dengan harapan itu akan bermanfaat bagi seseorang kecuali saya!
xjc-dokumentasi-annotation-plugin
Semuanya diletakkan di github: https://github.com/Hubbitus/xjc-documentation-annotation-plugin
Ada instruksi, tes, dan - gradle
terpisah - gradle
dengan contoh penggunaan.
Saya pikir tidak masuk akal untuk menyalin deskripsi di sini dari sana, hanya menunjukkan secara singkat apa yang dilakukannya.
Katakanlah ada fragmen XSD
:
<xs:complexType name="Customer"> <xs:annotation> <xs:documentation></xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="name" type="xs:string"> <xs:annotation> <xs:documentation> </xs:documentation> </xs:annotation> </xs:element> </xs:sequence> </xs:complexType>
Secara default, XJC
menghasilkan kelas XJC
dari itu (getter, setter, dan beberapa detail yang tidak relevan dihilangkan untuk dibaca):
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Customer", propOrder = { "name", "age" }) public class Customer { @XmlElement(required = true) protected String name; @XmlElement(required = true) @XmlSchemaType(name = "positiveInteger") protected BigInteger age; }
Dengan plugin, Anda mendapatkan ( Javadoc
tetap sama, dihilangkan karena kesederhanaan):
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Customer", propOrder = { "name", "age" }) @XsdInfo(name = "", xsdElementPart = "<complexType name=\"Customer\">\n <complexContent>\n <restriction base=\"{http://www.w3.org/2001/XMLSchema}anyType\">\n <sequence>\n <element name=\"name\" type=\"{http://www.w3.org/2001/XMLSchema}string\"/>\n <element name=\"age\" type=\"{http://www.w3.org/2001/XMLSchema}positiveInteger\"/>\n </sequence>\n </restriction>\n </complexContent>\n</complexType>") public class Customer { @XmlElement(required = true) @XsdInfo(name = " ") protected String name; @XmlElement(required = true) @XmlSchemaType(name = "positiveInteger") @XsdInfo(name = "") protected BigInteger age; }
Lihat anotasi @XmlType
ditambahkan.
Maka gunakan ini sesederhana anotasi lainnya:
XsdInfo xsdAnnotation = CadastralBlock.class.getDeclaredAnnotation(XsdInfo.class); System.out.println("XSD description: " + xsdAnnotation.name());
Contoh kerja dalam tes: 1 , 2 .