Hiểu biết về Đặc tả các dịch vụ Web, Phần 2: WSDL (Ngôn ngữ mô tả các dịch vụ Web)

Chia sẻ các dịch vụ Web

Tầm quan trọng hiện tại đối với SOA (Service-Oriented Architectures - Các kiến trúc hướng dịch vụ) đã diễn tả địa vị nổi bật của các dịch vụ Web, nhưng thật dễ dàng đi lạc trên tất cả thông tin đang được bàn tán đó. Loạt bài này mang đến cho bạn câu chuyện trung thực về tất cả các đặc tả dịch vụ Web chủ yếu, bắt đầu với SOAP (Simple Object Access Protocol – Giao thức truy cập đối tượng đơn giản) và xuống tới WS-BPEL (WS Business Process Execution Language - Ngôn ngữ thực hiện qui trình nghiệp vụ WS). Trong phần đăng thứ hai này, bạn sẽ tìm hiểu về WSDL, khi phòng chuyên mục rao vặt của tờ Daily Moon (Mặt trăng hàng ngày) sử dụng WSDL để mô tả dịch vụ Web riêng của họ theo cách cho những người khác có thể dễ dàng tạo các ứng dụng khách để truy cập dịch vụ đó từ nền tảng hay ngôn ngữ lập trình bất kỳ.

Nicholas Chase, Tác giả tự do, Site Dynamics Interactive Communications

Nicholas Chase đã phát triển trang web cho các công ty lớn như Lucent Technologies, Sun Microsystems, Oracle, và Tampa Bay Buccaneers. Nick đã từng là một giáo viên vật lý ở trường phổ thông, một nhà quản lý thiết bị phóng xạ mức thấp, một nhà biên tập tạp chí khoa học viễn tưởng trực tuyến, một kỹ sư đa phương tiện, một hướng dẫn của Oracle, và một trưởng phòng công nghệ của một công ty tương tác truyền thông. Nick là tác giả của một số sách



09 10 2010

Trước khi bạn bắt đầu

Hướng dẫn này được thiết kế để cung cấp cho bạn một sự hiểu biết về WSDL - Ngôn ngữ mô tả các dịch vụ Web. Hướng dẫn này dành cho các nhà phát triển muốn trưng ra các dịch vụ riêng của họ cho những người khác sử dụng khi dùng WSDL và cũng để các nhà phát triển có tệp WSDL dành cho một dịch vụ mà họ muốn truy cập và cần phải tạo một ứng dụng khách.

Để làm theo hướng dẫn này, bạn nên có một sự hiểu biết cơ bản về SOAP, bạn có thể đạt được sự hiểu biết cơ bản này bằng cách đọc Phần 1 của loạt bài hướng dẫn này và phần mở rộng, sự hiểu biết cơ bản về XML. WSDL là thuyết bất khả tri của ngôn ngữ lập trình, nhưng các ví dụ ở cuối hướng dẫn này lại sử dụng Java và dự án Apache Axis2. Tuy nhiên, các khái niệm này sẽ áp dụng cho ngôn ngữ lập trình và môi trường bất kỳ. Tương tự, hướng dẫn này tập trung vào WSDL 1.1 đã được triển khai thực hiện phổ biến hơn, nhưng các khái niệm này là giống nhau cho WSDL 2.0 sắp tới và hướng dẫn này trình bày những sự khác biệt cơ bản giữa chúng.

Về loạt bài này

Loạt bài hướng dẫn này dạy các khái niệm cơ bản về các dịch vụ Web bằng cách tiếp tục khai thác về tờ báo hư cấu Daily Moon, khi các nhân viên sử dụng các dịch vụ Web để tạo ra một hệ thống tiến trình công việc để tăng năng suất trong những thời điểm có nhiều thay đổi nà.

Phần 1 bắt đầu đơn giản, khi giải thích các khái niệm cơ bản đằng sau các dịch vụ Web và dạy bạn cách sử dụng SOAP, đặc tả làm cơ sở cho hầu hết những gì sắp tới, kết nối phòng chuyên mục rao vặt với Hệ thống quản lý nội dung.

Trong Phần 2, Phòng chuyên mục rao vặt đưa mọi thứ tiến lên một bước xa hơn, khi sử dụng WSDL (Web Services Description Language - Ngôn ngữ mô tả các dịch vụ Web) để định nghĩa các thông báo được các dịch vụ Web tạo ra như mong đợi, cho phép nhóm làm việc tạo ra các dịch vụ và các ứng dụng khách kết nối với các thông báo dễ dàng hơn.

Phần 3 tìm nhóm làm việc có một số dịch vụ tại chỗ và có một mong muốn định vị các dịch vụ dễ dàng. Đáp lại, UDDI (Universal Description, Discovery and Integration - Tích hợp, khám phá và mô tả đa năng) cung cấp đăng ký tìm kiếm của các dịch vụ có sẵn như là một cách đưa ra công khai các dịch vụ riêng của chúng cho những người khác.

Phần 4 và 5, Các dịch vụ Web-An ninh (WS-Security) và Các dịch vụ Web-Chính sách (WS-Policy), đã lấy mục tiêu là an ninh của các dịch vụ của tờ báo và những thay đổi mà các nhóm làm việc cần phải thực hiện để truy cập các dịch vụ mới được bảo vệ đó.

Tính tương thích là từ khóa trong phần 6, do các dịch vụ từ các sự hiện thực khác nhau phải được truy cập từ một hệ thống duy nhất. Phần 6 trình bày các yêu cầu và các thử nghiệm liên quan đến việc cấp chứng chỉ Các dịch vụ Web-Tính tương thích (WS-I).

Cuối cùng, phần 7 dạy cách sử dụng WS-BPEL (Ngôn ngữ thực hiện qui trình kinh doanh) để tạo các ứng dụng phức tạp từ các dịch vụ riêng biệt như thế nào.

Bây giờ hãy xem xét hướng dẫn này trình bày những gì cụ thể hơn một chút.

Về hướng dẫn này

Phần 1 của hướng dẫn này, Hiểu biết về các dịch vụ Web: SOAP, đã giới thiệu các nhân viên của tờ báo hư cấu Daily Moon. Cụ thể là bạn đã gặp Phòng chuyên mục rao vặt. Trong hướng dẫn đó, Phòng chuyên mục rao vặt xây dựng một ứng dụng khách để gửi các thông báo SOAP qua lại tới dịch vụ Web biểu thị Hệ thống quản lý nội dung (Content Management System). Trong hướng dẫn này, bị ấn tượng bởi những gì đã thấy, Phòng chuyên mục rao vặt quyết định xây dựng dịch vụ Web của riêng mình để nhận và quản lý các đoạn quảng cáo trong cơ sở dữ liệu rao vặt. Tuy nhiên, để cho phép người khác sử dụng dịch vụ này, họ sẽ cần tạo một tệp WSDL. Tệp này đưa ra các hướng dẫn cho những người dùng khác xây dựng các ứng dụng khách để họ biết dịch vụ đó dự kiến và trả về các thông báo nào.

Trong hướng dẫn này, bạn sẽ học những phần sau đây:

  • Tại sao các tệp WSDL lại quan trọng.

  • Bạn có thể làm gì với các tệp WSDL.

  • Các vấn đề cơ bản của lược đồ (schema) XML, xuất hiện trong các tệp WSDL.

  • Làm thế nào để cấu trúc một tệp WSDL.

  • Sự khác biệt cơ bản giữa WSDL 1.1 và WSDL 2.0.

  • Làm thế nào để tự động tạo một tệp WSDL từ một lớp Java đại diện cho một dịch vụ.

  • Làm thế nào để tạo ra một lớp Java đại diện cho một dịch vụ từ một tệp WSDL.

  • Làm thế nào để tạo ra một ứng dụng khách của dịch vụ Web từ một tệp WSDL.

Phòng chuyên mục rao vặt sẽ xây dựng một dịch vụ nhận các đoạn quảng cáo mới, chỉnh sửa và hiển thị các đoạn quảng cáo hiện có và hoàn tất một vấn đề để nó không còn chấp nhận bất kỳ đoạn quảng cáo nào nhiều hơn nữa. Họ sẽ sử dụng cả hai thông báo yêu cầu/đáp ứng lẫn thông báo một chiều.

Các công cụ và các điều kiện cần trước

Phần chính của hướng dẫn này dựa trên các khái niệm, những để làm theo các mã ở cuối của hướng dẫn này, bạn sẽ cần có sẵn các phần mềm sau và đã cài đặt:

Máy chủ Apache Geronimo hoặc máy chủ ứng dụng khác -- Nhóm làm việc tạo một dịch vụ Web mới trong tiến trình của hướng dẫn này và bạn sẽ cần một ứng dụng để chạy nó trên đó. Tất nhiên, do các dịch vụ Web được hỗ trợ để có khả năng tương thích với nhau, nên việc bạn sử dụng một dịch vụ nào thực sự không quan trọng. Trong hướng dẫn này, chúng tôi sẽ giải thích việc cài đặt và sử dụng máy chủ Apache Geronimo, cũng là ấn bản cộng đồng WebSphere của IBM (IBM® WebSphere® Community Edition). Bạn cũng có thể sử dụng các máy chủ ứng dụng khác như Máy chủ ứng dụng WebSphere (WebSphere Application Server). Bạn có thể tải Apache Geronimo từ http://geronimo.apache.org/downloads.html. Để biết thêm chi tiết về việc cài đặt Geronimo, xem hướng dẫn đầu tiên trong loạt bài này, "Hiểu biết về các dịch vụ Web, Phần 1: SOAP."

Apache Axis2 phiên bản 0.95 hoặc cao hơn -- Bạn có thể tạo các thông báo SOAP bằng tay và bạn có thể giải thích chúng bằng tay, nhưng thật thoải mái để có một sự thực hiện có lợi. Hướng dẫn này giải thích việc sử dụng Apache Axis2, bao gồm các việc thực hiện của các API có liên quan đến-SOAP khác nhau để làm cho cuộc sống của bạn dễ dàng hơn đáng kể. Bạn có thể tải Apache Axis2 tại http://ws.apache.org/axis2/download.cgi. Hướng dẫn này sử dụng phiên bản 0.95, nhưng các phiên bản sau này cũng sẽ dùng được. (Lưu ý Phần 1 của loạt bài này đã sử dụng phiên bản 0.94, nhưng nó vẫn chưa được thử nghiệm bằng các mã trong phần này).

Java 2 Standard Edition (Ấn bản tiêu chuẩn Java ™ 2) phiên bản 1.4 hoặc cao hơn -- Tất cả các công cụ này dựa trên Java, như là các dịch vụ và các ứng dụng khách mà bạn sẽ xây dựng trong hướng dẫn này. Bạn có thể tải J2SE SDK từ http://java.sun.com/j2se/1.5.0/download.jsp.

Bạn cũng sẽ cần một trình duyệt Web và một trình soạn thảo văn bản, nhưng tôi chắc chắn rằng bạn đã có chúng rồi. Nếu bạn muốn, bạn cũng có thể sử dụng một IDE như là Eclipse, nhưng do chúng ta tập trung vào các công nghệ hơn là các công cụ, nên chúng ta sẽ chỉ sử dụng một trình soạn thảo văn bản và dòng lệnh để chỉnh sửa các tệp của chúng ta và biên dịch chúng.


Tổng quan

Trước khi đi vào chi tiết, hãy xem bức tranh lớn.

Trình làm mới (refresher) dịch vụ Web

Các lợi thế chính của việc sử dụng các dịch vụ Web hơn các phương pháp lập trình truyền thống là khả năng tương thích. Bạn có thể tạo một hệ thống phân tán, trong đó các máy tính được phân tách theo vật lý và theo địa lý có thể truyền thông, nhưng trong hầu hết các trường hợp, bạn đang phải đối phó với phần mềm trung gian độc quyền, làm hạn chế tính linh hoạt của bạn. Nói cách khác, cả người gửi và người nhận cần sử dụng cùng một phần mềm.

Các dịch vụ Web cung cấp một phương tiện dựa trên văn bản (trên thực tế, dựa trên-XML) để truyền các thông báo qua lại, có nghĩa là các ứng dụng của bạn không chỉ có máy tính độc lập, mà còn có hệ điều hành và ngôn ngữ lập trình độc lập. Miễn là cả hai bên tuân theo các tiêu chuẩn dịch vụ Web, thì không có vấn đề gì về phần mềm đang chạy trên cả hai phía.

Hiện có một số các tiêu chuẩn để truyền thông tin này, nhưng loạt bài hướng dẫn này tập trung vào SOAP do tính linh hoạt và cách sử dụng của nó với nhiều tiêu chuẩn tiên tiến khác.

Trình làm mới SOAP

Một thông báo SOAP có ba phần chính: phần Tiêu đề (Header), phần Thân (Body) và phần tải trọng (payload) nằm trong phần thân. Hãy xem xét ví dụ này:

