Jaxb (XJC) generasi kelas dari XML Schema (XSD) dengan deskripsi kelas dan lapangan dalam bentuk anotasi. Plugin XJC

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:


  1. Menggunakan JAXB untuk menangani anotasi skema .
  2. Cara membuat kelas yang dihasilkan berisi Javadoc dari dokumentasi XML Schema
  3. 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:


  1. Menghasilkan kelas XSD menggunakan XJC
  2. 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):


 /** *  * * <p>Java class for Customer complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * &lt;complexType name="Customer"&gt; * &lt;complexContent&gt; * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt; * &lt;sequence&gt; * &lt;element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/&gt; * &lt;element name="age" type="{http://www.w3.org/2001/XMLSchema}positiveInteger"/&gt; * &lt;/sequence&gt; * &lt;/restriction&gt; * &lt;/complexContent&gt; * &lt;/complexType&gt; * </pre> * * */ @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 .

Source: https://habr.com/ru/post/id437914/


All Articles