使用IBM Rational Software Architect 在Java中處理XSD
許多應用程式需要以一種或多種使用 XSD 指定的行業標準訊息格式表示資料。XSD 通常是指定行業標準訊息格式的理想方法,因為它跨平臺和程式語言受到廣泛支援(無論是本機支援還是通過庫支援)。但是,即使擁有此支援,由於特定於應用程式的資料結構與 XSD 之間的特性不匹配,將儲存在這些特定於應用程式的資料結構中的資料轉換為符合 XSD 的訊息(通常為 XML 訊息)會帶來挑戰。
圖 1. 在兩種特定於應用程式的資料結構之間提供公共訊息模型的行業標準 XSD(中心)
在實現基於 Java 的 Web 服務時,這些特性不匹配會導致很難使用基於 Java API for XML-based RPC (JAX-RPC)、Java API for XML Web Services (JAX-WS) 或同時基於這兩者的工具包,自動化從特定於應用程式的資料結構到 XML 訊息的對映。
由於 XSD 與程式語言無關,它具有許多在 Java 物件中不直接受到支援的特性。此類特性的示例包括 xsd:choice 和 xsd:group 資料型別以及 xsd:restriction 屬性。本文向您介紹如何建立消除這些資料型別的 Java 友好的 XSD。您將使用基於 XSL Transformation (XSLT) 的對映,從而將基於 Java 友好的(內部)XSD 的訊息轉換為全功能的(外部)XSD。對於本文中的特定示例,外部 XSD 為 Postsecondary Electronic Standards Council (PESC) 的 Common Record: CommonLine (CRC) 助學貸款訊息標準。
本文中用於建立與 CRC 1.4 XSD 相對應的 Java 友好的 XSD 的技術可應用於任何太複雜而在基於 Java 的 Web 服務工具包中不直接受支援的 XSD。首先讓我們看一下大致步驟:
- 使用 JAX-RPC 或 JAX-WS 為 XSD 介面生成服務實現(和測試客戶端)。
- 如果需要,則建立外部 XSD 的 Java 友好的簡化版本。
- 使用 Java 友好的 XSD 重新生成服務實現。
- 實現 JAX-RPC 或 JAX-WS 程式碼生成當前不支援的 XSD 約束。
要按照本文所述進行操作,需要在系統上安裝以下軟體:
- 帶 IBM WebSphere® Application Server Feature Pack for Web Services 的 IBM® Rational® Software Architect V7.0.0.6
- IBM WebSphere Integration Developer V6.1
Feature Pack for Web Services 是 Rational Software Architect V7 的一個可選包,您可以使用 IBM Installation Manager 對其進行下載和安裝。安裝該功能包之後,確保通過在 Rational Software Architect 中單擊 Window > Preferences > General > Capabilities 啟用 Web Services Developer 功能。
您的第一個步驟是匯入外部 XSD 並基於該 XSD 建立 Web 服務描述語言(Web Services Description Language,WSDL)介面:
- 在 Rational Software Architect V7 中建立一個 Java 專案(例如,CRCLib)。
- 從 PESC 網站匯入該 XSD。
圖 2. 構成 CRC 標準的 XSD
- 通過右鍵單擊 CRCLib 專案並選擇 New > Other > WSDL 建立新的 WSDL 介面。
- 在 com.ibm.jxsd.services 目錄中建立名為 LoanProcessing.wsdl 的介面。
- 將操作名稱更改為 process,將輸入更改為 CommonRecordCommonlineReceipt,將輸出更改為 CommonRecordCommonlineResponse。
圖 3. 在 Rational Software Architect 中建立 WSDL 介面
下一步,您將建立服務實現。實現技術的選擇將決定您對內部 XSD 所做的更改。給定基於 WebSphere Application Server 的部署環境,總共存在兩種技術選擇:JAX-RPC 和 JAX-WS。JAX-WS 是一種較新的規範,比 JAX-RPC 支援更多的 XSD 構造,因此不需要單獨的(內部)XSD。JAX-RPC 是一種較舊的規範,並且需要內部 XSD;但是由於它較舊,因此受到比 JAX-WS 更廣泛的支援和採用。
CRC 標準
本文的示例中使用的 XSD 來自於 Common Record:CommonLine 標準。Common Record:CommonLine (CRC) 標準同時描述了助學貸款流程中的參與者用於進行訊息交換的訊息和流程:學生、學校、借款人和擔保人。完整的 CRC 1.4 XSD 包括在七個檔案中,可以在 Web上的地址 http://www.pesc.org/interior.php?page_id=162 處找到。本文介紹 JAX-RPC 和 JAX-WS 實現所需要的更改,首先從 JAX-RPC 開始:
- 右鍵單擊 LoanProcessing.wsdl 檔案並選擇 Web Service > Generate Java bean Skeleton。
- 使用 Generate Java bean Skeleton 嚮導,選擇一個新的專案名稱並確保 Web 服務執行時為 JAX-RPC。
- 單擊 Finish 生成程式碼。您應該看到一個視窗開啟並顯示警告。讓我們檢查一下其中一些警告,並瞭解為什麼會發生這些警告。
無法在 Java 中通過 JAX-RPC 對映的 XSD 特性之一是 xsd:group 資料型別。它在 XSD 中的存在導致類似於清單 1 所示的 JAX-RPC 警告。
清單 1. 由於 xsd:group 而產生的 JAX-RPC 警告
WSWS3029W: Warning: The xml construct named {urn:org:pesc:core:CoreMain:v1.4.0}OrganizationType cannot be mapped to a java type. The construct will be mapped to javax.xml.soap.SOAPElement.
由於 xsd:group 資料型別無法在 JAX-RPC 中進行明確的對映,因此一般將其對映到 Java 中的 SOAPElement。SOAPElement 需要以程式設計方式對映到 xsd:group 才能正常工作(請參見清單 2 和 3)。
清單 2. 包含 xsd:group 元素的 XSD
... ...
清單 3. 為 xsd:group 元素生成的 JAX-RPC 程式碼
... private javax.xml.soap.SOAPElement[] organizationType; ...
以程式設計方式將生成的 SOAPElement 對映到 xsd:group 資料型別是一種脆弱的解決方案,並違反了儘可能避免直接修改所生成的程式碼的實踐。您不能更改來自於標準的 XSD,因此可以建立一個內部 XSD,在其中將 xsd:group 替換為 xsd:complexType,如清單 4 所示。
清單 4. 在其中將 xsd:group 元素替換為 xsd:complexType 的 XSD
... ...
雖然 xsd:group 和 xsd:complexType 都是容器資料型別,但它們並不完全相同。組封裝 all、choice 或 sequence 元素,而 complexType 封裝屬性、巢狀元素和混合內容。因此您可能擔心在轉換到 xsd:complexType 時會失去 xsd:group 資料型別的某些表達功能。但是結果證明,xsd:choice 也不受 JAX-RPC 對映的支援,因此您無論如何都要在內部 XSD 中對此進行更改。xsd:sequences 在 xsd:complexType 中受支援(如清單 4 所示)。
xsd:choice 是另一個不受 JAX-RPC 支援的 XSD 特性。針對 xsd:choice 的警告與清單 5 所示類似。
清單 5. 由於 xsd:choice 而產生的 JAX-RPC 警告
WSWS3029W: Warning: The xml construct named {urn:org:pesc:core:CoreMain:v1.4.0}TestsType cannot be mapped to a java type. The construct will be mapped to javax.xml.soap.SOAPElement.
xsd:choice 資料型別描述了這樣一個結構,其中只有一個子元素可以是活動的或者可供選擇。Java 中不存在對應的結構,因此 JAX-RPC 同樣將 xsd:choice 資料型別對映到通用 SOAPElement(請參見清單 6 和 7)。
清單 6. 包含 xsd:choice 元素的 XSD
...
清單 7. 為 xsd:choice 元素生成的 JAX-RPC 程式碼
... private javax.xml.soap.SOAPElement[] testType; ...
要使您的 XSD 變得 Java 友好,您可以從出現 xsd:choice 的位置將其完全刪除,以便 JAX-RPC 能夠產生對映。沒有 xsd:choice 時,JAX-RPC 生成的程式碼將建立正確的類(請參見清單 8)。
清單 8. 在其中將 xsd:group 元素替換為 xsd:complexType 的 XSD
... ...
這可能讓人擔心 XSD 將允許訊息有多個元素,從而與外部 XSD 衝突。這種資料結構約束的弱化要求根據需要強化應用程式邏輯中的約束。但是,由於傳入資料來自於外部來源,並滿足外部 XSD,而傳出資料在傳輸前將根據外部 XSD 進行驗證,因此不存在應用程式接受或傳輸無效資料的危險。如果需要根據 XSD 約束對傳入資料或傳出資料進行權威驗證,可以考慮部署專用的網路邊緣裝置,例如 IBM WebSphere DataPower SOA Appliances 所提供的裝置。
Russell Butek 的文章“Web 服務技巧: 將多型性作為 xsd:choice 的備選方法”描述了對 xsd:choice 的另一種替代選擇。
在完成從外部 XSD 到內部 XSD 的所有更改之後,您可以在 WebSphere Integration Developer V6.1 中建立一箇中介模組,此模組將在 IBM WebSphere Enterprise Service Bus 或在 IBM WebSphere Process Server 中執行。在該中介模組中,一個 XSLT 對映在內部和外部 XSD 之間轉換 XML 訊息(請參見圖 4)。
建立中介流和 XSLT 對映超出了本文的範圍,但是WebSphere Integration Developer 幫助文件的構建中介流部分對此進行了詳細的描述。 此外,為了便於參考,下載部分作為專案交換檔案提供了為本文建立的中介模組。
請參見圖 4 的大圖。
圖 4. 在 WebSphere Integration Developer 中將內部 XSD 對映到外部 XSD
在實際實現中,您將選擇一種實現技術:JAX-RPC 或 JAX-WS。但是出於完整性的考慮,下面介紹了在使用 JAX-WS 時需要對內部 XSD 做出的更改:
- 在 CRCLib 專案中,右鍵單擊 LoanProcessing.wsdl 檔案,然後選擇 Web Services > Generate Java bean skeleton。
圖 5. 在 WSDL 基礎上生成 Web 服務
- 在視窗中,將 Web 服務執行時更改為 IBM WebSphere JAX-WS。如果 JAX-WS 選項未列出,這意味著未安裝 WebSphere Application Server Feature Pack for Web Services。
圖 6. 用於生成 JAX-WS Web 服務的選項
- 確保在視窗中選擇新的專案名稱(例如 LoanPWS),然後單擊 Next 以確保將 WSDL 複製到專案。
- 回到 Service Deployment Configuration 視窗,單擊 OK 生成所有程式碼。如果伺服器未執行,它將會啟動。
程式碼成功生成而無任何錯誤或警告。成功地為整個 XSD 生成了對應的類,因此不需要任何單獨的內部 XSD。JAX-WS 實現將 xsd:group 資料型別(此資料型別沒有對應的 Java 表示形式)轉換為 xsd:complexType。這是您在為 JAX-RPC 實現的內部 XSD 中手動執行的相同轉換;但是在 JAX-WS 實現中,該轉換是隱式和自動的。
JAX-WS 實現將 xsd:choice 資料型別表示為 Java 類的屬性,並且做出隱式和自動的轉換,同樣,此轉換與您使用內部 XSD 為 JAX-RPC 實現執行的轉換相同。
確保僅設定其中一個選擇。例如,在清單 9 中,eSignatureCustodianType 中可以具有 Lender 或 Guarantor 元素。
為此型別生成的 Java 程式碼如清單 10 所示。
清單 10. 為 xsd:choice 元素生成的 JAX-WS 程式碼
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "eSignatureCustodianType", namespace = "urn:org:pesc:core:CoreMain:v1.4.0", propOrder = { "lender", "guarantor" }) public class ESignatureCustodianType { @XmlElement(name = "Lender") protected ESignatureCustodianType.Lender lender; @XmlElement(name = "Guarantor") protected ESignatureCustodianType.Guarantor guarantor;
請注意,Lender 和 Guarantor 都存在 get 和 set 方法。您必須確保僅填充其中一個。
XSD 資料型別可以描述在 Java 沒有等效表示式時的約束。因此,JAX-RPC 和 JAX-WS 都不能建立保留所有約束的對應 Java 類。讓我們看看 XSD 約束和 JAX-WS 中生成的對應 Java 程式碼的一些示例。
在清單 11 中的 XSD 中,confirmationID 是一個最小長度為 1 和最大長度為 20 的字串。
Confirmation ID supplied from the counseling session
生成的 Java 程式碼如清單 12 所示。
清單 12. 為帶長度約束的 XSD 生成的 Java 程式碼
public class LoanCounselingType { @XmlElement(name = "ConfirmationID") protected String confirmationID; @XmlElement(name = "CompletionDate") protected XMLGregorianCalendar completionDate; @XmlElement(name = "CompletionTime") protected XMLGregorianCalendar completionTime;
為 confirmationID 生成的 Java 程式碼只是一個不帶任何約束的 Java 字串。如果將該字串設定為無效長度的值,該程式碼沒有問題,但是生成的 XML 將無法通過驗證。為了避免這一點,您必須顯式地向程式碼新增字串長度檢查。
另一個在 Java 中不受支援的 XSD 約束是必備 約束。例如,下面的 XSD 描述了一組必須從中選擇其一的列舉值(也就是說,值為 Null 或不做出選擇將是無效的)。
Code indicating the preferred or actual method of delivering the promissory note to the borrower
生成的 JAX-WS 程式碼如清單 14 所示。
清單 14. 為帶必備約束的 XSD 生成的 Java 程式碼
public enum PromissoryNoteDeliveryCodeType { @XmlEnumValue("Paper") PAPER("Paper"), @XmlEnumValue("Email") EMAIL("Email"), @XmlEnumValue("Web") WEB("Web"); private final String value;
程式碼生成器正確地建立了 Java 列舉,但是不確保至少選擇其中一個值。因此,強制執行此約束同樣是您的責任。
您將在這裡檢查的最後一個不受支援的 XSD 約束是 maxOccurs。在該示例中(請參見清單 15)中,父元素 PellAwardResponseType 具有一個名為 FSACode 的子元素,此子元素應該出現零至三次。
生成的 Java 程式碼(請參見清單 16)將 FSACode 表示為字串列表。它沒有將該列表的長度限制為少於四個專案。
清單 16. 為帶 maxOccurs 約束的 XSD 生成的 Java 程式碼
public class PellAwardResponseType extends ResponseType { …. @XmlElement(name = "FSACode") protected List
fsaCode;
Anthony Young-Garner, 解決方案開發人員, IBM
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14780914/viewspace-604215/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- xsd中schemaLocation使用
- XSD 使用概述
- Java 11:在Java中處理HTTP和WebSocket的新方法!JavaHTTPWeb
- java當中的批處理Java
- Java 中的並行處理Java並行
- Calendar類在Java中的應用與日期時間處理Java
- 在Linux中,如何使用awk和sed進行文字處理?Linux
- Java 異常處理:使用和思考Java
- Java中對時間的處理Java
- java中的垃圾處理機制Java
- java中 檔案壓縮處理Java
- mongoDB中聚合函式java處理MongoDB函式Java
- DOM在Ahooks中的處理過程Hook
- netty系列之:在netty中處理CORSNettyCORS
- Java中的任務超時處理Java
- Java 中的異常處理機制Java
- Java8中的時間處理Java
- java大資料處理:如何使用Java技術實現高效的大資料處理Java大資料
- eclipse在使用中彈出這個錯誤框,該如何處理?Eclipse
- Java處理emojiJava
- Rational ClearQuest 安裝、配置、使用手冊
- 使用Java預處理實現JSON插入PostgreSQLJavaJSONSQL
- Java如何使用實時流式計算處理?Java
- 在 C 程式中處理 UTF-8 文字
- 說說在 Python 中如何處理異常Python
- 怎樣在 Laravel 中處理前端認證Laravel前端
- 【翻譯】在Spring WebFlux中處理錯誤SpringWebUX
- 在 Laravel 中優雅處理 Form 表單LaravelORM
- 在 Java 中如何使用 transientJava
- Java中的異常處理最佳實踐Java
- Java中如何處理空指標異常Java指標
- 翻譯 | Java流中如何處理異常Java
- 在 SQL Server 中使用 Try Catch 處理異常SQLServer
- 在vue使用異常處理做錯誤提示Vue
- 在javascript中使用純函式處理副作用JavaScript函式
- 在 .NET 中使用 Flurl 高效處理Http請求HTTP
- Java 異常處理Java
- JAVA異常處理Java
- JAVA 異常處理Java