Liệt kê 1. Một ví dụ về thông báo SOAP
    >SOAPenv:Envelope 
       xmlns:SOAPenv="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<
 >SOAPenv:Body<
  >req:getNumberOfArticles xmlns:req="http://daily-moon.com/CMS/"<
     >req:category<classifieds>/req:category<
  >/req:getNumberOfArticles<
 >/SOAPenv:Body<
>/SOAPenv:Envelope<

Toàn bộ thông báo được gọi là Phong bì (Envelope), các nội dung của phong bì bao gồm phần Tiêu đề và phần Thân. Phần tiêu đề chứa thông tin về chính thông báo đó, chẳng hạn như thông tin định tuyến hoặc các thông tin dành cho "các phương tiện trung gian SOAP" xử lý hoặc các dịch vụ giữa người gửi và người nhận cuối có thể xử lý thông báo. Phần thân của thông báo bao gồm "tải trọng", có kèm theo các dữ liệu thực tế được chuyển tới dịch vụ Web

Trong trường hợp này, tải trọng là phần tử getNumberOfArticles và các nội dung của nó.

WSDL dành cho cái gì

Khi bạn tạo một dịch vụ, bạn thường thực hiện dịch vụ đó bởi vì bạn muốn người khác sử dụng dịch vụ. Để cho người dùng khác sử dụng dịch vụ, họ cần biết những thông tin nào gửi đến dịch vụ, dịch vụ sẽ gửi lại thông tin nào và nơi tìm dịch vụ từ chỗ ban đầu. Tất nhiên, bạn có thể đưa thông tin này vào trong một tài liệu xử lý văn bản, nhưng để có một định dạng tiêu chuẩn cho thông tin này, tốt nhất là người và máy có thể đọc được, thì có ích hơn nhiều.

WSDL cung cấp định dạng tiêu chuẩn này. Ngoài việc rõ nghĩa, lợi thế chủ yếu là thực tế rằng vì WSDL là tiêu chuẩn phổ biến và nó ở trong XML, nó có thể đọc được bằng máy tính, cho đến vị trí ở đó bạn có thể tự động tạo các ứng dụng khách (và thậm chí cả bộ khung của một dịch vụ). Phòng chuyên mục rao vặt sẽ tạo một dịch vụ để chấp nhận và quản lý các đoạn quảng cáo rao vặt và để cho phép những thứ khác như các trang Web tập hợp công việc dễ dàng sử dụng dịch vụ hơn, họ cũng sẽ mô tả dịch vụ bằng cách sử dụng một tệp WSDL.

Hướng dẫn này sẽ thực hiện cái gì

Trong tiến trình của hướng dẫn này, bạn sẽ tìm hiểu về WSDL bằng cách làm theo các nhân viên của Phòng chuyên mục rao vặt của tờ báo Daily Moon khi họ tạo ra dịch vụ của mình và trưng nó ra cho những người khác sử dụng.

Đầu tiên, Christine nhận các lược đồ XML, định nghĩa dữ liệu có thể xuất hiện trong thông báo SOAP. Tiếp theo, Larry ráp cấu trúc của một tệp WSDL thực tế vào với nhau để nắm chắc được những thông tin nào họ sẽ cần chuyển qua lại. Sau đó, Gene nhận tệp WSDL và sử dụng nó như là nguồn cảm hứng cho một lớp Java đại diện cho dịch vụ đó và sau đó để cho chắc chắn, Gene sử dụng Axis2 để tạo ra một tệp WSDL từ lớp Java để xem những sự khác biệt. Từ đó, Francis nhận tệp WSDL và sử dụng nó để tạo ra cả hai dịch vụ Web cơ bản lẫn một ứng dụng khách để truy cập dịch vụ Web.

Chúng ta hãy bắt đầu.


Một bài học vỡ lòng vắn tắt về Lược đồ XML

Daily Moon là một tờ báo hàng ngày khá nhỏ và như vậy Phòng chuyên mục rao vặt không thể cung cấp một DBA chuyên dụng. Do đó Christine đã luôn xem xét cơ sở dữ liệu "con của cô". Sau khi xem xét các đặc tả với WSDL, cô quyết định nhận nhiệm vụ định nghĩa dữ liệu có thể đưa vào các thông báo SOAP.

Xác nhận tính hợp lệ và các tùy chọn

Các nhân viên đã hiểu rõ XML sau lần thử sức ban đầu của họ trong các dịch vụ Web, vì vậy bước hợp lý tiếp theo với Christine là tìm hiểu về việc xác nhận tính hợp lệ.

Việc xác nhận tính hợp lệ XML là quá trình đảm bảo rằng cả hai cấu trúc và nội dung của một tài liệu XML tuân theo bất kỳ các yêu cầu được xác định trước. Ban đầu, điều này có nghĩa là tuân theo Document Type Definition (Định nghĩa kiểu tài liệu) hoặc DTD, một cấu trúc để lại về sau từ các gốc của XML như ngôn ngữ SGML. Các yêu cầu của DTD không thực sự khó, nhưng chúng đã có những hạn chế chủ yếu về thiếu tính linh hoạt, thiếu sự hỗ trợ cho các vùng tên XML và các vấn đề khác, do đó cộng đồng XML chuyển sang các loại lược đồ XML khác.

Lưu ý rằng từ "các lược đồ - schemas" không viết hoa trong phần còn lại. Bây giờ, trong trường hợp này, tôi đang nói về việc sử dụng chung thuật ngữ, có nghĩa là cấu trúc cụ thể cho một tài liệu, trái ngược với ngôn ngữ bất kỳ để tạo tài liệu có cơ cấu đó. Sự hỗ trợ chung nhất cho các lược đồ này là Ngôn ngữ Lược đồ (Schema) XML của W3C là, thường được gọi đơn giản là Lược đồ XML-XML Schema. (Lưu ý chữ hoa - Schema).

Christine thấy rằng họ sẽ sử dụng Lược đồ XML để xây dựng tài liệu WSDL 1.1 của họ, nhưng lưu ý rằng WSDL 2.0 hỗ trợ cụ thể cho các lược đồ khác, chẳng hạn như lược đồ RELAX NG và Schematron, có thể được sử dụng tại chỗ của nó.

Tài liệu phiên bản

Christine bắt đầu với một tài liệu ví dụ gần giống với dữ liệu mà cô hy vọng sẽ chảy vào và chảy ra ngoài hệ thống. Christine kéo một vài đoạn quảng cáo hiện có và tạo XML:

Liệt kê 2. Tài liệu phiên bản
Listing 2: the instance document
<?xml version="1.0"?>
<ClassifiedList>

   <ClassifiedAd adId="1138">
      <content>Vintage 1963 T-Bird.  Less than 300 miles.  
Driven by my daughter until I took it away.  Serious inquires
only. 555-3264 after 7 PM.</content>
      <endDate>4/15/2007</endDate>
      <startDate>4/1/2007</startDate>
   </ClassifiedAd>

   <ClassifiedAd adId="2187">
      <content>30 ft ladder, only used once.  Willing to let
go for half its worth. Has slight dent near the middle.  
Harder than a human head. $150 OBO.</content>
      <endDate>4/30/2007</endDate>
      <startDate>4/10/2007</startDate>
   </ClassifiedAd>

</ClassifiedList>

Tài liệu này được gọi là một "tài liệu phiên bản" (instance document), nó đại diện cho các dữ liệu được định nghĩa trong lược đồ XML. Trong trường hợp này, nó có hai phần tử ClassifiedAd là phần tử con của phần tử ClassifiedList. Mỗi phần tử ClassifiedAd có một thuộc tính adId tương ứng với khóa chính trong cơ sở dữ liệu, nội dung của quảng cáo và các ngày tháng bắt đầu và kết thúc cho đoạn quảng cáo.

Christine đặt tên cho tài liệu này là classifieds.xml.

Lược đồ cơ bản

Bước tiếp theo của Christine là tạo các tài liệu lược đồ cơ bản để cô ấy có thể thử nghiệm hệ thống này. Bản thân lược đồ thực tế cũng là một tài liệu XML, vì vậy Christine tạo ra tệp cơ bản, classifieds.xsd và một phần tử lược đồ (schema) duy nhất, như đã thấy trong Liệt kê 3:

Liệt kê 3. Phần tử lược đồ
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

</xsd:schema>

Phần tử này sẽ hoạt động như phần tử cha mẹ với tất cả các định nghĩa mà Christine tạo ra.

Xác nhận tính hợp lệ tài liệu

Bước tiếp theo trong việc thử nghiệm hệ thống là kết hợp một ứng dụng Java đơn giản vào với nhau và ứng dụng Java này sẽ xác nhận tính hợp lệ tài liệu phiên bản đối với lược đồ đó. Tất cả mọi thứ mà lớp đó đã làm là chỉ rõ việc xác nhận tính hợp lệ và phân tích cú pháp tài liệu, như trong Liệt kê 4.

Liệt kê 4. Lớp ValidateWithSchema
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
 
public class ValidateWithSchema {
 
    public static void main(String args[]) {

        DocumentBuilderFactory dbf = 
                        DocumentBuilderFactory.newInstance();
        dbf.setValidating(true);

        dbf.setAttribute(
          "http://java.sun.com/xml/jaxp/properties/schemaLanguage", 
          "http://www.w3.org/2001/XMLSchema");
        dbf.setAttribute(
          "http://java.sun.com/xml/jaxp/properties/schemaSource",
          "classifieds.xsd");

        Document doc = null;
        try{        
           DocumentBuilder parser = dbf.newDocumentBuilder();
           doc = parser.parse("classifieds.xml");
        } catch (Exception e){
           e.printStackTrace();
        }
    }
}

Phương thức thực tế để phân tích cú pháp không phải rất quan trọng; trong trường hợp này, Christine xây dựng ứng dụng bằng cách sử dụng một trình phân tích cú pháp (parser) DOM. Đầu tiên, xây dựng một nhà máy và sau đó xác định rằng bất kỳ các trình phân tích cú pháp nào mà nó tạo ra nên là "các trình phân tích cú pháp xác nhận tính hợp lệ". (Không phải tất cả các trình phân tích cú pháp đều sẽ xác nhận tính hợp lệ. Một số chỉ cần kiểm tra xem tài liệu đó có "định dạng đúng" không, mà không cần kiểm tra cấu trúc thực tế của chúng).

Tiếp theo, xác định ngôn ngữ lược đồ để sử dụng và bản thân tài liệu lược đồ đó. Trong trường hợp này, Christine sẽ sử dụng một tệp cục bộ, nhưng bạn có thể sử dụng bất kỳ tệp nào có thể tham chiếu được như là một URL.

Christine lưu tệp này và biên dịch nó và sau khi chạy nó, cô ấy nhận được đầu ra như sau, được hiển thị trong Liệt kê 5.

Liệt kê 5. Chạy lược đồ rỗng
Warning: validation was turned on but an org.xml.sax.ErrorHandler 
was not set, which is probably not what is desired.  Parser will 
use a default ErrorHandler to print the first 10 errors.  Please call
the 'setErrorHandler' method to fix this.

Error: URI=file:///E:/WSDLFiles/classifieds.xml Line=2: cvc-elt.1: 
Cannot find the declaration of element 'ClassifiedList'.

Warning (Cảnh báo) này không quan trọng; Christine chỉ muốn biết liệu tệp đó có hợp lệ hay không, vì vậy cô không cần bất kỳ các khả năng xử lý lỗi ngoại lệ nào. Error (Lỗi) này rất quan trọng, vì nó có nghĩa là trình phân tích cú pháp trong thực tế đang chú ý đến lược đồ đó và xác nhận tính hợp lệ tài liệu phiên bản.

Bây giờ Christine cần thêm các định nghĩa thực tế.

Tạo một phần tử đơn giản

Thật dễ dàng để định nghĩa một vài phần tử đầu tiên. Các phần tử content (nội dung), endDate (Ngày kết thúc) và startDate (Ngày bắt đầu) có các chuỗi đơn giản, như trong Liệt kê 6.

Liệt kê 6. Thêm các phần tử đơn giản
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

   <xsd:element type="xsd:string" name="content" /> 
   <xsd:element type="xsd:string" name="endDate" /> 
   <xsd:element type="xsd:string" name="startDate" />

</xsd:schema>

Trong trường hợp này, Christine đã định nghĩa ba phần tử chỉ có văn bản (trái ngược với các phần tử khác) làm nội dung. Ngoài ra, không có phần tử nào trong số chúng có các thuộc tính. Khuyến nghị của Lược đồ XML (XML Schema Recommendation) định nghĩa một số loại lược đồ khác nhau mà bạn có thể sử dụng chúng để định nghĩa nội dung của bạn. Ví dụ, bạn có thể xác định các giá trị endDatestartDate phải là các giá trị datetime (thời gian ngày tháng).

Tạo một phần tử phức tạp hơn

Tất nhiên, nếu tất cả các phần tử là phần tử đơn giản, có thể bạn sẽ không cần một lược đồ ở vị trí đầu tiên. Christine tiếp tục định nghĩa phần tử ClassifiedList (xem Liệt kê 7).

