Các đặc tính mới của JiBX 1.2 mà bạn sẽ tìm hiểu về nó trong hướng dẫn này — Phần 1 của một loạt bài viết có hai phần — cho phép bạn bắt đầu từ mã Java và dễ dàng tạo ra các định nghĩa l
Trang 1JiBX 1.2, Phần 1: Từ mã Java thành lược đồ XML
Cải thiện chất lượng lược đồ bằng phép biến đổi tùy chỉnh các mô hình dữ liệu Java thành tài liệu XML và từ tài liệu XML
Dennis Sosnoski, Nhà tư vấn, Sosnoski Software Solutions, Inc
Tóm tắt: Các định nghĩa lược đồ XML là cơ sở cho nhiều kiểu trao đổi dữ liệu,
bao gồm hầu hết các dạng dịch vụ web Nhưng lược đồ XML là một tiêu chuẩn phức tạp và hầu hết các công cụ để tạo và sửa đổi các định nghĩa lược đồ không đủ mạnh mẽ hay dễ sử dụng như các công cụ để làm việc với mã Java™ Các đặc tính mới của JiBX 1.2 mà bạn sẽ tìm hiểu về nó trong hướng dẫn này — Phần 1 của một loạt bài viết có hai phần — cho phép bạn bắt đầu từ mã Java và dễ dàng tạo ra các định nghĩa lược đồ có chất lượng khớp với các cấu trúc dữ liệu của bạn Sau
đó bạn có thể sử dụng trực tiếp các lược đồ này, dù bạn có sử dụng liên kết dữ liệu JiBX hay không
Trước khi bạn bắt đầu
Về hướng dẫn này
JiBX là một công cụ để liên kết dữ liệu XML với các đối tượng Java Liên kết dữ liệu JiBX đã được biết đến từ lâu như là cách tiếp cận nhanh nhất và linh hoạt nhất
để liên kết mã Java tới XML Nhưng sự phức tạp của các định nghĩa liên kết JiBX
và sự hỗ trợ còn hạn chế của nó với các định nghĩa lược đồ XML đang được sử dụng ngày càng rộng rãi hơn đã làm cho những người dùng thất vọng nhiều lần May mắn thay, phiên bản 1.2 của JiBX đã tiến một bước dài theo hướng loại bỏ những vấn đề này Trong hướng dẫn này, bạn sẽ tìm hiểu về việc sử dụng các đặc tính mới của JiBX 1.2 để tạo ra các định nghĩa lược đồ XML một cách dễ dàng từ
mã Java hiện có và để đọc và viết các tài liệu khớp với các định nghĩa lược đồ đã tạo ra — hoàn toàn không cần phải đi vào các chi tiết của các định nghĩa liên kết của JiBX Phần 2 trình bày nửa còn lại của vấn đề: bắt đầu từ các định nghĩa lược
đồ XML và tạo mã Java
Mục tiêu
Hướng dẫn này chỉ dẫn cho bạn về quá trình sử dụng JiBX để tạo ra các định nghĩa lược đồ XML từ mã Java Đầu tiên, bạn sẽ thấy làm thế nào để bắt đầu với một mô hình dữ liệu Java đơn giản và tạo ra một lược đồ mặc định khớp với mô hình đó Trên cơ sở đó, bạn sẽ tìm hiểu cách làm thế nào để bạn có thể dễ dàng áp dụng một loạt các tuỳ chỉnh để kiểm soát các giá trị thực tế đã sử dụng trong các lớp Java của bạn và cách làm thế nào để truy cập chúng, cho dù chúng là cần phải
Trang 2có (required) hay tùy chọn (optional); để kiểm soát các tên và các không gian tên (namespaces) được sử dụng trong XML và thậm chí để kiểm soát cấu trúc của các định nghĩa lược đồ đã tạo ra Đồng thời, bạn sẽ thấy JiBX tăng thêm giá trị cho các lược đồ bạn đã tạo ra như thế nào khi sử dụng những công sức đầu tư của bạn vào Javadocs để làm tài liệu về định nghĩa lược đồ một cách tự động Sau khi đọc hướng dẫn này và thực hiện các ví dụ được cung cấp, bạn sẽ có khả năng sử dụng JiBX để tạo ra các định nghĩa lược đồ XML có chất lượng từ các lớp cấu trúc dữ liệu Java riêng của bạn
Các điều kiện cần có trước
Để hiểu được hướng dẫn này, bạn ít nhất nên có các kiến thức cơ bản về cả mã Java và XML Bạn không cần phải hiểu biết chi tiết về các định nghĩa lược đồ XML nhưng sự quen thuộc với các lược đồ sẽ giúp bạn hiểu các ví dụ tốt hơn
Các yêu cầu hệ thống
Để chạy các ví dụ này, bạn cần phải cài đặt:
Cả hai:
o Sun's JDK 1.5.0_09 (hoặc mới hơn)
o Bộ dụng cụ của nhà phát triển của IBM cho công nghệ Java 1.5.0 SR3
Một phiên bản mới đây của công cụ xây dựng Apache Ant
Các hướng dẫn tải về và cài đặt JiBX có trong hướng dẫn này
Trang 3Bắt đầu
Trong phần này, bạn sẽ có được cái nhìn tổng quan về JiBX và bạn sẽ cài đặt JiBX
và mã lệnh mẫu của hướng dẫn này
Giới thiệu JiBX
JiBX là một trong nhiều công cụ dùng để chuyển đổi giữa các cấu trúc dữ liệu Java và các tài liệu XML (Tài nguyên) Cái làm nên sự khác biệt của JiBX so với những công cụ khác là các đặc tính linh hoạt và hiệu năng Hiệu năng của JiBX luôn được đánh giá ở vị trí cao nhất trong lĩnh vực này, vượt quá hai lần hoặc hơn nữa so với hiệu năng của các công cụ phổ biến khác (như JAXB 2.0 chẳng hạn) JiBX cũng linh hoạt hơn hầu hết tất cả các công cụ Java-XML khác, khi sử dụng các định nghĩa liên kết để tách các cấu trúc Java khỏi biểu diễn XML sao cho từng cái có thể được thay đổi độc lập với cái kia
Với bản phát hành 1.2, JiBX bổ sung thêm các đặc tính hỗ trợ các định nghĩa lược
đồ XML Bạn có thể sử dụng các công cụ kèm theo trong bản phát hành JiBX để tạo ra một định nghĩa lược đồ khớp với mã Java của bạn hoặc để tạo mã Java khớp với định nghĩa lược đồ của bạn Dù bằng cách nào, bạn cũng nhận được một định nghĩa liên kết để cho phép bạn sử dụng JiBX để chuyển đổi giữa các mã Java và các tài liệu XML khớp với định nghĩa lược đồ Trong hướng dẫn này, bạn sẽ thấy cách làm thế nào để áp dụng kiểu tạo mã đầu tiên: từ mã Java sinh ra định nghĩa lược đồ
Cài đặt JiBX
Bạn cần phải cài đặt JiBX trước khi tiếp tục thực hiện hướng dẫn này Hãy tải về bản ZIP phân phối mới nhất 1.2.x và giải nén nó vào một chỗ thuận tiện trên hệ thống của bạn Xong việc, bạn sẽ nhận được một thư mục có tên là jibx, trong đó
có chứa tất cả các tệp JiBX JAR, tài liệu hướng dẫn, các ví dụ và thậm chí cả mã nguồn
Cài đặt mã nguồn các ví dụ của hướng dẫn này
Bây giờ hãy tải về các mã mẫu, của hướng dẫn này, cũng được cung cấp dưới dạng một tệp tin ZIP Cách dễ nhất để cài đặt nó trên hệ thống của bạn là giải nén tệp tin ZIP vào thư mục gốc của bản phân phối JiBX của bạn (hoặc trên
Windows®, sao chép thư mục dwcode1 từ bên trong tệp tin ZIP này vào thư mục gốc bản phân phối JiBX của bạn) Điều này sẽ tạo ra một thư mục con dwcode1 trong thư mục jibx, với các tệp tin ví dụ (bao gồm cả các tệp tin build.xml,
custom1.xml và các tệp tin khác) bên trong thư mục con dwcode1 đó
Trang 4Mã mẫu bao gồm một tệp tin xây dựng Ant Apache để tự động hoá cho chạy các công cụ JiBX và xử lý các bước khác có trong các ví dụ Nếu bạn cài đặt các mã mẫu trực tiếp vào thư mục cài đặt của JiBX, công cụ xây dựng (build) có thể truy cập các tệp JiBX JAR mà không cần thêm bất kỳ cấu hình nào Nếu bạn cài đặt các mã mẫu ở nơi khác, bạn vẫn có thể sử dụng công cụ xây dựng Ant Trong trường hợp này, bạn chỉ cần thiết lập một biến môi trường JIBX_HOME chỉ rõ đường dẫn đến bản cài đặt JiBX của bạn Ngoài ra, một cách khác là bạn có thể chỉnh sửa các tệp tin build.xml-bên trong thư mục mã mẫu và bỏ dấu chú thích ở đầu các dòng phía trên cùng của tệp tin, nơi trực tiếp thiết lập các thuộc tính jibx-home
Trang 5Tạo ra liên kết mặc định và lược đồ từ mã Java
Cách sử dụng cho trường hợp không phải Java 5
Mã ví dụ của hướng dẫn này sử dụng các đặc tính về bảng kê (enum) và sưu tập có định kiểu của Java 5, nhưng bản thân JiBX hoàn toàn tương thích với các phiên bản Java cũ hơn Môi trường chạy JiBX tiêu chuẩn làm việc được với các JVM phiên bản 1.3 và mới hơn và cũng có thể được xây dựng để tương thích với J2ME Hầu hết các thành phần khác của JiBX bao gồm cả BindGen, có thể chạy được trên các bản JVM phiên bản 1.4.1 và mới hơn Tài liệu BindGen trong bản tải về JiBX có một ví dụ chỉ rõ cách tùy chỉnh như thế nào để có thể cung cấp cho
BindGen các thay thế tương đương của các sưu tập có định kiểu nếu bạn sử dụng
mã Java cũ hơn phiên bản Java 5
Thật dễ dàng để tạo ra một định nghĩa liên kết JiBX và định nghĩa lược đồ XML tương ứng từ mã Java Bạn sẽ tìm hiểu cách làm thế nào trong phần này
Giới thiệu về mã ví dụ Java
Như một ví dụ, tôi sẽ bắt đầu với mã Java cho một tập các lớp theo phong cách bean (các trường dữ liệu là riêng-private và các phương thức set và các phương thức get là chung-public) dùng để mô tả một đơn hàng từ một cửa hàng trực tuyến Listing 1 hiển thị một phiên bản mã rút gọn, bỏ qua hầu hết các phương thức get/set Toàn bộ mã mẫu hoàn chỉnh nằm trong thư mục src các mã mẫu
Listing 1 Mã Java cơ sở
Trang 6{
private long orderNumber;
private Customer customer;
/** Billing address information */
private Address billTo;
private Shipping shipping;
/** Shipping address information If missing, the billing address is also used as the
shipping address */
private Address shipTo;
private List<Item> items;
/** Date order was placed with server */
private Date orderDate;
/** Date order was shipped This will be <code>null</code> if the order has not yet shipped */
private Date shipDate;
private Float total;
Trang 7public long getOrderNumber() { return orderNumber;
private String lastName;
/** Middle name(s), if any */ private List<String> middleNames;
}
Trang 8/** First line of street information (required) */
private String street1;
/** Second line of street information (optional) */
private String street2;
private String city;
/** State abbreviation (required for the U.S and Canada, optional otherwise) */ private String state;
/** Postal code (required for the U.S and Canada, optional otherwise) */
private String postCode;
/** Country name (optional, U.S assumed if not supplied) */
private String country;
}
Trang 9private String id;
/** Text description of item */
private String description;
/** Number of units ordered */
private int quantity;
/** Price per unit */
private float price;
Trang 10Tạo liên kết và lược đồ mặc định
Để tạo ra một liên kết JiBX và lược đồ XML từ một số lớp Java, đầu tiên bạn cần phải biên dịch các lớp, sau đó chạy công cụ org.jibx.binding.generator.BindGen có trong jibx-tools.jar từ bản phân phối JiBX Bạn có thể chạy trực tiếp công cụ từ dòng lệnh hoặc gián tiếp thông qua một công cụ xây dựng như Ant
Trong tệp tải về của hướng dẫn có chứa một kịch bản lệnh Ant build.xml với đích compile để biên dịch mã ví dụ và đích bindgen để chạy chương trình BindGen trên
mã đã biên dịch
Để thử làm việc này, mở một cửa sổ lệnh trong thư mục dwcode1 nơi cài đặt ví dụ
đã tải về và gõ ant compile bindgen Nếu Ant đã được cài đặt trên hệ thống và bạn
đã cài đặt mã đã tải xuống theo đúng các chỉ dẫn, bạn sẽ thấy kết quả tương tự như được hiển thị trong Hình 1:
Trang 11Hình 1 Sử dụng công cụ xây dựng Ant
Bạn cũng có thể chạy BindGen trực tiếp từ cửa số lệnh Để làm được điều này, bạn cần đưa thêm vào biến môi trường Java classpath của bạn tên tệp tin jibx-tools.jar cùng với đường dẫn đến các tệp tin lớp đã biên dịch sẽ được sử dụng làm đầu vào cho BindGen Nếu bạn muốn tạo bản sao đúp kết quả của đích Ant bindgen, đã cung cấp, bạn cũng cần phải thêm vào dòng lệnh cả tên thư mục gốc của các tệp
mã nguồn của các lớp đó Cuối cùng, bạn cần liệt kê (các) lớp gốc mà bạn muốn
sử dụng cho việc sinh mã Trên các hệ thống UNIX® và Linux®, dòng lệnh Java (chỉ là một dòng, ngay cả khi hiển thị màn hình có xuống dòng vì quá dài) để sao đúp đích Ant bindgen từ cửa sổ lệnh trong thư mục dwcode1 (giả thiết bạn đã làm theo đúng các chỉ dẫn cài đặt được khuyến cáo) là:
java -cp /lib/jibx-tools.jar:bin org.jibx.binding.generator.BindGen
-s src org.jibx.starter.Order
Trên Windows, dòng lệnh (chỉ là một dòng, bất kể hiển thị ở đây như thế nào) là:
java -cp \lib\jibx-tools.jar;bin org.jibx.binding.generator.BindGen
Trang 12-s src org.jibx.starter.Order
Có thể chuyển thêm nhiều tham số tùy chọn khác đến dòng lệnh cho chạy
BindGen Bạn sẽ xem xét các tùy chọn đó sau trong hướng dẫn này Bây giờ, hãy nhìn vào lược đồ đã tạo ra
Các tạo phẩm được tạo ra
Listing 2 cho thấy lược đồ kết quả đã tạo ra từ BindGen (tên là starter.xsd), được định dạng lại một chút cho phù hợp với độ rộng trang và bỏ bớt một số chi tiết Thẻ bắt đầu của định nghĩa lược đồ khớp với mỗi lớp Java được hiển thị bằng chữ
Trang 13<xs:documentation>First line of street information
Trang 14<xs:element name="shipping" minOccurs="0">
Trang 16<xs:documentation>Price per unit.</xs:documentation>
<xs:attribute type="xs:long" use="required" name="orderNumber"/>
<xs:attribute type="xs:date" name="orderDate">
Trang 17Theo mặc định, BindGen tạo ra một lược đồ với các định nghĩa complexType và simpleType ghép lồng nhau nếu các kiểu chỉ được sử dụng một lần và tách riêng các định nghĩa nếu các kiểu được sử dụng nhiều lần Trong trường hợp này, dùng định nghĩa kiểu lồng nhau dẫn đến một lược đồ chỉ có ba định nghĩa toàn cục: các kiểu phức hợp: địa chỉ (address) và đơn hàng và phần tử đơn hàng order Lớp Address được sử dụng ở hai chỗ trong lớp Order (cho các địa chỉ thanh toán và vận chuyển), đó là lý do tại sao mà lớp đó được miêu tả bằng một định nghĩa toàn cầu riêng biệt trong lược đồ (Lược đồ cho phép bạn sử dụng lại các định nghĩa chỉ khi chúng là toàn cầu) Các lớp khác trong cấu trúc dữ liệu Java (Khách hàng (Customer), Mục hàng (Item) và Vận chuyển (Shipping)) mỗi lớp được tham chiếu chỉ tại một điểm trong lớp Order, do đó các định nghĩa kiểu tương ứng được
nhúng trực tiếp trong định nghĩa kiểu lược đồ order
Một trong những đặc tính tốt đẹp hơn của BindGen là nó có thể tạo ra các tài liệu lược đồ từ Javadocs trong các lớp đầu vào Bạn có thể xem tài liệu lược đồ trong Listing 2 cho từng trường với một Javadoc trong Listing 1 và cho mỗi kiểu toàn cầu tương ứng với một lớp với một Javadoc Không phải tất cả các định dạng của các Javadoc đều có thể khớp với các thành phần của lược đồ theo xử lý mặc định của BindGen — và một số Javadoc, ví dụ như những javadocs về các phương thức truy cập “get”, có thể trông có vẻ kỳ cục khi được biến đổi thành tài liệu lược đồ
— và một số Javadoc, ví dụ như những javadocs về các phương thức truy cập
“get”, có thể trông có vẻ kỳ cục khi được biến đổi thành tài liệu lược đồ - nhưng tài liệu lược đồ kết quả có thể vô cùng hữu ích để làm rõ việc sử dụng đúng đắn các biểu diễn XML Bạn thậm chí có thể định nghĩa một lớp định dạng (formatter) của riêng bạn dành cho các Javadoc được sử dụng như là tài liệu lược đồ, nếu bạn muốn thực hiện một số thay đổi lời văn trong quá trình biến đổi (chẳng hạn như việc loại bỏ đoạn mào đầu câu "Get " trong Javadocs của phương thức "get")
Đặc tính chuyển đổi Javadoc này chỉ hoạt động được nếu bạn có sẵn mã nguồn cho các lớp và cung cấp một đối số cho BindGen để báo cho nó biết một đường dẫn của thư mục gốc (hoặc các đường dẫn) Trong các mẫu dòng lệnh tôi đã cung cấp trước đó (xem Tạo liên kết và lược đồ mặc định-Generating the default
binding and schema), đường dẫn nguồn được cung cấp là -s src
Liên kết JiBX được tạo ra
Ngoài các định nghĩa lược đồ, BindGen cũng tạo ra một định nghĩa liên kết JiBX (là tệp tin binding.xml, trong trường hợp này) Định nghĩa liên kết cho các trình biên dịch liên kết của JiBX biết cách chuyển đổi giữa các lớp Java và XML như thế nào Định nghĩa liên kết đó thực sự là kết quả chính của BindGen, với lược đồ được tạo ra từ việc liên kết Các định nghĩa liên kết có đầy đủ các các chi tiết về
Trang 18các phép chuyển đổi được JiBX thực hiện, vì thế chúng nhất định là phải phức tạp May mắn thay, bạn không cần phải hiểu định nghĩa liên kết để làm việc với JiBX khi sử dụng tạo lược đồ và liên kết của BindGen, vì vậy hướng dẫn này không trình bày các chi tiết
Trang 19Làm việc với các tài liệu XML
Trong phần này, bạn sẽ tìm hiểu về việc chạy trình biên dịch liên kết JiBX và sử dụng JiBX lúc đang chạy để làm việc với các tài liệu XML
Chạy trình biên dịch liên kết JiBX
Để sử dụng định nghĩa liên kết được tạo ra trong khi làm việc với các tài liệu XML, trước hết bạn cần phải chạy công cụ trình biên dịch liên kết JiBX Trình biên dịch liên kết thêm mã byte (bytecode) vào các tệp tin lớp đã biên dịch của bạn
để thực sự triển khai thực hiện các phép biến đổi thành XML và từ XML, như định nghĩa liên kết đã chỉ rõ Bạn phải chạy trình biên dịch liên kết mỗi khi bạn biên dịch lại lớp Java của bạn hoặc sửa đổi định nghĩa liên kết, vì vậy tốt nhất là thêm bước biên dịch liên kết như là một phần của quá trình xây dựng tiêu chuẩn của các
dự án của bạn
Trình biên dịch liên kết được bao gồm trong bản phân phối JiBX như là một phần của tệp tin jibx-bind.jar Tài liệu JiBX cung cấp đầy đủ các chi tiết về các cách khác nhau để chạy trình biên dịch liên kết, bao gồm cả cách làm thế nào để bạn có thể chạy nó ở môi trường đang chạy chứ không phải là một phần của quá trình xây dựng JiBX cũng cung cấp các trình cắm thêm cho Eclipse và IntelliJ IDEA để tự động chạy các trình biên dịch liên kết khi bạn đang làm việc trong các IDE này
Với mục đích của hướng dẫn này, bạn nên làm đơn giản mọi việc và chỉ cần chạy trình biên dịch liên kết thông qua Ant, sử dụng đích bind (liên kết) trong tệp tin build.xml Hình 2 cho thấy kết quả đầu ra mà bạn sẽ thấy khi bạn chạy đích này, giả định bạn đã chạy các đích compile và bindgen (Bạn cũng có thể chạy lần lượt tất cả ba đích này bằng cách liệt kê chúng theo thứ tự trên dòng lệnh: ant compile bindgen bind.)
Trang 20Hình 2 Tác vụ bind của công cụ xây dựng Ant
Sử dụng JiBX trong môi trường đang chạy chương trình
Listing 3 cho thấy một tài liệu thử nghiệm đơn giản khớp với lược đồ đã tạo ra, có trong mã đã tải về của hướng dẫn này, có tên là data.xml:
Listing 3 Tài liệu kiểm tra liên kết mặc định
<order orderNumber="12345678" orderDate="2008-10-18" 22"
Trang 21<street1>12345 Happy Lane</street1>
<item quantity="2" price="9.50">
<id>IW2349050499</id>
<description>Right-handed widget</description> </item>
Trang 22<item quantity="1" price="8.95">
<id>RC3000488209</id>
<description>High-speed MP3 rewinder</description>
</item>
</order>
Gói tải về cũng bao gồm một chương trình kiểm tra đơn giản, được hiển thị ở đây
như Listing 4, để trình bày việc sử dụng JiBX cho cả hai tài liệu không tuần tự hóa (unmarshalling) và tuần tự hóa (marshalling) (Marshalling là quá trình sinh ra
một biểu diễn XML của một đối tượng trong bộ nhớ, có thể bao gồm cả các đối tượng được liên kết với đối tượng ban đầu Unmarshalling là quá trình ngược với tuần tự hóa, tức là xây dựng một đối tượng (và có thể là một đồ thị của các đối tượng liên kết với nhau) trong bộ nhớ từ một biểu diễn XML) Đích run của Ant thi hành chương trình thử nghiệm này bằng cách sử dụng tài liệu trong Listing 3 làm đầu vào và viết ra một bản sao kết quả tuần tự hóa đối tượng thành một tệp tin
có tên là out.xml
Listing 4 Chương trình thử nghiệm
public class Test
{
/**
* Unmarshal the sample document from a file, compute and set order total, then
* marshal it back out to another file
*
* @param args
*/
Trang 23public static void main(String[] args) {
// unmarshal customer information from file
IBindingFactory bfact = BindingDirectory.getFactory(Order.class); IUnmarshallingContext uctx = bfact.createUnmarshallingContext(); FileInputStream in = new FileInputStream(args[0]);
Order order = (Order)uctx.unmarshalDocument(in, null);
Trang 24// marshal object back out to file (with nice indentation, as UTF-8) IMarshallingContext mctx = bfact.createMarshallingContext();