Liệt kê 7. Định nghĩa phần tử ClassifiedList
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="ClassifiedList"> 
  <xsd:complexType> 
    <xsd:sequence> 
       <xsd:element name="ClassifiedAd" maxOccurs="unbounded" type="ClassifiedAdType"/> 
    </xsd:sequence> 
  </xsd:complexType> 
</xsd:element> 

<xsd:complexType name="ClassifiedAdType"> 
  <xsd:sequence>
       <xsd:element type="xsd:string" name="content" />
       <xsd:element type="xsd:string" name="endDate" />
       <xsd:element type="xsd:string" name="startDate" />
 </xsd:sequence> 
</xsd:complexType>

</xsd:schema>

Bắt đầu từ phía dưới cùng, Christine tạo phần tử ClassifiedAdType complexType. Đây là một loại phần tử có chứa, theo thứ tự, một phần tử nội dung, một phần tử endDate và một phần tử startDate. Chuyển lên phần trên cùng, Christine định nghĩa phần tử ClassifiedList có một phần tử cũng chứa một chuỗi các phần tử. Tuy nhiên, trong trường hợp này, chuỗi không chứa hoặc có chứa nhiều phần tử thuộc loại ClassifiedAdType, tất cả có tên là ClassifiedAd.

Cho đến nay, chỉ với hai định nghĩa này, Christine đã trình bày hầu hết cấu trúc của tài liệu. Bây giờ tất cả mọi thứ mà Christine cần làm là thêm một định nghĩa cho thuộc tính adId.

Thêm các thuộc tính

Cần định nghĩa một thuộc tính có trong một phần tử complexType, như trong Liệt kê 8.

Liệt kê 8. Thêm một thuộc tính
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="ClassifiedList">
   <xsd:complexType>
      <xsd:sequence>
         <xsd:element name="ClassifiedAd" maxOccurs="unbounded"
 type="ClassifiedAdType"/>
      </xsd:sequence>
   </xsd:complexType>
</xsd:element>

<xsd:complexType name="ClassifiedAdType">
   <xsd:sequence>
       <xsd:element type="xsd:string" name="content" />
       <xsd:element type="xsd:string" name="endDate" />
       <xsd:element type="xsd:string" name="startDate" />
   </xsd:sequence>
   <xsd:attribute name="adId" type="xsd:integer" />
</xsd:complexType>

</xsd:schema>

Trong trường hợp này, Christine đã hạn chế nội dung của thuộc tính adId theo các số nguyên. Tuy nhiên, cô ấy có thể tạo ra một kiểu hạn chế nhiều hơn.

Sử dụng simpleTypes

Lược đồ (Schema) XML cung cấp nhiều khả năng khi nó đi vào định nghĩa nội dung thực tế mà tài liệu của bạn có thể chứa. Ví dụ, Christine có thể xác định rằng thuộc tính adId phải chứa chỉ các số nguyên lớn hơn hoặc bằng 1000 (xem Liệt kê 9).

Liệt kê 9. Hạn chế các giá trị
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

...

<xsd:complexType name="ClassifiedAdType">
   <xsd:sequence>
       <xsd:element type="xsd:string" name="content" />
       <xsd:element type="xsd:string" name="endDate" />
       <xsd:element type="xsd:string" name="startDate" />
   </xsd:sequence>
   <xsd:attribute name="adId" type="thousandOrGreater" />
</xsd:complexType>

<xsd:simpleType name="thousandOrGreater"> 
  <xsd:restriction base="xsd:integer"> 
     <xsd:minInclusive value="1000"/> 
  </xsd:restriction> 
</xsd:simpleType>

</xsd:schema>

Định nghĩa này không liên quan đến bất kỳ phần tử nào, do đó, Christine sử dụng một phần tử simpleType thay cho một phần tử complexType. Christine tạo ra một restriction (hạn chế) -- một hạn chế về loại dữ liệu -- với loại cơ sở là các số nguyên. Sau đó, Christine thêm một "khía cạnh" (facet) cho hạn chế đó, xác định rằng giá trị tối thiểu là 1000. Lược đồ XML định nghĩa một số lượng lớn các khía cạnh này cho bạn sử dụng. Một khi Christine tạo ra kiểu đó, cô ấy có thể tham chiếu nó trong định nghĩa thuộc tính. Bây giờ sau khi đã định nghĩa dữ liệu, Christine chuyển lược đồ đó cho Larry để anh ta có thể xây dựng WSDL thực tế.


Tạo một tài liệu WSDL

Trong khi Christine phụ trách về dữ liệu thực tế, thì Larry chịu trách nhiệm về thông báo thực tế để di chuyển qua lại giữa các dịch vụ và các ứng dụng của nó. Từ những thông báo đó, Larry tạo ra tài liệu WSDL.

Các thông báo

Bước đầu tiên của Larry là quyết định dịch vụ đó sẽ thực sự thực hiện các hàm nào và sau đó định nghĩa các thông báo cho các dịch vụ. Sau khi tham khảo ý kiến với các nhân viên còn lại của phòng này, Larry đến gần với một danh sách các hàm và các thông báo tương ứng của chúng và trong phần còn lại của phần này bạn sẽ xem xét các hàm này.

createNewAd

Hàm này nhận nội dung của đoạn quảng cáo tại ngày kết thúc của nó và sẽ quay trở lại ý tưởng cho đoạn quảng cáo mới được tạo ra (xem Liệt kê 10 và Liệt kê 11).

Liệt kê 10. createNewAdRequest (Nhập vào)
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

 <env:Body>
  <req:createNewAdRequest xmlns:req="http://daily-moon.com/classifieds/"> 
      <req:content>Vintage 1963 T-Bird...</req:content> 
      <req:endDate>4/30/07</req:endDate> 
  </req:createNewAdRequest>
 </env:Body>
Liệt kê 11. createNewAdResponse (Xuất ra)
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <env:Body>
  <res:createNewAdResponse xmlns:res="http://daily-moon.com/classifieds/"> 
         <res:newAdId>1138</res:newAdId> 
  </res:createNewAdResponse>
 </env:Body>

editExistingAd

Hàm này nhận một đoạn quảng cáo hiện có và thay thế nội dung của nó trong cơ sở dữ liệu. Hàm này trả về một giá trị đại số Bool (Boolean) nói rằng liệu hoạt động đó đã thành công chưa (xem Liệt kê 12 và Liệt kê 13).

Liệt kê 12. editExistingAdRequest (Nhập vào)
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <env:Body>
  <req:editExistingAdRequest xmlns:req="http://daily-moon.com/classifieds/"> 
     <req:ClassifiedAd> <req:id>1138</req:id> 
        <req:content>Vintage 1963 T-Bird...</req:content> 
        <req:startDate>4/1/2007</req:startDate> 
        <req:endDate>4/30/2007</req:endDate> 
     <req:ClassifiedAd> 
   </req:editExistingAdRequest >
 </env:Body>
Liệt kê 13. editExistingAdResponse (Xuất ra)
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <env:Body>
  <res:editExistingAdResponse xmlns:res="http://daily-moon.com/classifieds/"> 
      <res:isOK>true</res:isOK> 
  </res:editExistingAdResponse>
 </env:Body>

getExistingAds

Hàm này trả về một danh sách phần tử ClassifiedAds hiện có (xem Liệt kê 14 và Liệt kê 15).

Liệt kê 14. getExistingAdsRequest (Nhập vào)
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <env:Body>
  <req:getExistingAdsRequest xmlns:req="http://daily-moon.com/classifieds/"> 
  </req:getExistingAdsRequest>
 </env:Body>
Liệt kê 15. getExistingAdsResponse (Xuất ra)
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <env:Body>
  <res:getExistingAdsResponse xmlns:res="http://daily-moon.com/classifieds/"> 
      <res:ClassifiedList> 
         <res:ClassifiedAd> 
            <res:id>1138</res:id> 
            <res:content>Vintage 1963 T-Bird...</res:content> 
            <res:startDate>4/1/2007</res:startDate> 
            <res:endDate>4/30/2007</res:endDate> 
         </res:ClassifiedAd> 
         <res:ClassifiedAd> 
            <res:id>2883</res:id> 
            <res:content>Championship playoff tickets...</res:content> 
            <res:startDate>4/1/2007</res:startDate> 
            <res:endDate>4/30/2007</res:endDate> 
         </res:ClassifiedAd> 
      </res:ClassifiedList> 
   </res:getExistingAdsResponse >
</env:Body>

finalizeIssue

Hàm này là một hàm "chỉ nhập vào", nhận một ngày phát hành để thông qua lần cuối và không trả về thứ gì (xem Liệt kê 16).

Liệt kê 16. finalizeIssueRequest (Nhập vào)
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <env:Body>
  <req:finalizeIssueRequest xmlns:req="http://daily-moon.com/classifieds/"> 
           <req:issueDate>4/10/06</req:issueDate> 
  </req:FinalizeIssueRequest >
 </env:Body>

Mang theo các thông báo này, Larry bắt đầu tạo tài liệu WSDL thực tế..

Tạo tài liệu cơ bản

Larry bắt đầu với khung công tác cơ bản của một tài liệu WSDL (xem Liệt kê 17).

Liệt kê 17. Tài liệu WSDL cơ bản
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       targetNamespace="http://ws.apache.org/axis2">

<wsdl:types>
</wsdl:types>

<wsdl:message name="createNewAdRequestMessage">
</wsdl:message>

<wsdl:portType name="ClassifiedServicePortType">
</wsdl:portType>

<wsdl:binding name="ClassifiedServiceBinding">
</wsdl:binding>

<wsdl:service name="ClassifiedService">
</wsdl:service>

</wsdl:definitions>

Giống như các thông báo SOAP được WSDL định nghĩa, WSDL do XML tạo nên. Các định nghĩa cư trú trong phần tử definitions (các định nghĩa), như bạn có thể thấy ở đây. Bắt đầu từ phía dưới cùng, bạn định nghĩa phần tử service (dịch vụ). Phần tử service này sử dụng một phần tử binding (ràng buộc) cụ thể, đó là việc thực hiện của một portType. portType định nghĩa các hoạt động, do messages (các thông báo) tạo nên. Các thông báo bao gồm XML được định nghĩa trong phần types (các kiểu).

Phần tử definitions định nghĩa hai vùng tên. Vùng tên đầu tiên, sử dụng tiền tố wsdl:, cung cấp một vùng tên cho các phần tử thực tế tạo nên WSDL. Vùng tên thứ hai targetNamespace, định nghĩa vùng tên mà các mục được WSDL định nghĩa thuộc về vùng tên đó.

Larry bắt đầu bằng cách định nghĩa các loại.

Xác định các loại

Larry nhận các định nghĩa mà Christine cung cấp cho mình và tách chúng thành phần tử types, tạo một lược đồ mới trong tài liệu, như trong Liệt kê 18.

Liệt kê 18. Xác định các loại
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       xmlns:ns1="http://org.apache.axis2/xsd" 
       targetNamespace="http://ws.apache.org/axis2">

<wsdl:types>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
              targetNamespace="http://org.apache.axis2/xsd" 
              elementFormDefault="unqualified" attributeFormDefault="unqualified"> 
      
      <xs:element type="ns1:ClassifiedAd" name="ClassifiedAd" /> 
         <xs:complexType name="ClassifiedAd"> 
            <xs:sequence> <xs:element type="xs:int" name="id" /> 
               <xs:element type="xs:string" name="content" /> 
               <xs:element type="xs:string" name="endDate" /> 
               <xs:element type="xs:string" name="startDate" /> 
            </xs:sequence> 
          </xs:complexType> 

      <xs:element type="ns1:ClassifiedList" name="ClassifiedList" /> 
        <xs:complexType name="ClassifiedList"> 
           <xs:sequence> 
             <xs:element minOccurs="0" type="ns1:ClassifiedAd" 
                            name="ClassifiedAd" maxOccurs="unbounded" /> 
           </xs:sequence> 
      </xs:complexType> 

      <xs:element name="createNewAdRequest"> 
      <xs:complexType> 
           <xs:sequence> 
              <xs:element type="xs:string" name="content" /> 
              <xs:element type="xs:string" name="endDate" /> 
           </xs:sequence> 
      </xs:complexType> 
      </xs:element> 

      <xs:element name="createNewAdResponse"> 
          <xs:complexType> 
              <xs:sequence> 
                <xs:element type="xs:int" name="newAdId" /> 
              </xs:sequence> 
          </xs:complexType> 
       </xs:element> 

       <xs:element name="editExistingAdRequest"> 
           <xs:complexType> 
              <xs:sequence> 
                 <xs:element type="ns1:ClassifiedAd" name="ClassifiedAd" /> 
              </xs:sequence> 
           </xs:complexType> 
       </xs:element> 

       <xs:element name="editExistingAdResponse"> 
            <xs:complexType> 
               <xs:sequence> 
                  <xs:element type="xs:boolean" name="isOK" /> 
               </xs:sequence> 
            </xs:complexType> 
       </xs:element> 

       <xs:element name="getExistingAdsRequest"> 
           <xs:complexType /> 
       </xs:element> 

       <xs:element name="getExistingAdsResponse"> 
           <xs:complexType> 
              <xs:sequence> 
                  <xs:element type="ns1:ClassifiedList" name="ClassifiedList" /> 
              </xs:sequence> 
           </xs:complexType> 
       </xs:element> 

       <xs:element name="finalizeIssueRequest"> 
          <xs:complexType> 
              <xs:sequence> 
                  <xs:element type="xs:string" name="issueDate" /> 
              </xs:sequence> 
          </xs:complexType> 
       </xs:element> 

</xs:schema>

</wsdl:types>

</wsdl:definitions>

Bắt đầu từ trên cùng, lưu ý rằng chúng ta có hai phần của các vùng tên. Đầu tiên là trong chính phần tử schema (lược đồ). Ở đây Larry định nghĩa hai vùng tên. Vùng tên đầu tiên, bắt đầu bằng xs:, là vùng tên của Lược đồ XML. Vùng tên thứ hai, targetNamespace, định nghĩa vùng tên mà lược đồ tạo ra các định nghĩa thuộc về vùng tên này. Nói cách khác, khi định nghĩa thứ hai tạo ra một complexType gọi là ClassifiedAd, định nghĩa đó thuộc về vùng tên http://org.apache.axis2/xsd. Tuy nhiên, để tham chiếu vùng tên đó, Larry cần tạo ra bí danh khác. Bạn có thể thấy rằng bí danh trên phần tử các định nghĩa, bắt đầu bằng ns1:. (Larry đã không thể chỉ dễ dàng đưa ra các định nghĩa đó trên các phần tử lược đồ (schema), mà anh ta sẽ cần nó bên ngoài phần tử lược đồ sau này). Hai thuộc tính mới nhất, elementFormDefaultattributeFormDefault, tham chiếu xem có hay không có các phần tử và các thuộc tính được dự kiến sẽ có các tiền tố vùng tên.

Bốn định nghĩa đầu tiên là từ lược đồ mà Christine đã cung cấp cho Larry, nhưng phần còn lại định nghĩa các thông báo do Larry tạo ra trước đó.

Một lưu ý về các vùng tên

Trong XML, như trong nhiều ngôn ngữ lập trình, luôn cần thiết xác định một "vùng tên" cho các phần tử và các thuộc tính khác nhau. Điều này cung cấp cho bạn một phương tiện để phân biệt giữa các phần tử có cùng tên, nhưng có các mục đích khác nhau và có lẽ có các nguồn gốc khác nhau. XML tham chiếu một vùng tên bằng một URI. Ví dụ, vùng tên lược đồ XML là http://www.w3.org/2001/XMLSchema. Tuy nhiên, để cho thuận tiện, vùng tên cũng được gán một bí danh hoặc tiền tố. Ví dụ, ở đây vùng tên lược đồ (schema) có một tiền tố là xs:. Hãy nhớ rằng bí danh chỉ là một bí danh mà thôi. Cái chính là ở URI. Do đó, các phần tử hoặc các thuộc tính là một phần của vùng tên ns1: cũng là một phần của targetNamespace của lược đồ đó.

Tạo các thông báo

Với các kiểu tại chỗ, Larry có thể định nghĩa các thông báo sẽ chuyển qua lại trong phong bì SOAP (xem Liệt kê 19).

Liệt kê 19. Tạo ra các thông báo
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       xmlns:ns1="http://org.apache.axis2/xsd" 
       targetNamespace="http://ws.apache.org/axis2">

<wsdl:types>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
         targetNamespace="http://org.apache.axis2/xsd" 
         elementFormDefault="unqualified" 
         attributeFormDefault="unqualified">
...
    <xs:element name="createNewAdRequest">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:string" name="content" />
          <xs:element type="xs:string" name="endDate" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>

    <xs:element name="createNewAdResponse">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:int" name="newAdId" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>

...
  </xs:schema>

</wsdl:types>

<wsdl:message name="createNewAdRequestMessage">
  <wsdl:part name="part1" element="ns1:createNewAdRequest" />
</wsdl:message>

<wsdl:message name="createNewAdResponseMessage"> 
     <wsdl:part name="part1" element="ns1:createNewAdResponse" /> 
</wsdl:message> 

<wsdl:message name="getExistingAdsResponseMessage"> 
     <wsdl:part name="part1" element="ns1:getExistingAdsResponse" /> 
</wsdl:message> 

<wsdl:message name="editExistingAdRequestMessage"> 
     <wsdl:part name="part1" element="ns1:editExistingAdRequest" /> 
</wsdl:message> 

<wsdl:message name="getExistingAdsRequestMessage"> 
     <wsdl:part name="part1" element="ns1:getExistingAdsRequest" /> 
</wsdl:message> 

<wsdl:message name="editExistingAdResponseMessage"> 
     <wsdl:part name="part1" element="ns1:editExistingAdResponse" /> 
</wsdl:message> 

<wsdl:message name="finalizeIssueRequestMessage"> 
       <wsdl:part name="part1" element="ns1:finalizeIssueRequest" /> 
</wsdl:message>

<wsdl:portType name="ClassifiedServicePortType">
</wsdl:portType>

<wsdl:binding name="ClassifiedServiceBinding">
</wsdl:binding>

<wsdl:service name="ClassifiedService">
</wsdl:service>

</wsdl:definitions>

Mỗi thông báo có một name (tên) để bạn có thể tham chiếu nó sau này. Trong mỗi thông báo, bạn định nghĩa một hoặc nhiều part (phần). Lưu ý rằng WSDL 2.0 cho phép chỉ có một part cho mỗi message (thông báo ), do đó, ở đây Larry vẫn trung thành với quy ước đó .

Mỗi part có một name và tên của element (phần tử) tạo nên part đó. Tên phần tử tham chiếu lại các kiểu được quy định trong phần tử types. Lưu ý rằng tên của phần tử này có tiền tố ns1: đặt trước, tiền tố cho vùng tên khớp với targetNamespace cho lược đồ đó. Nói cách khác, khi Larry đã tạo ra định nghĩa cho createNewAdResponse, thì định nghĩa đó đã đi vào vùng tên http://org.apache.axis2/xsd và vì tiền tố ns1: cũng tham chiếu đến vùng tên đó, nên bạn có thể tham chiếu ngay bây giờ bằng cách sử dụng tiền tố đó.

Định nghĩa giao diện (portType)

Các thông báo không thực hiện bất kỳ điều tốt nào cho riêng mình, do đó Larry cần kết hợp các thông báo với các hoạt động cụ thể. Các hoạt động (operation) này là một phần của portType. portType chỉ chứa định nghĩa và không chứa các việc thực hiện. Ở khía cạnh đó, portType là giống hệt như một giao diện. Trong thực tế, trong WSDL2.0, tên của portType đã được thay đổi thành interface (giao diện). Larry tạo một hoạt động cho từng hàm (xem Liệt kê 20).

Liệt kê 20. Thêm các hoạt động
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       xmlns:tns=http://ws.apache.org/axis2
       xmlns:ns1="http://org.apache.axis2/xsd" 
       targetNamespace="http://ws.apache.org/axis2">

<wsdl:types>
...
</wsdl:types>

<wsdl:message name="createNewAdRequestMessage">
  <wsdl:part name="part1" element="ns1:createNewAdRequest" />
</wsdl:message>

<wsdl:message name="createNewAdResponseMessage">
  <wsdl:part name="part1" element="ns1:createNewAdResponse" />
</wsdl:message>
...
<wsdl:message name="finalizeIssueRequestMessage">
  <wsdl:part name="part1" element="ns1:finalizeIssueRequest" />
</wsdl:message>

<wsdl:portType name="ClassifiedServicePortType">

<wsdl:operation name="finalizeIssue"> 
   <wsdl:input message="tns:finalizeIssueRequestMessage" /> 
</wsdl:operation> 

<wsdl:operation name="createNewAd"> 
    <wsdl:input message="tns:createNewAdRequestMessage" /> 
    <wsdl:output message="tns:createNewAdResponseMessage" /> 
</wsdl:operation> 

<wsdl:operation name="editExistingAd"> 
    <wsdl:input message="tns:editExistingAdRequestMessage" /> 
    <wsdl:output message="tns:editExistingAdResponseMessage" /> 
</wsdl:operation> 

<wsdl:operation name="getExistingAds"> 
    <wsdl:input message="tns:getExistingAdsRequestMessage" /> 
    <wsdl:output message="tns:getExistingAdsResponseMessage" /> 
</wsdl:operation>

</wsdl:portType>

<wsdl:binding name="ClassifiedServiceBinding">
</wsdl:binding>

<wsdl:service name="ClassifiedService">
</wsdl:service>

</wsdl:definitions>

Larry tạo ra hai kiểu thông báo. Một, như là finalizeIssue, là một hoạt động "chỉ-nhập vào", trong đó nó chỉ có một thông báo nhập vào. Đó là thông báo, finalizeIssueRequest, đã được định nghĩa trước đó và giống như trước, chúng ta tạo một tiền tố mới, tns:, để tham chiếu đến vùng tên có tiền tố đó

Kiểu hoạt động thứ hai là một hoạt động yêu cầu/đáp ứng, chẳng hạn như createNewAd. Trong trường hợp này, Larry định nghĩa cả các thông báo nhập vào lẫn xuất ra.

Định nghĩa các ràng buộc

Nếu portType giống như một giao diện, thì binding (ràng buộc) là sự thực hiện của giao diện đó (xem Liệt kê 21).

Liệt kê 21. Tạo ràng buộc
<wsdl:definitions 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       xmlns:tns="http://ws.apache.org/axis2"
       xmlns:ns1="http://org.apache.axis2/xsd" 
       targetNamespace="http://ws.apache.org/axis2">

<wsdl:types>
</wsdl:types>

<wsdl:message name="createNewAdRequestMessage">
  <wsdl:part name="part1" element="ns1:createNewAdRequest" />
</wsdl:message>
...
<wsdl:portType name="ClassifiedServicePortType">

  <wsdl:operation name="finalizeIssue">
    <wsdl:input message="tns:finalizeIssueRequestMessage" />
  </wsdl:operation>

  <wsdl:operation name="createNewAd">
    <wsdl:input message="tns:createNewAdRequestMessage" />
    <wsdl:output message="tns:createNewAdResponseMessage" />
  </wsdl:operation>

  <wsdl:operation name="editExistingAd">
    <wsdl:input message="tns:editExistingAdRequestMessage" />
    <wsdl:output message="tns:editExistingAdResponseMessage" />
  </wsdl:operation>

  <wsdl:operation name="getExistingAds">
    <wsdl:input message="tns:getExistingAdsRequestMessage" />
    <wsdl:output message="tns:getExistingAdsResponseMessage" />
  </wsdl:operation>

</wsdl:portType>

<wsdl:binding name="ClassifiedServiceBinding" 

type="tns:ClassifiedServicePortType"> 
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> 

<wsdl:operation name="createNewAd"> 
  <soap:operation soapAction="createNewAd" style="document" /> 
  <wsdl:input> 
   <soap:body use="literal" namespace="http://daily-moon.com/classifieds" /> 
  </wsdl:input> 
  <wsdl:output> 
   <soap:body use="literal" namespace="http://daily-moon.com/classifieds" /> 
  </wsdl:output> 
</wsdl:operation> 

<wsdl:operation name="finalizeIssue"> 
   <soap:operation soapAction="finalizeIssue" style="document" /> 
   <wsdl:input> 
      <soap:body use="literal" namespace="http://daily-moon.com/classifieds" /> 
   </wsdl:input> 
</wsdl:operation> 

<wsdl:operation name="editExistingAd"> 
   <soap:operation soapAction="editExistingAd" style="document" /> 
   <wsdl:input> 
      <soap:body use="literal" namespace="http://daily-moon.com/classifieds" /> 
   </wsdl:input> 
   <wsdl:output> <
   soap:body use="literal" namespace="http://daily-moon.com/classifieds" /> 
   </wsdl:output> 
</wsdl:operation> 

<wsdl:operation name="getExistingAds"> 
   <soap:operation soapAction="getExistingAds" style="document" /> 
   <wsdl:input> 
       <soap:body use="literal" namespace="http://daily-moon.com/classifieds" /> 
   </wsdl:input> 
   <wsdl:output> 
       <soap:body use="literal" namespace="http://daily-moon.com/classifieds" /> 
   </wsdl:output> 
</wsdl:operation>

</wsdl:binding>

<wsdl:service name="ClassifiedService">
</wsdl:service>

</wsdl:definitions>

Trước tiên, lưu ý rằng type (kiểu) ràng buộc tham chiếu ClassifiedServicePortType mà Larry đã tạo ra rồi. Thứ hai, lưu ý việc bổ sung thêm vùng tên soap:. binding này dành cho thông báo SOAP trên HTTP, như bạn có thể thấy trong phần tử soap:binding. Lưu ý đến thuộc tính transport (vận chuyển). (Đừng lo lắng về phong cách (style) vội, chúng ta sẽ xem xét nó trong phần tiếp theo).

Đối với mỗi hoạt động, chia sẻ tên đã có trong portType, bây giờ Larry thêm một phần tử soap:operation. Phần tử này thực hiện hai hoạt động. Một, nó xác định rằng trên thực tế, đây là một hoạt động SOAP. Thứ hai là xác định một soapAction, một tiêu đề HTTP được gửi trước thông báo SOAP thực tế. Máy chủ có thể sử dụng tiêu đề này để định tuyến yêu cầu cho hoạt động thích hợp.

Lưu ý rằng soapAction đã luôn có vấn đề nào đó và trong khi nó là tùy chọn trong WSDL 1.1, thì nó đã được gỡ bỏ hoàn toàn khỏi WSDL 2.0.

Mỗi hoạt động cũng định nghĩa một thông báo input (nhập vào) và một thông báo output (xuất ra) (hoặc, trong trường hợp của thông báo chỉ-nhập vào, chỉ cần một thông báo input ), nhưng bây giờ Larry cũng thêm thông tin SOAP cụ thể. Một lần nữa, đừng lo lắng về thuộc tính use (sử dụng), chúng ta cũng sẽ xem xét thuộc tính đó sau. Phần tử này cũng định nghĩa vùng tên cho nội dung của tải trọng.

Định nghĩa dịch vụ

Với cả hai giao diện và sự ràng buộc được định nghĩa, đây là lúc định nghĩa dịch vụ (xem Liệt kê 22).

Liệt kê 22. Định nghĩa dịch vụ
...
<wsdl:binding name="ClassifiedServiceBinding" 
                     type="tns:ClassifiedServicePortType">

...
</wsdl:binding>

<wsdl:service name="ClassifiedService">
  <wsdl:port name="ClassifiedServicePort" binding="tns:ClassifiedServiceBinding"> 
     <soap:address location= "http://127.0.0.1:8080/axis2/services/ClassifiedService" /> 
  </wsdl:port>
</wsdl:service>

</wsdl:definitions>

Một service (dịch vụ) có thể có nhiều hơn một điểm đầu cuối, với mỗi điểm đầu cuối được xác định bằng một phần tử port (cổng) riêng của nó. Phần tử port tương ứng với một ràng buộc cụ thể và bao gồm thông tin về cách truy cập nó. Trong trường hợp này, Larry quy định rằng có thể truy cập cổng này thông qua SOAP tại http://127.0.0.1:8080/axis2/services/ClassifiedService.

Tạo tài liệu dịch vụ

Với dịch vụ đã xác định, có thêm một bước nữa. Đó là tùy chọn, nhưng bạn thực sự cần thực hiện bước đó. WSDL cho phép bạn thêm một phần tử tài liệu cho bất kỳ phần tử nào trong tài liệu WSDL. Liệt kê 23 cung cấp một ví dụ.

Liệt kê 23. Tạo tài liệu dịch vụ
...
<wsdl:portType name="ClassifiedServicePortType">

  <wsdl:document>The finalizeIssue operation is an "in-only" operation that tells 
            the system not to accept any more ads for a particular date.</wsdl:document>

  <wsdl:operation name="finalizeIssue">
    <wsdl:input message="tns:finalizeIssueRequestMessage" />
  </wsdl:operation>
...

Có rất nhiều thứ hơn với WSDL, nhưng những thứ đó là những điều cơ bản. Tuy nhiên, trước khi chúng ta tiếp tục, chúng ta hãy xem nhanh một vài tình huống cao cấp hơn mà bạn có thể chạy trong đó.

Các ràng buộc khác ngoài SOAP trên HTTP

Mặc dù việc sử dụng WSDL phổ biến nhất là định nghĩa SOAP trên HTTP, không hề có cách duy nhất để xác định một dịch vụ Web. Ví dụ, Larry có thể tạo ra một ràng buộc để sử dụng SOAP qua e-mail và cho phép nó với hoạt động finalizeIssue duy nhất (xem Liệt kê 24).

Liệt kê 24. Thêm một ràng buộc bổ sung
...
<wsdl:binding name="ClassifiedServiceEmailBinding" 
                          type="tns:ClassifiedServicePortType">

   <soap:binding style="document" transport="http://example.com/smtp"/>

   <wsdl:operation name="finalizeIssue">
     <wsdl:input message="tns:finalizeIssueRequestMessage">
         <soap:body parts="body" use="literal"/>
      </wsdl:input>
   </wsdl:operation>

</wsdl:binding>

<wsdl:service name="ClassifiedService">
  <wsdl:port name="ClassifiedServicePort" 
                    binding="tns:ClassifiedServiceBinding">
    <soap:address location=
       "http://127.0.0.1:8080/axis2/services/ClassifiedService" />
  </wsdl:port>

  <wsdl:port name="ClassifiedServiceEmailPort" 
              binding="tns:ClassifiedServiceEmailBinding"> 
      <soap:address location="mailto:finalizeIssue@daily-moon.com" /> 
  </wsdl:port>
</wsdl:service>

</wsdl:definitions>

Ở đây Larry đã thêm vào một ràng buộc thứ hai, ClassifiedServiceEmailBinding. Giống như ràng buộc ClassifiedServiceBinding, ràng buộc này được dựa trên ClassifiedServicePortType portType. Tuy nhiên, trong trường hợp này, Larry sử dụng SMTP (giao thức thường dùng để gửi e-mail) thay cho HTTP. Sau đó Larry có thể thêm một cổng thứ hai cho dịch vụ đó, dựa vào nó trên ràng buộc mới và sử dụng một e-mail URL như là vị trí thay cho một HTTP URL. Bạn có thể tạo ra nhiều cổng như bạn muốn cho một dịch vụ duy nhất.

SOAP và Mime

Một chủ đề khác mà giải pháp không rõ ràng ngay cho chủ đề đó là việc sử dụng SOAP với các tệp đính kèm. Do thông báo có nhiều hơn một tài liệu XML, nên khi sử dụng WSDL bạn sẽ xác định thông báo như thế nào? Câu trả lời liên quan đến thực tế là thông báo được gửi đi bằng cách sử dụng "MINE nhiều phần" (multipart MIME). May mắn thay, bạn có thể xác định MIME nhiều phần trong tài liệu WSDL. Ví dụ, Larry muốn quy định một hoạt động, trong đó những người sử dụng chỉnh sửa một đoạn quảng cáo hiện có, nhận lại một bằng chứng PDF của đoạn quảng cáo đó (xem Liệt kê 25).

Liệt kê 25. Xác định một thông báo nhiều phần
...
  <wsdl:operation name="editExistingAd">
    <soap:operation soapAction="editExistingAd" 
style="document" />
    <wsdl:input>
      <soap:body use="literal" 
                namespace="http://daily-moon.com/classifieds" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" 
                namespace="http://daily-moon.com/classifieds" />
      <mime:multipartRelated> 
           <mime:part> 
               <soap:body parts="body" use="literal"/> 
           </mime:part> 
           <mime:part> 
               <mime:content part="docs" type="text/html"/> 
           </mime:part> 
           <mime:part> 
               <mime:content part="proof" type="image/gif"/> 
               <mime:content part="proof" type="image/jpeg"/> 
           </mime:part> 
      </mime:multipartRelated>
    </wsdl:output>
...

Trong trường hợp này, thông báo trả về bao gồm SOAP, một tài liệu HTML và hai tệp hình ảnh.

Đến với WSDL 2.0

Trong suốt phần này, tôi đã cố gắng chỉ ra một số trong những chỗ ở đó WSDL 2.0 sẽ khác với WSDL 1.1, chẳng hạn như sự thay đổi từ các portType nhiều tiềm năng bằng một interface (giao diện) duy nhất và thực tế là các thông báo message có thể không còn có nhiều hơn một phần. Những thay đổi khác cũng theo chiều ngang.

Một số nhân tố thúc đẩy những sự thay đổi này, nhưng chủ yếu là do các mục đích về tính tương thích dẫn đến các nhân tố đó -- các cấu trúc không dựa trên pháp lý theo WS-I's Basic Profile (Hiện trạng cơ bản của Các dịch vụ Web-Tính tương thích) nói chung bị cấm -- hoặc làm cho nó dễ dàng sử dụng WSDL với các đặc tả SOAP mở rộng hơn. Ví dụ, WSDL 2.0 sử dụng nhiều hơn một mô hình "thành phần", thích hợp hơn cho việc tích hợp với các yêu cầu của các đặc tả như Các dịch vụ Web-Choreography (WS-Choreography).

Sự thay đổi khác liên quan đến đặc tả chính thức của "các mô hình trao đổi thông báo". Thay vì chỉ hy vọng những người sử dụng xem xét liệu có một thông báo nhập vào và thông báo xuất ra hay chỉ có thông báo một nhập vào hay không, WSDL 2.0 cho phép bạn tuyên bố rõ bạn đang sử dụng mô hình nào (xem Liệt kê 26).

Liệt kê 26. Xác định các mô hình trao đổi thông báo
...
  <wsdl:operation name="finalizeIssue"
            pattern=http://www.w3.org/2006/01/wsdl/in-only">
    <wsdl:input message="tns:finalizeIssueRequestMessage" />
  </wsdl:operation>

  <wsdl:operation name="createNewAd"
            pattern="http://www.w3.org/2006/01/wsdl/in-out">
    <wsdl:input message="tns:createNewAdRequestMessage" />
    <wsdl:output message="tns:createNewAdResponseMessage" />
  </wsdl:operation>
...

Bây giờ hãy bắt đầu phần dưới cùng của các phong cách WSDL.


Các phong cách WSDL

Một trong những nhiệm vụ khó hiểu nhất đối với các nhà phát triển mới học WSDL là việc lựa chọn một phong cách cho một tài liệu. Hãy xem xét các sự lựa chọn khác nhau và chúng ảnh hưởng đến cả tài liệu WSDL lẫn tài liệu SOAP như thế nào.

Các phong cách lập trình và mã hóa

Trong thế giới XML, nói chung có hai loại người: những người nghĩ về XML như là một định dạng dữ liệu và những người nghĩ về XML như là sự đánh dấu tài liệu. Nói chung, không bao giờ đáp ứng cho cả hai. Phần nào, sự phân chia này tiếp tục trong các dịch vụ Web. Có những người coi XML là một dạng dựa trên XML của Cuộc gọi theo giao thức từ xa (Remote Procedure Call) và có những người coi XML là một phương tiện để nhận được thông tin XML từ một nơi này đến nơi khác.

Về WSDL, điều này diễn ra trong sự lựa chọn về "phong cách" của thông báo. Khi bạn tạo sự ràng buộc, bạn có một sự lựa chọn về phong cách tài liệu, như Larry đã chọn cho dịch vụ Rao vặt hoặc phong cách RPC. Chẳng có phong cách nào vốn là "đúng" hay là "sai" cả. Nhưng cả hai đều có những ưu và nhược điểm của mình.

Khi sử dụng phong cách RPC, tên của phương thức được thực hiện cũng là tên của phần tử gốc của tải trọng. Nhưng bạn nói, hãy chờ đợi. Đó không phải là cách cấu trúc WSDL Rao vặt phải không? Vâng, đúng và không đúng. Đúng, tên của phần tử gốc giống như tên của phương thức mà chúng ta muốn dịch vụ này thực hiện. Tuy nhiên, theo một số nghĩa, đây là một sự trùng hợp; Larry rõ ràng đã cấu trúc các dịch vụ theo cách đó.

Hãy xem xét các lựa chọn khác nhau và cách chúng diễn ra dưới dạng WSDL và SOAP.

Tài liệu/bằng chữ

Phong cách tài liệu/bằng chữ có nghĩa là tải trọng có chứa chỉ các dữ liệu thực tế được chuyển tới dịch vụ. Bất kỳ sự cần thiết định tuyến nào để nhận được thông báo đến đích của nó cần được thực hiện theo một vài cách khác, chẳng hạn như thông qua tiêu đề soapAction hoặc một URL cụ thể cho dịch vụ đó.

Một thông báo đơn giản và dễ hiểu (xem Liệt kê 27).

Liệt kê 27. Một thông báo tài liệu/bằng chữ
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <env:Body>
     <req:content>Vintage 1963 T-Bird...</req:content> 
      <req:endDate>4/30/07</req:endDate>
  </env:Body>
</env:Envelope>

Chú ý rằng không có phần tử gốc nào cho tải trọng này. Trong tệp WSDL, bạn định nghĩa các phần tử trực tiếp và thêm chúng vào thông báo (xem Liệt kê 28).

Liệt kê 28. WSDL tài liệu/bằng chữ
...
<wsdl:types>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
         targetNamespace="http://org.apache.axis2/xsd" 
         elementFormDefault="unqualified" 
         attributeFormDefault="unqualified">

...
    <xs:element type="xs:string" name="content" /> 
    <xs:element type="xs:string" name="endDate" />
...
  </xs:schema>

</wsdl:types>

<wsdl:message name="createNewAdRequestMessage">
  <wsdl:part name="part1" element="ns1:content" />
  <wsdl:part name="part2" element="ns1:endDate" />
</wsdl:message>
...
<wsdl:portType name="ClassifiedServicePortType">

...
  <wsdl:operation name="createNewAd">
    <wsdl:input message="tns:createNewAdRequestMessage" />
    <wsdl:output message="tns:createNewAdResponseMessage" />
  </wsdl:operation>
...
</wsdl:portType>
...
<wsdl:binding name="ClassifiedServiceBinding"
 type="tns:ClassifiedServicePortType">

  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
    style="document" />

  <wsdl:operation name="createNewAd">
    <soap:operation soapAction="createNewAd" style="document" />
    <wsdl:input>
      <soap:body use="literal" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" />
    </wsdl:output>
  </wsdl:operation>

...
</wsdl:binding>
...

Lưu ý rằng theo phong cách tài liệu, tất cả các phần tử là một phần của tải trọng cũng có các định nghĩa trong lược đồ đó. Ngoài ra, lưu ý rằng thông báo có hai phần khác nhau, mỗi phần tham chiếu một phần tử cụ thể.

Phong cách tài liệu/bằng chữ/được bọc lại

Hướng dẫn này sử dụng phong cách tài liệu/bằng chữ/được bọc lại (document/literal/wrapped). Phong cách này giống như phong cách tài liệu/bằng chữ, trừ tải trọng có một phần tử gốc. Điều này có lợi thế do bao gồm tên của phương thức để thực hiện (mặc dù điều này không phải là một yêu cầu), cũng như tuân thủ các yêu cầu của WS-I Basic Profil. Nhắc lại, ở đây là một thông báo đơn giản (xem Liệt kê 29).

Liệt kê 29. Một thông báo tài liệu/bằng chữ/ được bọc lại
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <env:Body>
  <req:createNewAdRequest 
              xmlns:req="http://daily-moon.com/classifieds/">
     <req:content>Vintage 1963 T-Bird...</req:content>
     <req:endDate>4/30/07</req:endDate>
  </req:createNewAdRequest>
 </env:Body>
</env:Envelope>

Để cho trọn vẹn, đây là WSDL có liên quan (xem Liệt kê 30).

Liệt kê 30. WSDL của phong cách tài liệu/bằng chữ/được bọc lại
...
<wsdl:types>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
         targetNamespace="http://org.apache.axis2/xsd" 
         elementFormDefault="unqualified" 
         attributeFormDefault="unqualified">
...
    <xs:element name="createNewAdRequest"> 
       <xs:complexType> 
         <xs:sequence> 
            <xs:element type="xs:string" name="content" /> 
            <xs:element type="xs:string" name="endDate" /> 
         </xs:sequence> 
       </xs:complexType> 
    </xs:element>
...
  </xs:schema>

</wsdl:types>

<wsdl:message name="createNewAdRequestMessage">
  <wsdl:part name="part1" element="ns1:createNewAdRequest"
 />
</wsdl:message>
...
<wsdl:portType name="ClassifiedServicePortType">

  <wsdl:operation name="createNewAd">
    <wsdl:input message="tns:createNewAdRequestMessage" />
    <wsdl:output message="tns:createNewAdResponseMessage" />
  </wsdl:operation>
...
</wsdl:portType>
...
<wsdl:binding name="ClassifiedServiceBinding"
 type="tns:ClassifiedServicePortType">

  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />

  <wsdl:operation name="createNewAd">
    <soap:operation soapAction="createNewAd" style="document" />
    <wsdl:input>
      <soap:body use="literal" namespace="http://ws.apache.org/axis2" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" namespace="http://ws.apache.org/axis2" />
    </wsdl:output>
  </wsdl:operation>
...
</wsdl:binding>
...

Một lần nữa, tất cả các phần tử trong tải trọng được định nghĩa trong lược đồ này.

RPC/bằng chữ

Phong cách RPC xử lý những thứ này theo một cách hơi khác một chút. Đây là WSDL thích hợp định nghĩa cái gì đưa vào trong thông báo và không phải là lược đồ. Ví dụ, xem xét thông báo SOAP này (xem Liệt kê 31).

Liệt kê 31. Một thông báo RPC/bằng chữ
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <env:Body>

  <req:createNewAdRequest xmlns:req="http://daily-moon.com/classifieds/">
     <req:content>Vintage 1963 T-Bird...</req:content>
     <req:endDate>4/30/07</req:endDate>
  </req:createNewAdRequest>
 </env:Body>
</env:Envelope>

Chính thông báo này giống với phong cách tài liệu/bằng chữ/được bọc lại, nhưng WSDL lại rất khác nhau (xem Liệt kê 32).

Liệt kê 32. WSDL cho một thông báo RPC/bằng chữ
...
<wsdl:types>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
         targetNamespace="http://org.apache.axis2/xsd" 
         elementFormDefault="unqualified" 
         attributeFormDefault="unqualified">
...
  </xs:schema>

</wsdl:types>

<wsdl:message name="createNewAdRequest">
  <wsdl:part name="content" element="xsd:string" />
  <wsdl:part name="endDate" element="xsd:string" />
</wsdl:message>

...
<wsdl:portType name="ClassifiedServicePortType">

  <wsdl:operation name="createNewAd">
    <wsdl:input message="tns:createNewAdRequest" />
    <wsdl:output message="tns:createNewAdResponseMessage" />
  </wsdl:operation>
...
</wsdl:portType>
...
<wsdl:binding name="ClassifiedServiceBinding" type="tns:ClassifiedServicePortType">

  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />

  <wsdl:operation name="createNewAd">
    <soap:operation soapAction="createNewAd" style="rpc" />
    <wsdl:input>
      <soap:body use="literal" namespace="http://ws.apache.org/axis2" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" namespace="http://ws.apache.org/axis2" />
    </wsdl:output>
  </wsdl:operation>
...
</wsdl:binding>
...

Trước tiên, lưu ý rằng trên thực tế người ta không định nghĩa thứ gì trong lược đồ này. Thay vào đó, message (thông báo) mang tên của phương thức được thực hiện và các message part (bộ phận thông báo) trực tiếp xác định mỗi phần tử. Ngoài ra cũng lưu ý rằng trong phong cách RPC, tên của một bộ phận thông báo là quan trọng; nó là tên của phần tử trong tải trọng này. Các loại thông báo được định nghĩa trực tiếp. (Tất nhiên, điều này không có nghĩa là bạn không thể có những phần tử phức tạp làm một phần của tải trọng của bạn, nhưng vì phong cách này có nghĩa là để giả lập một cuộc gọi thủ tục từ xa, điều đó không phải là một vấn đề).

Trong portType, khi bạn chỉ định một thông báo, bạn tham chiếu trực tiếp thông báo đó như được tạo với những phần tử đó. Sau đó, theo ràng buộc, bằng cách xác định phong cách RPC, cách làm cho tất cả mọi thứ của thông báo này chuyển thành thông báo SOAP sẽ trở nên rõ ràng.

RPC/mã hóa

Phong cách xem xét cuối cùng là phong cách RPC/mã hóa. Phong cách này cũng tương tự như phong cách RPC/bằng chữ, trừ ra thông báo SOAP định nghĩa thông tin kiểu thực tế (xem Liệt kê 33).

Liệt kê 33. Thông báo SOAP RPC/mã hóa
<env:Envelope 
       xmlns:env="http://schemas.xmlSOAP.org/SOAP/envelope/" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <env:Body>
     <req:createNewAdRequest xmlns:req="http://daily-moon.com/classifieds/">
       <req:content xsi:type="xs:string">Vintage 1963 T-Bird...</req:content>
       <req:endDate xsi:type="xs:string">4/30/07</req:endDate>
     </req:createNewAdRequest>
   </env:Body>
</env:Envelope>

WSDL dùng để xác định thông báo tương tự như RPC/bằng chữ, nhưng thông tin mã hóa bổ sung được thêm vào ràng buộc đó (xem Liệt kê 34).

Liệt kê 34. WSDL RPC/mã hóa
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       xmlns:tns="http://ws.apache.org/axis2"

       xmlns:axis2="http://ws.apache.org/axis2"
       xmlns:ns1="http://org.apache.axis2/xsd" 
 
       targetNamespace="http://ws.apache.org/axis2">

<wsdl:types>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
         targetNamespace="http://org.apache.axis2/xsd" 
         elementFormDefault="unqualified" 
         attributeFormDefault="unqualified">
...
  </xs:schema>

</wsdl:types>

<wsdl:message name="createNewAdRequest">
  <wsdl:part name="content" element="xsd:string" />
  <wsdl:part name="endDate" element="xsd:string" />
</wsdl:message>
...
<wsdl:portType name="ClassifiedServicePortType">

  <wsdl:operation name="createNewAd">
    <wsdl:input message="tns:createNewAdRequest" />
    <wsdl:output message="tns:createNewAdResponse" />
  </wsdl:operation>
...
</wsdl:portType>

<wsdl:binding name="ClassifiedServiceBinding"
 type="tns:ClassifiedServicePortType">

  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
style="rpc" />

  <wsdl:operation name="createNewAd">
    <soap:operation soapAction="createNewAd" style="document" />
    <wsdl:input>
      <soap:body use="encoded" 
encodingStyle=http://schemas.xmlsoap.org/soap/encoding/
  namespace="http://ws.apache.org/axis2" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" namespace=
"http://ws.apache.org/axis2" />
    </wsdl:output>
  </wsdl:operation>

...
</wsdl:binding>
...

Khi bạn tạo một tệp WSDL bằng tay, bạn phải xử lý tất cả mọi thứ của chính tệp này. May mắn thay, bạn không luôn phải tạo ra tệp này bằng tay.


Tạo mã bằng cách sử dụng WSDL

Gene và Francis là các lập trình viên của nhóm làm việc tại tờ báo, được đưa khỏi phòng Công nghệ thông tin (CNTT) mỗi khi phòng chuyên mục rao vặt có thể kéo họ ra để làm việc cho một trong các dự án riêng của phòng này. Họ sẽ tiếp tục công việc tạo các mã WSDL bằng cách tiếp cận nó theo hai cách; Gene sẽ tập trung vào việc chuyển mã từ Java sang WSDL và Francis sẽ chuyển mã từ WSDL sang Java.

Việc tạo mã thực hiện như thế nào

Trong những ngày đầu của WSDL, hai trong số những ứng dụng đầu tiên xuất hiện là Java2WSDL và WSDL2Java. Sau đó, một định dạng được tự động hóa có thích hợp không nếu bạn không thể sử dụng nó để tự động hóa bất cứ điều gì? Tất nhiên, sau đó việc quay trở về các tùy chọn của bạn đã phần nào bị hạn chế. Người ta đã hướng các mã theo phong cách RPC và thật khó để tự động tạo một hệ thống với các trọng tải phức tạp.

Cho đến hiện nay, người ta đã vượt qua được những vấn đề này khá tốt. Axis2 có thể tạo mã Java từ hầu như bất kỳ tài liệu WSDL nào và tạo WSDL từ một lớp Java. Nó hoàn thành kỳ tích này bằng cách sử dụng ràng buộc dữ liệu, trong đó một cấu trúc XML được chuyển đổi thành một đối tượng Java và ngược lại. Quá trình tạo mã này tạo các mã, sau đó bạn có thể thay đổi, tinh chỉnh, biên dịch và chạy các mã đó.

Trước tiên, Gene bắt đầu với một lớp Java và sử dụng nó để tạo một tài liệu WSDL. Francis sau đó nhận tài liệu đó và sử dụng nó để tạo ra cả hai dịch vụ và ứng dụng khách. Đối với dịch vụ này, quá trình tạo mã tạo ra một bộ khung để bạn có thể thêm mã riêng của mình vào trong đó để thực hiện các hành động mà bạn muốn dịch vụ đó thực hiện. Đối với ứng dụng khách, quá trình tạo mã tạo ra một nhánh rẽ để bạn có thể dùng nhánh đó để gọi một phương thức dịch vụ Web như thể nó đã là một phương thức Java.

Sẵn sàng

Bước đầu tiên để đảm bảo rằng môi trường của bạn đã sẵn sàng. Tải về phiên bản 0.95 của Apache Axis2, giải nén nó và bảo đảm rằng tất cả các tệp *. jar trong thư mục lib đang nằm trên đường dẫn lớp (CLASSPATH) này.

Để chạy dịch vụ Web này, hãy cài đặt Apache Geronimo (nếu bạn chưa có) và khởi động nó. (Xem Phần 1 để được hướng dẫn). Tải bản phân phối Axis2 v0.95 War và sao chép nó vào thư mục <GERONIMO_HOME>/deploy. Geronimo sẽ triển khai Axis2 tự động.

Các lớp Java

Gene bắt đầu với lớp ClassifiedService. Gene dự định sẽ sử dụng lớp này như là dịch vụ giúp việc và cũng như là một phương tiện cho việc kiểm tra để bảo đảm mọi thứ hoạt động theo cách mà Gene hy vọng (xem Liệt kê 35).

Liệt kê 35. ClassifiedService.java
package org.dailymoon.classifieds;

public class ClassifiedService {
   
   public static int createNewAd(String content, String endDate){

      ClassifiedAd newAd = new ClassifiedAd();
      newAd.setEnd(endDate);
      newAd.setContent(content);
      newAd.save();

      return 1;

   }

   public static boolean editExistingAd(ClassifiedAd adToEdit){

      //Do stuff with the ad here
      return true;

   }


   public static ClassifiedList getExistingAds(){

       ClassifiedAd[] listOfAds = {new ClassifiedAd(), 
                               new ClassifiedAd(), new ClassifiedAd()};
       ClassifiedList listToReturn = new ClassifiedList(listOfAds);
       return listToReturn;
   }

   public static void finalizeIssue(String dateToFinalize){
       //Don't return anything.
       System.out.println(dateToFinalize + " finalized.");
   }

   public static void main (String args[]){

         ClassifiedService.createNewAd(
           "Eclipse experts needed.  Contact Nick for details.",
                                                   "4/21/2006");

         ClassifiedAd adToEdit = new ClassifiedAd();
         adToEdit.setId(1);
         adToEdit.setStart("4/8/2006");
         adToEdit.setEnd("4/30/2006");
         adToEdit.setContent(
             "Geronimo experts needed.  Contact Nick for details.");

         ClassifiedService.editExistingAd(adToEdit);

         ClassifiedList adList = ClassifiedService.getExistingAds();
         System.out.println(adList.toString());

   }


}

Bản thân ứng dụng khá đơn giản. Nó cung cấp một ví dụ về việc tạo một đoạn quảng cáo mới, chỉnh sửa một đoạn quảng cáo hiện có và liệt kê tất cả các đoạn quảng cáo hiện có. Ứng dụng cung cấp các giới hạn cơ bản cho cả bốn phương thức mà Gene muốn trưng ra, createNewAd, editExistingAd, getExistingAdsfinalizeIssue.

(Hãy bảo đảm đưa ra lời bình phương thức chính trước khi tạo WSDL. Nó sẽ không gây bất kỳ tác hại nào, nhưng nó sẽ tạo ra các mã không cần thiết, thêm vào).

Ngoài ra lớp này cũng tham chiếu đến hai lớp khác, ClassifiedAdClassifiedList. Để cho quá trình tạo mã hiểu cách cấu trúc các đối tượng này như là XML, Gene tạo ra chúng như là các lớp riêng biệt (xem Liệt kê 36).

Liệt kê 36. ClassifiedAd.java
package org.dailymoon.classifieds;

public class ClassifiedAd {

   private int id;
   private String startDate;
   private String endDate;
   private String content;

   public void setId(int newId){
      id = newId;
   }

   public void setStartDate(String newStart){
      startDate = newStart;
   }

   public void setEndDate(String newEnd){
      endDate = newEnd;
   }

   public void setContent(String newContent){
      content = newContent;
   }

   public void save(){
       //Save data here
       System.out.println("Ad saved.");
   }

}

Một lần nữa, chính lớp này chưa hoàn chỉnh, nhưng cấu trúc ở đúng chỗ (xem Liệt kê 37).

Liệt kê 37. ClassifiedList.java
package org.dailymoon.classifieds;

public class ClassifiedList {

    public ClassifiedAd[] listOfAds;

    public ClassifiedList(ClassifiedAd[] newListOfAds){
        listOfAds = newListOfAds;
    }

    public ClassifiedAd[] getRawAds(){
         return listOfAds;
    }

    public String toString(){
         return "This is a string of results.";
    }

}

Ở đây Gene quy định rằng lớp ClassifiedList bao gồm một mảng các đối tượng ClassifiedAd.

Với tất cả các lớp ở đúng chỗ, Gene có thể tạo WSDL.

Tạo và thông báo WSDL

Việc tạo WSDL là một quá trình đơn giản. Từ dòng lệnh, Gene đưa ra lệnh, như trong Liệt kê 38:

Liệt kê 38. Lệnh để tạo WSDL
java org.apache.axis2.wsdl.Java2WSDL -cn org.dailymoon.classifieds.ClassifiedService -o

(Lưu ý rằng tất cả lệnh này sẽ xuất hiện trên một dòng)

Khóa chuyển đổi -cn xác định lớp làm cơ sở cho dịch vụ. Khóa chuyển đổi -o xác định thư mục đầu ra. Giả sử không có vấn đề nào, các lớp lặng lẽ thực hiện, để lại tệp ClassifiedService.wsdl trong thư mục đầu ra. Tệp này rất giống với một tệp được Larry tạo trước đó -- theo thiết kế, do tất cả chúng đang tiếp tục làm việc trên cùng dịch vụ -- nhưng một số thay đổi nhỏ cần được thực hiện để hoàn thành các mục đã được quá trình tạo mã đặt tên tổng quát. Cụ thể, các tham số không luôn chuyển dịch tốt và có khả năng sẽ phải được đổi tên.

Ở đây là tệp WSDL được tạo ra, với các tinh chỉnh in đậm (xem Liệt kê 39).

Liệt kê 39. Tệp WSDL
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       xmlns:tns="http://ws.apache.org/axis2"
       xmlns:ns1="http://org.apache.axis2/xsd" 
       targetNamespace="http://ws.apache.org/axis2">

<wsdl:types>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
         targetNamespace="http://org.apache.axis2/xsd" 
         elementFormDefault="unqualified" 
         attributeFormDefault="unqualified">

    <xs:element type="ns1:ClassifiedAd" name="ClassifiedAd" />
    <xs:complexType name="ClassifiedAd">
      <xs:sequence>
        <xs:element type="xs:int" name="id" />
        <xs:element type="xs:string" name="content" />
        <xs:element type="xs:string" name="endDate" />
        <xs:element type="xs:string" name="startDate" />
      </xs:sequence>
    </xs:complexType>

    <xs:element type="ns1:ClassifiedList" name="ClassifiedList" />
    <xs:complexType name="ClassifiedList">
      <xs:sequence>
        <xs:element minOccurs="0" type="ns1:ClassifiedAd" name="ClassifiedAd" 
                                 maxOccurs="unbounded" />
      </xs:sequence>
    </xs:complexType>

    <xs:element name="createNewAdRequest">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:string" name="content" />
          <xs:element type="xs:string" name="endDate" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>

    <xs:element name="createNewAdResponse">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:int" name="newAdId" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>

    <xs:element name="editExistingAdRequest">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="ns1:ClassifiedAd" name="existingAd" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>

    <xs:element name="editExistingAdResponse">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:boolean" name=" wasSuccessful"/>
        </xs:sequence>
      </xs:complexType>
    </xs:element>

    <xs:element name="getExistingAdsRequest">
      <xs:complexType />
    </xs:element>

    <xs:element name="getExistingAdsResponse">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="ns1:ClassifiedList" name="ClassifiedList" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>

    <xs:element name="finalizeIssueRequest">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:string" name="issueToFinalize"
 />
        </xs:sequence>
      </xs:complexType>
    </xs:element>

  </xs:schema>

</wsdl:types>

<wsdl:message name="createNewAdRequestMessage">
  <wsdl:part name="part1" element="ns1:createNewAdRequest" />
</wsdl:message>

<wsdl:message name="createNewAdResponseMessage">
  <wsdl:part name="part1" element="ns1:createNewAdResponse" />
</wsdl:message>

<wsdl:message name="getExistingAdsResponseMessage">
  <wsdl:part name="part1" element="ns1:getExistingAdsResponse" />
</wsdl:message>

<wsdl:message name="editExistingAdRequestMessage">
  <wsdl:part name="part1" element="ns1:editExistingAdRequest" />
</wsdl:message>

<wsdl:message name="getExistingAdsRequestMessage">
  <wsdl:part name="part1" element="ns1:getExistingAdsRequest" />
</wsdl:message>

<wsdl:message name="editExistingAdResponseMessage">
  <wsdl:part name="part1" element="ns1:editExistingAdResponse" />
</wsdl:message>

<wsdl:message name="finalizeIssueRequestMessage">
  <wsdl:part name="part1" element="ns1:finalizeIssueRequest" />
</wsdl:message>

<wsdl:portType name="ClassifiedServicePortType">

  <wsdl:operation name="finalizeIssue">
    <wsdl:input message="tns:finalizeIssueRequestMessage" />
  </wsdl:operation>

  <wsdl:operation name="createNewAd">
    <wsdl:input message="tns:createNewAdRequestMessage" />
    <wsdl:output message="tns:createNewAdResponseMessage" />
  </wsdl:operation>

  <wsdl:operation name="editExistingAd">
    <wsdl:input message="tns:editExistingAdRequestMessage" />
    <wsdl:output message="tns:editExistingAdResponseMessage" />
  </wsdl:operation>

  <wsdl:operation name="getExistingAds">
    <wsdl:input message="tns:getExistingAdsRequestMessage" />
    <wsdl:output message="tns:getExistingAdsResponseMessage" />
  </wsdl:operation>

</wsdl:portType>

<wsdl:binding name="ClassifiedServiceBinding"
 type="tns:ClassifiedServicePortType">

  <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
 style="document" />

  <wsdl:operation name="createNewAd">
    <soap:operation soapAction="createNewAd" style="document" />
    <wsdl:input>
      <soap:body use="literal" 
                 namespace="http://daily-moon.com/classifieds" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" 
                 namespace="http://daily-moon.com/classifieds" />
    </wsdl:output>
  </wsdl:operation>

  <wsdl:operation name="finalizeIssue">
    <soap:operation soapAction="finalizeIssue" style="document" />
    <wsdl:input>
      <soap:body use="literal" 
                  namespace="http://daily-moon.com/classifieds" />
    </wsdl:input>
  </wsdl:operation>

  <wsdl:operation name="editExistingAd">
    <soap:operation soapAction="editExistingAd" style="document" />
    <wsdl:input>
      <soap:body use="literal" 
                   namespace="http://daily-moon.com/classifieds" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" 
                   namespace="http://daily-moon.com/classifieds" />
    </wsdl:output>
  </wsdl:operation>

  <wsdl:operation name="getExistingAds">
    <soap:operation soapAction="getExistingAds" style="document" />
    <wsdl:input>
      <soap:body use="literal" 
                   namespace="http://daily-moon.com/classifieds" />
    </wsdl:input>
    <wsdl:output>
      <soap:body use="literal" 
                   namespace="http://daily-moon.com/classifieds" />
    </wsdl:output>
  </wsdl:operation>

</wsdl:binding>

<wsdl:service name="ClassifiedService">
  <wsdl:port name="ClassifiedServicePort" 
                           
 binding="tns:ClassifiedServiceBinding">
    <soap:address location=
         "http://127.0.0.1:8080/axis2/services/ClassifiedService" />
  </wsdl:port>
</wsdl:service>

</wsdl:definitions>

Hầu hết những thay đổi này đúng là tiện lợi, cũng như có thể sử dụng được; dễ dàng hơn để nhớ "nội dung", sau đó "param0". Hai trong số những thay đổi này -- vùng tên ở phía trên cùng và tiền tố vùng tên ở phía dưới cùng -- là do các lỗi nhỏ trong quá trình tạo mã này tồn tại trong phiên bản Axis2 0.95 và tới lúc bạn đọc điều này, chúng có thể không còn cần thiết nữa.

Tạo các dịch vụ từ WSDL

Một khi tệp WSDL tồn tại, Francis có thể sử dụng nó để tạo ra dịch vụ và ứng dụng khách. (Trên thực tế, Francis đúng là đã có thể dễ dàng sử dụng phiên bản do Larry tạo ra).

Francis bắt đầu bằng cách tạo các mã phía máy chủ, như trong Liệt kê 40:

Liệt kê 40. Mã phía máy chủ
java org.apache.axis2.wsdl.WSDL2Java -uri ClassifiedService.wsdl 
-ss -sd -p org.dailymoon.classifieds -d xmlbeans -o service

(Một lần nữa, hãy nhập lệnh này trên một dòng đơn).

Tham số đầu tiên là địa chỉ dùng cho tệp WSDL. Đúng, bạn có thể truy cập một tệp từ xa bằng cách sử dụng ứng dụng này. Khóa chuyển đổi thứ hai, -ss, cho ứng dụng biết cách tạo ra dịch vụ, đối lập với ứng dụng khách. Khóa chuyển đổi -sd cho ứng dụng biết cách tạo bộ mô tả (descriptor) dịch vụ XML, làm cho bộ mô tả dịch vụ này giúp bạn triển khai dịch vụ dễ dàng hơn một khi bạn đã tạo ra nó. Tất nhiên, tham số tiếp theo là gói phần mềm, rồi đến phương thức ràng buộc dữ liệu. Các phương thức có sẵn là adb, xmlbeansjaxme. Cuối cùng, để giữ cho mọi thứ sạch sẽ, Francis tạo ra dịch vụ trong một thư mục mới được gọi là nguồn.

Đúng là kết quả có hàng trăm tệp. May mắn thay, bạn chỉ cần đối phó với một trong số các tệp đó.

Triển khai thực hiện dịch vụ

Mặc dù trong trường hợp này dịch vụ đã được tạo từ một tệp WSDL đã được chính nó tạo từ một lớp Java, không có logic thực tế nào trong mã được tạo. Chỉ có cấu trúc xuất hiện. Để có được dịch vụ thực sự làm điều gì đó, bạn cần chỉnh sửa tệp bộ khung.

Trong cấu trúc này, tệp đang được nói đến được hiển thị trong Liệt kê 41:

Liệt kê 41. Tệp được tạo từ một lớp Java
service\src\org\dailymoon\classifieds\ClassifiedServicePortTypeSkeleton.
java

Mã này được nhận xét nhiều, điều này có ích khi bạn cố tìm hiểu mã đó cho chính mình, nhưng có thể rất mất tập trung khi bạn đang cố giải thích nó. Đây là phiên bản đã sạch, cùng với mã được thêm vào để triển khai thực hiện một phần của dịch vụ này (xem Liệt kê 42).

Liệt kê 42. ClassifiedServicePortTypeSkeleton.java
package org.dailymoon.classifieds;

public class ClassifiedServicePortTypeSkeleton {

   public  axis2.apache.org.xsd.CreateNewAdResponseDocument createNewAd   
      (axis2.apache.org.xsd.CreateNewAdRequestDocument param0 ) throws Exception {

      //Todo fill this with the necessary business logic
      //throw new  java.lang.UnsupportedOperationException();

      System.out.println("New ad requested, to end on " + 
                              param0.getCreateNewAdRequest().getEndDate()); 
      System.out.println( param0.getCreateNewAdRequest().getContent()); 
      axis2.apache.org.xsd.CreateNewAdResponseDocument responseDoc = 
            axis2.apache.org.xsd.CreateNewAdResponseDocument .Factory.newInstance(); 
      axis2.apache.org.xsd.CreateNewAdResponseDocument .CreateNewAdResponse response = 
              responseDoc.addNewCreateNewAdResponse(); 
      response.setNewAdId(1138); 
      return responseDoc;

   }
     
   public  void finalizeIssue
           (axis2.apache.org.xsd.FinalizeIssueRequestDocument param2)
                                                    throws Exception {

        //Todo fill this with the necessary business logic
                
   }
     
   public  axis2.apache.org.xsd.EditExistingAdResponseDocument 
                                                       editExistingAd
        (axis2.apache.org.xsd.EditExistingAdRequestDocument param3) 
                                                    throws Exception {

      //Todo fill this with the necessary business logic
      throw new  java.lang.UnsupportedOperationException();

   }
     
   public  axis2.apache.org.xsd.GetExistingAdsResponseDocument 
                                                      getExistingAds
        (axis2.apache.org.xsd.GetExistingAdsRequestDocument param5) 
                                                     throws Exception {

      //Todo fill this with the necessary business logic
      throw new  java.lang.UnsupportedOperationException();

   }
     
}

Mỗi phương thức bắt đầu vòng đời bằng cách ném ra một ngoại lệ UnsupportedOperationException, cho đến khi bạn thực sự triển khai thực hiện phương thức. Để có được dữ liệu được đệ trình cho dịch vụ, hãy bắt đầu với một tham số và rồi nhận được yêu cầu của nó. Từ đó, bạn có thể trích xuất các thành viên riêng bằng cách sử dụng các phương thức getter.

Rõ ràng, trong một dịch vụ thực, bạn muốn thực hiện nhiều văn bản xuất ra đơn giản hơn sau đó, nhưng Francis chỉ quan tâm đến việc bảo đảm nó sẽ hoạt động. Để tạo ra đáp ứng, bắt đầu với tài liệu đáp ứng thích hợp, rồi nhận được một phiên bản thông qua Factory (nhà máy) của lớp. (Các lớp tự nó là khá phức tạp, chứa một số các lớp bên trong, nhưng thật đáng giá có một cái nhìn để xem các lớp có cấu trúc như thế nào). Khi bạn có tài liệu, hãy tạo ra chính đáp ứng thực tế và thêm nó vào tài liệu đó.

Khi sử dụng phương thức setter, bạn có thể trực tiếp thiết lập các giá trị cho đáp ứng. Chỉ cần trả về tài liệu đáp ứng và các lớp hỗ trợ sẽ xử lý việc gửi nó lại cho người yêu cầu.

Triển khai dịch vụ

Để triển khai dịch vụ, bạn sẽ cần biên dịch dịch vụ và chuyển dịch vụ thành một tệp lưu trữ Axis2. Bắt đầu bằng việc biên dịch và đóng gói dịch vụ, như trong Liệt kê 43.

Liệt kê 43. Đóng gói dịch vụ
set ANT_HOME=e:\apache-ant-1.6.5
PATH=%PATH%;%ANT_HOME%\bin;
set AXIS2_HOME=e:\axis2
cd service
ant jar.service

Điều chỉnh cú pháp của bạn một cách thích hợp cho các việc cài đặt không trong Windows và bảo đảm sử dụng các vị trí tệp thực sự của bạn.

Nhiệm vụ của Ant này biên dịch tất cả các tệp thích hợp và tạo ra hai tệp lưu trữ, ClassifiedService.aar và Xbeans-packaged.jar, cả hai đều nằm trong thư mục build/lib.

Để triển khai dịch vụ, hãy chắc chắn Geronimo đang chạy và trỏ tới trình duyệt của bạn như trong Liệt kê 44:

Liệt kê 44. Triển khai dịch vụ
http://localhost:8080/axis2/Login.jsp

Đăng nhập với các ủy quyền admin/axis2 và nhấn Upload Service>Browse. Chuyển hướng đến tệp ClassifiedService.aar và nhấn OK. Nhấn vào Upload để hoàn tất quá trình này.

Nếu bạn nhấn vào View Services (Xem các dịch vụ), bạn sẽ thấy dịch vụ mới được liệt kê.

Tạo nhánh rẽ ứng dụng khách từ WSDL

Tất cả những gì còn lại bây giờ là tạo ứng dụng khách để truy cập dịch vụ mới. Để làm điều đó, thực hiện lệnh sau từ dòng lệnh:

Liệt kê 45. Lệnh để tạo ứng dụng khách
java org.apache.axis2.wsdl.WSDL2Java -uri ClassifiedService.wsdl -p
 org.dailymoon.classifieds -d xmlbeans -o client

Như thường lệ, đây là một lệnh đơn, có nghĩa là cho một dòng đơn. Các tham số hầu như giống hệt với những tham số thường dùng cho việc tạo mã ở phía máy chủ, trừ ra bạn không cần một bộ mô tả dịch vụ. Ngoài ra, để giữ cho mọi thứ sạch sẽ, Francis đặt các tệp mới trong một thư mục, ứng dụng khách, riêng biệt.

Lớp này nên lặng lẽ thực hiện, để lại hàng trăm tệp theo sau nó, nhưng bạn không cần đối phó trực tiếp với bất kỳ tệp nào trong số đó.

Tạo ứng dụng khách

Quá trình tạo mã không thực sự tạo ra một ứng dụng khách, nhưng nó tạo một lớp mà bạn có thể sử dụng để dễ dàng tạo ra một ứng dụng khách. Để đơn giản hóa việc biên dịch, Francis tạo một tệp lớp mới gọi là tệp Client.java trong thư mục client\src\org\dailymoon\classifieds. Bằng cách này, Ant sẽ nhận tệp java và biên dịch nó với phần còn lại của nguồn.

Francis thêm các mã trong Liệt kê 46.

Liệt kê 46. Ứng dụng khách
package org.dailymoon.classifieds;

import axis2.apache.org.xsd.*;

public class Client{

   public static void main(java.lang.String args[]){

      try{
         ClassifiedServicePortTypeStub stub = 
              new ClassifiedServicePortTypeStub(null,
     "http://localhost:8080/axis2/services/ClassifiedService");
            
         CreateNewAdRequestDocument cnaDoc = 
               CreateNewAdRequestDocument.Factory.newInstance();

         CreateNewAdRequestDocument.CreateNewAdRequest cnaReq = 
                              cnaDoc.addNewCreateNewAdRequest();
         cnaReq.setContent("Vintage 1963 T-Bird...");
         cnaReq.setEndDate("7/4/06");

         CreateNewAdResponseDocument cnaResDoc = 
                                       stub.createNewAd(cnaDoc);
         System.out.println("New ad ID number:  "+
                cnaResDoc.getCreateNewAdResponse().getNewAdId());

      } catch(Exception e){
         e.printStackTrace();
      }
   }
}

Lớp ClassifiedServicePortTypeStub đại diện cho dịch vụ thực tế và bạn thể hiện nó bằng AXIS_HOME (ở đây để cho mặc định) và vị trí của dịch vụ thực tế. Tiếp theo, tạo tài liệu yêu cầu, một lần nữa bằng cách tham chiếu Factory (nhà máy) của nó và sử dụng nhà máy để tạo ra một CreateNewAdRequest mới, thêm nó vào tài liệu yêu cầu trong quá trình này. Đúng như trong dịch vụ của mình, sau đó bạn có thể thiết lập các thuộc tính trực tiếp sử dụng các phương thức setter.

Để nhận được đáp ứng, sử dụng nhánh rẽ để thực hiện phương thức createNewAd() chuyển nó như một tham số qua tài liệu yêu cầu. Một khi bạn có tài liệu đáp ứng, hay đúng hơn là CreateNewAtResponseDocument, bạn có thể sử dụng nó để trích xuất đáp ứng của chính nó và một thuộc tính của đáp ứng đó.

Bây giờ hãy chạy nó.

Chạy ứng dụng khách

Để chạy một ứng dụng khách, đầu tiên Francis cần biên dịch nó. Hãy thực hiện các bước sau (xem Liệt kê 47).

Liệt kê 47. Biên dịch ứng dụng khách
>>set ANT_HOME=e:\apache-ant-1.6.5
>>PATH=%PATH%;%ANT_HOME%\bin;
>>set AXIS2_HOME=e:\axis2
>>cd client
>>ant jar.client
Buildfile: build.xml 
init: pre.compile.test: [echo] Stax 
Availability= true [echo] Axis2 
Availability= true 
compile.src: compile.test: jar.client: BUILD SUCCESSFUL 
Total time: 2 seconds

Trước tiên, đảm bảo môi trường có các biến thích hợp. (Điều này giả định bạn đã thêm tất cả mọi thứ của các tệp AXIS2_HOME\lib jar). Tiếp theo, thay đổi thành thư mục ứng dụng khách (hoặc thư mục bất kỳ sử dụng đầu ra cho quá trình tạo mã) và chạy Ant dựa vào tệp đích jar.client. Bạn sẽ thấy kết quả tương tự như kết quả được viết bằng chữ in nghiêng (xem Liệt kê 47). Để chạy ứng dụng khách, đầu tiên sửa đổi đường dẫn lớp (classpath) để bao gồm thư mục tài nguyên và thư mục có chứa tất cả các lớp do quá trình ràng buộc dữ liệu tạo ra (xem Liệt kê 48).

Liệt kê 48. Chạy ứng dụng khách
>>set CLASSPATH=E:\WSDLFiles\client\resources\;E:\WSDLFiles\client\bui
ld\classes\axis2\apache\org\xsd\;%CLASSPATH%
>>cd build\classes
>>java org.dailymoon.classifieds.Client

Bạn sẽ thấy các kết quả như kết quả được hiển thị trong Liệt kê 49:

Liệt kê 49. Số nhận dạng đoạn quảng cáo mới
New ad ID number: 1138

Như kết quả cho thấy, đó là tất cả mọi thứ có với nó.


Tóm tắt

Trong phần 1 của loạt bài này, Phòng chuyên mục rao vặt của tờ báo Daily Moon đã học cách sử dụng các dịch vụ web SOAP để kết nối với hệ thống quản lý nội dung của tờ báo. Trong hướng dẫn này, các nhân viên đã học cách sử dụng WSDL (Ngôn ngữ mô tả dịch vụ Web) để mô tả các dịch vụ riêng của họ sao cho người khác có thể sử dụng chúng. Hướng dẫn này trình bày các cơ sở của lược đồ XML, cùng với cấu trúc của một tệp WSDL để có thể xây dựng lược đồ này bằng tay. Hướng dẫn này cũng thảo luận về những sự khác nhau giữa nhiều phong cách và các cách mã hóa có sẵn. Hướng dẫn này cũng giải thích cách sử dụng các công cụ Java2WSDL và WSDL2Java đi kèm với Apache Axis2 để tự động tạo WSDL từ tệp Java và ngược lại.

Phần 3 của loạt bài này sẽ xem xét việc xây dựng các ứng dụng đăng ký dịch vụ Web bằng cách sử dụng UDDI.


Tải về

Mô tảTênKích thước
WSDL filesws-understand-web-services2-WSDL.zip3000KB

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=SOA và dịch vụ Web
ArticleID=549727
ArticleTitle=Hiểu biết về Đặc tả các dịch vụ Web, Phần 2: WSDL (Ngôn ngữ mô tả các dịch vụ Web)
publish-date=10092010