Hiểu biết về Đặc tả các dịch vụ Web, Phần 3: Giao diện khám phá và mô tả thống nhất (UDDI)

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). Hướng dẫn này, Phần 3 trong loạt bài này, giải thích các khái niệm cơ bản về giao diện UDDI (Universal Description, Discovery and Integration - Tích hợp, khám phá và mô tả đa năng) và cách truy cập nó bằng cách sử dụng ứng dụng Java.

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



10 10 2010

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

Hướng dẫn này giải thích giao diện khám phá và mô tả thống nhất hoặc UDDI (Uniform Description and Discovery Interface). UDDI xác định một đăng ký của các dịch vụ Web và thông tin công ty khác và được thiết kế để cung cấp một cách khám phá các dịch vụ Web mới để sử dụng và trong các trường hợp lý tưởng, tự động hoá việc sử dụng chúng.

Hướng dẫn này giả định rằng bạn đã quen thuộc với các khái niệm chung của các dịch vụ Web, cũng như SOAP. Kiến thức về WSDL cũng có ích, nhưng hướng dẫn này chỉ xem xét lại các khái niệm nói chung.

Để làm theo cùng các mã trong phần cuối, bạn nên hiểu rõ về Java, nhưng các khái niệm, như phần còn lại của hướng dẫn, áp dụng cho bất kỳ ngôn ngữ lập trình nào.

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 (Mặt trăng hàng ngày), như là 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 khi có nhiều thay đổi.

Phần 1 đã giải thích các khái niệm cơ bản sau các dịch vụ Web và đã hiển thị cách sử dụng SOAP, đặc tả này 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.

Phần 2, đưa mọi thứ tiến một bước xa hơn, khi giải thích cách 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 tạo với những thứ mà người ta hy vọng ở dịch vụ Web, cho phép nhóm làm việc tạo 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 một đăng ký có thể tìm kiếm được của các dịch vụ có sẵn bằng 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), tìm nhóm làm việc có mục tiêu là bảo vệ 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ừ những 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 cho thấ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.

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 loạt bài này giới thiệu cho bạn các dịch vụ Web và nhấn mạnh tầm quan trọng của SOAP. Chúng tôi đã làm điều này thông qua việc khai thác của một phòng chuyên mục rao vặt của tờ báo hư cấu Daily Moon. Trong Phần 2 của loạt bài này, phòng chuyên mục rao vặt quyết định tạo ra một dịch vụ Web của riêng mình, tạo tài liệu sử dụng của mình bằng WSDL (Ngôn ngữ mô tả các dịch vụ Web). Ở đây trong Phần 3, về các dịch vụ Web chủ báo đã quyết định đưa tất cả ra khỏi các dịch vụ và đã yêu cầu sử dụng một đăng ký UDDI để theo dõi tất cả các dịch vụ có sẵn.

Trong tiến trình hướng dẫn này, bạn sẽ học:

  • UDDI là gì.
  • UDDI dành cho cái gì.
  • Cấu trúc của dữ liệu UDDI.
  • Làm thế nào để biểu diễn có hiệu quả WSDL khi sử dụng UDDI.
  • Các hoạt động mà bạn có thể thực hiện trên dữ liệu UDDI.
  • Tương tác với một đăng ký UDDI bằng cách sử dụng Java.

Điều kiện cần trước

Để làm theo cùng với các mã cho hướng dẫn này, bạn sẽ cần có sẵn phần mềm sau đây:

Thực hiện Apache Geronimo hay thực hiện một UDDI khác. Để làm theo cùng với các mã, bạn sẽ cần truy cập vào một đăng ký UDDI. Đến cuối hướng dẫn, kiểu đăng ký nào mà bạn sử dụng không quan trọng, do UDDI về cơ bản là một dịch vụ Web và cần được truy cập từ nền tảng hay ngôn ngữ bất kỳ, tới nền tảng hoặc ngôn ngữ bất kỳ khác. Điều đó nói rằng, các máy chủ ứng dụng Apache Geronimo cũng là cơ sở cho IBM Community Edition (Ấn bản cộng đồng của WebSphere của IBM) và chúng tôi đã sử dụng máy chủ đó trong Phần 1 và 2 của loạt bài này, có thực hiện đăng ký UDDI của Apache, jUDDI, được cài đặt sẵn và cấu hình như là một phần của một cài đặt tiêu chuẩn. Bạn có thể tải Apache Geronimo từ Apache.org. Để biết thêm thông tin về cài đặt Geronimo, xem Phần 1 của loạt bài này.

UDDI4J -- Để truy cập đăng ký, hướng dẫn này giải thích việc sử dụng dự án UDDI4J, cung cấp một sự tích hợp khá chặt chẽ giữa các khái niệm UDDI và mã Java. Bạn có thể tải UDDI4J từ Sourceforge.net.

Apache Axis2 hoặc việc thực hiện SOAP khác -- 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ó ích. Bạn sẽ 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ừ Apache.org. Hướng dẫn này sử dụng phiên bản 0.94, nhưng phiên bản mới hơn cũng sẽ hoạt động.

Ấn bản tiêu chuẩn Java 2 phiên bản 1.4 -- Tất cả mọi thứ trong 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ừ Sun Developer Network. Geronimo sẽ không chạy đúng với Java 1.5.

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ư Eclipse, nhưng do chúng ta đang 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

Chúng ta hãy nhìn vào nơi chúng ta ở đó cho đến nay.

Câu chuyện cho đến nay

Loạt bài này cho phép các nhân viên của tờ báo hư cấu Daily Moon khi tờ báo này chuyển nhiều hoạt động hàng ngày của mình sang một hệ thống dựa trên các dịch vụ Web. Trong Phần 1, Phòng chuyên mục rao vặt tìm hiểu về SOAP bằng cách tương tác với Hệ thống quản lý nội dung và trong Phần 2, họ đã tạo dịch vụ riêng của mình và đã định nghĩa nó bằng cách sử dụng WSDL. Bây giờ Rudy, chủ báo, bị ấn tượng với cách mà các dịch vụ Web đang làm việc trong tổ chức của mình đến mức ông muốn nhìn thấy các dịch vụ Web được sử dụng thường xuyên hơn, thậm chí đến mức tương tác với các tổ chức khác.

Cuối cùng, ông đã yêu cầu hai thành viên của nhóm Công nghệ thông tin, Gene và Francis, tạo một đăng ký dịch vụ Web, mà ông hy vọng sẽ cho phép các phòng khác dễ dàng tìm thấy những gì họ cần để chuyển các hoạt động của họ qua các dịch vụ Web.

Hai nhân viên này quyết định cách tốt nhất để làm điều đó sẽ là triển khai thực hiện một đăng ký của giao diện UDDI. Đăng ký này sẽ cho phép họ không chỉ lưu thông tin trên các dịch vụ riêng của tờ báo, mà nó cũng có thể tương tác với các đăng ký tại các tờ báo khác.

Trình làm mới WSDL

Một phần của quá trình đăng ký một dịch vụ với một đăng ký UDDI bao gồm việc thao tác định nghĩa WSDL, vì vậy trước khi chuyển sang dự án mới, Gene xem xét lại các khái niệm cơ bản của WSDL bằng cách quay lại qua các tệp được tạo ra trong dự án sau cùng của mình. Xem Liệt kê 1.

Liệt kê 1. Các 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://www.daily-moon.com/classifieds"
       xmlns:ns1="http://org.apache.axis2/xsd" 
       targetNamespace="http://www.daily-moon.com/classifieds">

<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:message>

<wsdl:portType name="ClassifiedServicePortType">

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

  <wsdl:operation name="finalizeIssue">...</wsdl:operation>
  <wsdl:operation name="editExistingAd">...</wsdl:operation>
  <wsdl:operation name="getExistingAds">...</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:operation name="finalizeIssue">...</wsdl:operation>
  <wsdl:operation name="editExistingAd">...</wsdl:operation>
  <wsdl:operation name="getExistingAds">...</wsdl:operation>

</wsdl:binding>

<wsdl:service name="ClassifiedService">
  <wsdl:port name="ClassifiedServicePort" 
             binding="tns:ClassifiedServiceBinding">
    <soap:address location=
"http://www.daily-moon.com:8080/axis2/services/ClassifiedService" />
  </wsdl:port>
</wsdl:service>

</wsdl:definitions>

Chúng tôi đã gỡ bỏ một số đoạn trong tài liệu này vì các lý do không gian của bài viết này, nhưng chúng ta hãy xem lại các khái niệm chung.

Bắt đầu từ phía dưới cùng, chúng ta có dịch vụ thực tế, có sẵn tại một vị trí cụ thể và triển khai thực hiện giao diện ClassifiedServiceBinding. Người ta đã biểu thị giao diện đó như là một ràng buộc, chỉ rõ các hoạt động được quy định trong portType ClassifiedServicePortType. portType định nghĩa các thông báo nhập vào và xuất ra bằng cách sử dụng các phần tử được quy định trong phần các kiểu.

Một ứng dụng khách XML có thể đọc thông tin này và sử dụng nó để truy cập vào dịch vụ Web. (Hoặc chính xác hơn, một công cụ tạo ứng dụng khách của dịch vụ Web có thể đọc thông tin này và tạo một ứng dụng khách có thể truy cập vào dịch vụ Web).

Từ đây chúng ta đi đâu

Trong tiến trình hướng dẫn này, Gene và Francis sẽ tách thông tin của tờ báo Daily Moon thành các cấu trúc thân thiện-UDDI, bao gồm thông tin nghiệp vụ và thông tin dịch vụ. Họ sẽ sử dụng nó để nhập các thông tin và các dịch vụ của tờ báo vào một đăng ký UDDI bằng cách sử dụng UDDI4J. Họ cũng sẽ làm việc với đăng ký riêng của một tờ báo khác, tờ Daily Star, để tìm kiếm một dịch vụ cung cấp điểm số của các môn thể thao đang diễn ra.

Bây giờ hãy xem tất cả mọi thứ về UDDI.


Giới thiệu về UDDI

UDDI về cơ bản là một dịch vụ Web, nhưng UDDI rất khác so với SOAP và WSDL nên để hiểu được một nền tảng nhỏ trước khi chúng ta bắt đầu là rất tốt.

Tại sao là UDDI?

Khi tất cả các ứng dụng là cục bộ, thật khá dễ dàng để tìm những gì bạn muốn. Tuy nhiên, khi bạn có một hệ thống phân tán như các dịch vụ Web, bạn không có lợi ích gì về việc có một kho lưu trữ trung tâm nữa. Hệ thống phân tán cũng dễ bị thay đổi. Đây là thế giới trong đó UDDI hình thành. UDDI được dự định để phục vụ hai mục đích. Theo sự tạo hình ban đầu của mình, UDDI đã được diễn đạt như là một loại "Đăng ký doanh nghiệp đa năng" (Universal Business Registry). Ý tưởng là điều mà các doanh nghiệp có thể tìm kiếm các đối tác bằng cách sử dụng một trong ba phương pháp sau:

  • "Các trang trắng": Các trang trắng giống như các trang trắng của danh bạ điện thoại, trong đó người ta có thể tìm kiếm thông tin về một công ty. Ví dụ, nếu bạn đã biết tên của công ty, bạn có thể tìm ra công ty đó ở đâu, cách để liên hệ với họ và thậm chí cả liên hệ với ai trong tổ chức đó.
  • "Các trang vàng": Các trang vàng, cũng vậy, giống như các trang trắng của danh bạ điện thoại, trong đó bạn có thể tra cứu các doanh nghiệp dựa trên sự phân loại. UDDI đã quy định các sự phân loại khác nhau mà các công ty có thể sử dụng để phân loại chính mình. Ví dụ, nếu bạn đang tìm kiếm các đồ thể thao, bạn có thể tìm các công ty có một mã số của hệ thống phân loại công nghiệp Bắc Mỹ (NAICS) là 339.920.
  • "Các trang xanh": Đúng, không có các trang xanh lá cây trong danh bạ điện thoại của bạn, nhưng ý tưởng là ở chỗ các công ty có thể sử dụng phương pháp tìm kiếm này để tìm các đối tác thương mại đã triển khai thực hiện một dịch vụ cụ thể. Ví dụ, bạn có thể thực hiện tìm kiếm các công ty triển khai thực hiện một tính toán từ xa bằng cách sử dụng các mã bưu điện (zip).

Người ta cũng nghĩ UDDI như là một cách để giữ cho các ứng dụng phân tán hoạt động trong thời gian dài. Ý tưởng là bạn sẽ nhớ nhanh thông tin về cách truy cập một dịch vụ cụ thể và nếu khách hàng của bạn bị ngắt, ứng dụng sẽ tự động quay trở về chỗ đăng ký và kiểm tra để xem các thông tin đã thay đổi chưa. Nếu nó đã thay đổi, bạn có thể chỉ cần tạo các thay đổi trong ứng dụng của bạn (một cách tự động, trong một thế giới lý tưởng) và thử lại yêu cầu của bạn.

UDDI trong thế giới thực

Khi đang tìm kiếm một UBR (Đăng ký doanh nghiệp đa năng), Francis đã phát hiện ra rằng UBR đã không còn tồn tại nữa. Trong thực tế, các nhà tài trợ cho công ty của nó đã ngừng UBR khi UDDI phiên bản 3.0 được phát hành. Tại sao? Đúng, bất kể ý tưởng UBR đã là tốt như thế nào, thực tế là hầu như không ai sử dụng nó. Lý do gồm hai phần: đầu tiên, đã có rất ít thông tin có ích trong UBR -- trừ khi, đó là, bạn đang tìm kiếm một dịch vụ về số lượng cổ phiếu được bán ra tại thị trường chứng khoán, trong trường hợp này bạn có thể tìm thấy khá phong phú. Lý do thứ hai là các công ty, theo quy luật, không thực hiện kinh doanh với các tổ chức mà họ không hiểu rõ. Rất ít các tổ chức, nếu có, sẽ thực hiện một sự tìm kiếm tự động đối với các đối tác thương mại và sau đó mở hệ thống của họ cho các đối tác đó mà không có một chút chú trọng thích hợp nào. Vì vậy mô hình tìm kiếm tự động và gọi ra đã không thực sự cất cánh.

Mô hình đó cũng bị cản trở bởi thực tế là UDDI đã đi trước thời của nó, theo một số cách. Được thiết kế để xử lý tất cả các kiểu dịch vụ và không chỉ SOAP trên HTTP, UDDI không thêm ngay chính mình vào việc sử dụng các định nghĩa WSDL, ít nhất là trong khung nhìn của những thứ đang cố gắng sử dụng UDDI.

Tuy nhiên, điều đó không nói rằng UDDI không còn được sử dụng chút nào nữa. Thay vào đó, trên thực tế nó đang được sử dụng như một "đăng ký riêng" nhiều hơn. Các công ty tạo các đăng ký riêng của mình và nhập vào các dịch vụ riêng của mình. UDDI cũng có thể được sử dụng và là một kiểu đăng ký kinh doanh bên trong, theo cách mà từ đó người ta sử dụng LDAP theo truyền thống.

Hơn nữa, khi chúng ta chuyển qua một cách suy nghĩ "chỉ có dịch vụ Web" nhiều hơn về một ý tưởng SOA (Kiến trúc hướng dịch vụ), khả năng để xử lý nhiều hơn chỉ có mình SOAP có thể chỉ chứng tỏ bản thân nó khi chạy lâu dài.

Cấu trúc dữ liệu UDDI

Thông tin được chứa trong một đăng ký UDDI bao gồm năm kiểu khác nhau:

  • businessEntity hoặc tổ chức công ty thực tế. Điều này có thể có nghĩa là toàn bộ tổ chức hoặc nó có thể là một tổ chức liên kết hoặc chi nhánh.
  • publisherAssertion hoặc mối quan hệ giữa businessEntities. Để hợp lệ publisherAssertions phải được cả hai bên yêu cầu (vì vậy tôi không thể yêu cầu là một chi nhánh của một công ty khác), trừ khi cả hai thực thể có trách nhiệm với chủ báo hoặc trừ khi cả hai thực thể được nhập vào trong đăng ký bằng một tài khoản người dùng giống nhau.
  • bindingTemplate, về cơ bản là đặc tả của một giao diện của một dịch vụ. Nhiều businessServices có thể thực hiện businessServices.
  • businessService hay một dịch vụ do một doanh nghiệp cung cấp. Bây giờ, điều đó có vẻ đơn giản, nhưng trong thế giới của UDDI, điều đó không nhất thiết có nghĩa là nó là một dịch vụ Web. Ví dụ, bạn thực sự có thể xác định dịch vụ hỗ trợ điện thoại của doanh nghiệp của bạn (có nghĩa là số điện thoại thực tế mà người dùng quay số và tất cả mọi thứ mà đi kèm với nó) như một dịch vụ UDDI. Tất nhiên, bạn sẽ không có một tài liệu WSDL giả, nhưng nó sẽ là một dịch vụ được doanh nghiệp của bạn cung cấp.
  • tModels hoặc các mô hình siêu dữ liệu. Khi nghiên cứu UDDI, Francis đi đến kết luận rằng tModel có lẽ là lý do lớn nhất tại sao UDDI đã không cất cánh như mong đợi. Như một đăng ký của các dịch vụ, bạn sẽ mong đợi tìm thấy một cách để trực tiếp xác định giao diện cho một dịch vụ, như WSDL thực hiện. Nhưng, như đã nói, UDDI đã chưa bao giờ được dự định là độc quyền về các dịch vụ Web và được thiết kế với linh hoạt hơn nữa. tModels thực hiện trợ giúp trỏ đến các tài liệu XML, như chúng ta sẽ thấy sau này, nhưng trong thực tế chúng có nghĩa là một cách tổng quát để xác định thông tin về thứ gì đó, thông qua dịch vụ, một doanh nghiệp hay bất cứ điều gì khác.

Đó là những cấu trúc dữ liệu cơ bản của UDDI. Bây giờ hãy xem và cách thức trong đó UDDI nói chúng ta có thể tương tác với chúng.

API của UDDI

UDDI nổi danh là quá phức tạp, nhưng với cốt lõi của mình UDDI thuộc về năm kiểu dữ liệu được mô tả ở trên, được kết hợp với bốn hoạt động: tìm kiếm, nhận, lưuxóa. Nói cách khác, đặc tả UDDI lưu ý những điều sau đây để bạn có thể thực hiện với dữ liệu:

  • find_xx: Những phương thức này, chẳng hạn như find_businessEntity, find_businessService và v.v, cung cấp một cách để bạn tìm kiếm một bản ghi trong đăng ký UDDI. Những phương thức này trả về khóa để nhận dạng đối tượng.
  • get_xx: Một khi bạn có khóa duy nhất nhận dạng một đối tượng, bạn có thể sử dụng get_xx methods, như get_businessService và v.v, để lấy ra chính đối tượng thực tế đó. Ví dụ, get_businessService trả về toàn bộ đối tượng businessService, từ đó bạn thu được bất kỳ thông tin nào mà bạn cần.
  • save_xx: Như bạn có thể đã đoán được, các phương thức này thêm thông tin vào cơ sở dữ liệu hoặc chúng thay đổi thông tin đã có trong cơ sở dữ liệu.
  • delete_xx: Những phương thức này, chẳng hạn như delete_bindingTemplate, delete_tModel, và v.v, lấy khóa duy nhất của đối tượng làm tham số và loại bỏ nó khỏi cơ sở dữ liệu. Hành vi thực tế của các phương thức này phụ thuộc vào những gì bạn đang xóa. Ví dụ, vì tModels thường xuyên được các đối tượng khác trong cơ sở dữ liệu tham chiếu, nên chúng có thể không thực sự bị xóa; để thay thế người ta ẩn chúng đi

Hầu như tất cả mọi thứ của UDDI dựa trên 20 phân cắt giữa năm đối tượng (businessService, bindingTemplate, publisherAssertion, businessEntitytModel) và bốn hành động (find, get, savedelete).

Bây giờ hãy xem cấu trúc này thực sự trông giống như thế nào.


Cấu trúc dữ liệu UDDI

Để bắt đầu quá trình thêm công ty vào một đăng ký UDDI, Francis đã định nghĩa thông tin để nhập vào đăng ký đó.

businessEntity

Bước đầu tiên là nhập chính tờ báo đó vào đăng ký. Để làm điều này, Francis tạo một đối tượng businessEntity. Đối tượng này chứa thông tin về doanh nghiệp, vừa để xác định doanh nghiệp và vừa để cung cấp thông tin về doanh nghiệp. Ví dụ, đối tượng businessEntity có nhiều hơn một tên, (cho phép bạn, ít nhất là, tạo một phần tử tên cho mỗi ngôn ngữ trong đó công ty được thể hiện), thông tin liên hệ (người ta bảo Francis thêm Pat Mooney làm liên hệ chính), các dịch vụ liên kết với các thực thể (Gene sẽ làm sau) và thông tin để nhận dạng và phân loại công ty.

Mặc dù hầu hết mọi người sẽ không bao giờ tương tác với Đăng ký của UDDI (UDDI Registry) theo cách này, thực tế là về cơ bản UDDI là một ứng dụng SOAP; tất cả các hoạt động mà bạn thực hiện xảy ra như là kết quả của các thông báo SOAP được chuyển qua lại. Điều này có nghĩa là businessEntity do Francis đang tạo ra cuối cùng được biểu diễn như một phần tử XML. Xem Liệt kê 2.

Liệt kê 2. Phần tử businessEntity
<businessEntity businessKey="{uuid}" 
operator="(optional)" 
authorizedName="(optional)">
<discoveryURLs>
<discoveryURL></discoveryURL>
<discoveryURL></discoveryURL>
</discoveryURLs>
<name>The Daily Moon</name>
<name lang="fr-ca">La Lune Quotidienne</name>
<description></description>
<contacts>
<contact>
<description></description>
<personName>Pat Mooney</personName>
<phone></phone>
<email>patm@daily-moon.com</email>
<address useType="optional, billing, etc." 
sortCode="optional" 
tModelKey="optional">
<addressLine></addressLine>
<addressLine></addressLine>
<addressLine></addressLine>
</address>
</contact>
<contact>
         ...
</contact>
</contacts>
<businessServices>
<businessService serviceKey="required" 
businessKey="optional">
         ...
</businessService>
</businessServices>
<identifierBag>
      ...
</identifierBag>
<categoryBag>
      ...
</categoryBag>
</businessEntity>

Một bản ghi businessEntity thực hiện phải không quá phức tạp. Trong thực tế, chỉ có một tên duy nhất và trình nhận dạng duy nhất để hoạt động như là businessKey (Khóa doanh nghiệp) cần thiết. Tuy nhiên, để cho đầy đủ, tôi đã bao gồm toàn bộ cấu trúc, trừ một số đoạn bị cắt mà chúng tôi sẽ nói về chúng sau đây. Trong một môi trường sản xuất các phần tử rỗng cần được gỡ bỏ.

Hãy xem xét một số thông tin ở đây.

Bắt đầu từ trên cùng, một lần nữa, businessKey, là một trình nhận dạng. Toán tử và các thuộc tính authorizedName được ứng dụng đăng ký xử lý nội bộ, bạn không cần phải chạm vào chúng, nhưng chúng đại diện cho thực thể chạy ứng dụng đăng ký đó và người hoặc tài khoản mà người nào đó đã thêm vào bản ghi.

discoveryURLs được thêm vào đăng ký mỗi khi một businessEntity được lưu vào đăng ký. Các URL này có nghĩa là một vị trí mà người sử dụng có thể đi tới đó để có thêm nhiều thông tin về businessEntity này.

Lưu ý là Francis đã thêm một tên bổ sung khác, biểu thị tên của tờ báo bằng tiếng Pháp, ở đây tờ báo này đang cố gắng quảng cáo rùm beng để lôi kéo doanh nghiệp. Mỗi một trong số những thực thể này mang thuộc tính lang xác định mã cho ngôn ngữ đang nói đến. Bạn có thể cung cấp các tên thay thế từ các chữ viết tắt phổ biến, ví dụ, IBM thay cho International Business Machines.

Mô tả tùy chọn sắp tới chỉ là một chuỗi văn bản. Trong thực tế, hầu hết các phần tử chính trong UDDI có một mô tả tùy chọn.

Tiếp theo, Francis có thể thêm nhiều mối liên hệ hơn nữa. Đối với mỗi liên hệ anh ta có thể xác định nhiều hay ít thông tin khi cần thiết personName thường được cung cấp, nhưng các thông tin như số điện thoại, e-mail và v.v được cung cấp dựa trên ý muốn của những người có liên quan, do tất cả các thông tin trong Đăng ký UDDI (Registry UDDI) là công khai cho tất cả người dùng. Các liên hệ cũng có thể có một địa chỉ, với useType quy định cụ thể loại địa chỉ. Ví dụ, trong trường hợp của một mối liên hệ, thông tin có thể là địa chỉ nhà so với thông tin công việc và v.v. Trong trường hợp của một công ty, useType có thể là văn phòng chính, trung tâm phân phối và v.v.

Phần tử businessServices liệt kê các dịch vụ bất kỳ đã được liên kết với businessEntity này. Vì Gene vẫn chưa thêm bất kỳ các dịch vụ nào, nên phần tử này thường vẫn rỗng. Hai mục cuối cùng, identifierBagcategoryBag, cung cấp thêm thông tin về chính công ty đó và được sử dụng trong tìm kiếm. Chúng ta sẽ xem xét từng thứ trong chúng ngay sau đây.

publisherAssertion

Một publisherAssertion là một câu lệnh về mối quan hệ của một businessEntity này với một businessEntity khác. Ví dụ, Francis biết rằng một trong những mục tiêu của dự án này là sử dụng một dịch vụ được cung cấp trong tờ báo Daily Star, trong đó tờ Daily Star cung cấp các điểm số của các môn thể thao cho tờ Daily Moon. Điều đó khiến cho tờ Daily Star trở thành một nhà cung cấp nội dung cho tờ Daily Moon.Francis có thể biểu thị điều đó như thể hiện trong Liệt kê 3.

Liệt kê 3. publisherAssertion
<publisherAssertion>
<fromKey>(businessKey for Daily Star)</fromKey>
<toKey>(businessKey for Daily Moon)</toKey>
<keyedReference tModelKey="904BD800-D53A-11DA-B055-850A1DA99D79" 
         keyName="optional" keyValue="CONTENTPROVIDER" />
</publisherAssertion>

Các phần tử fromKeytoKey biểu thị các mã nhận dạng (ID) duy nhất cho hai thực thể có liên quan. Trong trường hợp này, đó là tờ Daily Moon và tờ Daily Star. Tờ Daily Star là nhà cung cấp nội dung cho tờ Daily Moon, do đó, các khóa được đặt cho phù hợp. Chúng ta sẽ thấy keyedReference (Tham chiếu có khóa) nhiều lần. Trong trường hợp này, chúng ta sẽ nói rằng chính tham chiếu đó là một nhà cung cấp nội dung. keyValue (Giá trị khóa) là thuộc tính duy nhất cần thiết cho một keyedReference, nhưng cũng bình thường để bao gồm một keyName (Tên khóa) cho dễ đọc và một tModelKey để nhận dạng một kiểu tham chiếu cụ thể. Trong trường hợp này tModelKey biểu thị cho vùng tên của các hiệp hội giữa các tờ báo đối lập với các đại diện bên trong. Một lát nữa chúng ta sẽ nói thêm về tModels.

businessService

Tiếp theo, Francis cần nhập thông tin về các dịch vụ thực tế bất kỳ mà tờ Daily Moon sắp cung cấp. Một đối tượng businessService chứa hai mẩu thông tin chính ngoài serviceKey duy nhất cần thiết và tên. Chúng là bindingTemplates và bất kỳ các thể loại nào mà dịch vụ này thuộc về chúng. Xem Liệt kê 4.

Liệt kê 4. businessService
<businessService serviceKey="required" businessKey="optional">
<name></name>
<description></description>
<bindingTemplates>
<bindingTemplate serviceKey="optional" bindingKey="required">
         ...
</bindingTemplate>
</bindingTemplates>
<categoryBag>
      ...
</categoryBag>
</businessService>

BindingTemplate

Tmodelinstancedetails là một sự biểu thị về nó tương thích với những ứng dụng hoặc các đặc tả nào. Xem Liệt kê 5.

Liệt kê 5. The bindingTemplate

Nhấp vào để xem mã nguồn

Liệt kê 5. The bindingTemplate

<bindingTemplate serviceKey="optional" bindingKey="required"><accessPoint> OR <hostingRedirector bindingKey="another binding to be used instead"> 
<tModelInstanceDetails> <tModelInstanceDetail> 
<tModelInstanceInfo tModelKey=""uuid key for specification tModel">>
<description></description>
<instanceDetails>
<description></description>
<overviewDoc>
<description></description>
<overviewURL></overviewURL>
</overviewDoc>
<instanceParams>string</intstanceParms>
</instanceDetails>
</tModelInstanceInfo>
<tModelInstanceInfo>
            ...
</tModelInstanceInfo>
</tModelInstanceDetail> 
<tModelInstanceDetails> 
</bindingTemplate>
TModels (including tModel of tModels)
Serve two purposes.  As specification indicators, and as namespace indicators.
<tModel tModelKey="required" operator="optional" 
authorizedName="optional">
<name></name>
<description></description>
<overviewDoc>
<description></description>
<overviewURL></overviewURL>
<overviewDoc>

   <identifierBag>
...
</identifierBag>
<categoryBag>
      ...
</categoryBag>
</tModel>

Một bindingTemplate là thứ định nghĩa cả nơi người ta có thể tìm thấy dịch vụ lẫn dịch vụ này làm gì, nghe có vẻ đơn giản. Tuy nhiên, cả hai hàm này đảm nhận ý nghĩa mới trong nội dung của UDDI. Ví dụ, để xác định có thể truy cập một dịch vụ ở đâu, bạn có thể cung cấp một accessPoint, đại diện cho một URL đơn giản hoặc bất kỳ dữ liệu thích hợp khác, chẳng hạn như một số điện thoại với một đường dây trợ giúp hoặc một hostingRedirector.

Các nguyên tắc phân loại

Khi chúng ta phân loại thông tin, nó trợ giúp chúng ta khả năng thỏa thuận gọi các phân loại như thế nào. Các phân loại theo thỏa thuận được gọi là các nguyên tắc phân loại.

Ví dụ, NAICS (Hệ thống phân loại công nghiệp Bắc Mỹ) phân biệt giữa "cho thuê đồ thể thao", "các cửa hàng đồ thể thao" và "các cửa hàng đồ thể thao, đã sử dụng," bằng cách gán cho mỗi thứ một mã số duy nhất. Bằng cách này, khi bạn bắt gặp một mã số là 532.292, bạn biết bạn đang nói về một nơi để thuê đồ thể thao, ngược với một nơi để mua chúng.

Các toán tử của UDDI thêm một số của các nguyên tắc phân loại cho hệ thống như là một thông lệ, làm cho chúng sẵn sàng cho việc sử dụng của bạn mà không cần phải đăng ký tModels cho chúng. Ví dụ, jUDDI để tạo ra một tModel cho uddi-org:general_keywords với một khóa tModelA035A07C-F362-44DD-8F95-E2B134BF43B4, vì vậy bạn có thể sử dụng tModel mà không cần định nghĩa tModel cho riêng mình.

Người ta thường sử dụng hostingRedirector khi ràng buộc cho một dịch vụ thay đổi. Ví dụ, nếu tờ Daily Moon đã thiết lập dịch vụ các đoạn quảng cáo được phân loại của nó và cho phép cả hai tờ báo gửi các đoạn quảng cáo lên bằng cách sử dụng cuộc gọi createNewAdd(), thì tờ báo này sẽ cần hoặc là đảm bảo rằng các dịch vụ không bao giờ thay đổi hoặc cung cấp một cách để cho các ứng dụng khách biết dịch vụ đã thay đổi. Đó là nơi mà hostingRedirector được dùng. Trong trường hợp đó, Francis (hoặc trên thực tế là Gene) sẽ tạo ra một bindingTemplate mới, biểu thị cho các thông tin mới và nhập bindingKey của bindingTemplate đó vào trong thuộc tính bindingKey của phần tử hostingRedirector.

Việc xác định các dịch vụ làm gì thậm chí có thể còn khó khăn hơn. Lý do của việc này có hai phần. Trước tiên, vì chúng ta không nhất thiết phải nói về một dịch vụ SOAP, bạn không thể chỉ cần cung cấp một tệp WSDL. Thứ hai, vì điều này được hiểu là một quá trình tự động, nên bạn cần cung cấp thông tin này theo một cách như vậy là hoàn toàn rõ ràng.

Kết quả là bindingTemplate bao gồm một phần tử tModelInstanceDetails, trong đó có một hoặc nhiều phần tử tModelInstanceDetail. Mỗi một trong số các phần tử đó bao gồm một hoặc nhiều phần tử tModelInstanceInfo, trỏ đến một tModel cụ thể. Một lần nữa, chúng ta sẽ nói về tModels ngay sau đây. Tuy nhiên, điều quan trọng cần hiểu là phần tử tModelInstanceInfo có thể chứa một phần tử instanceDetails, mà bản thân phần tử instanceDetails lại chứa một overviewDoc, bao gồm overviewURL, một URL cho một tài liệu thực sự xác định dịch vụ đó. (Đúng, đó là nơi bạn xác định tệp WSDL).

TModels (bao gồm cả tModel của tModels)

Bây giờ hãy nói về tModels.

tModels thực sự nhằm vào hai mục đích. Đầu tiên, như chúng ta đã thấy một chút trong cuộc thảo luận về publisherAssertions, là một phần của "bộ chỉ thị vùng tên". Nói cách khác, một tModel có thể cung cấp cách để phân biệt giữa các kiểu thông tin có thể dẫn đến nhầm lẫn. Một ví dụ như mã số thuế hoặc giá trị khác dễ nhầm với các số. Ví dụ, một keyedReference có những điều sau dường như không cung cấp tất cả các thông tin, vì hai mã nhận dạng thuế này thuộc về các nước khác nhau. Trong cả hai nước, chúng được gọi là mã số thuế, nhưng theo lập trình, chúng ta phải có một cách để phân biệt giữa chúng, như trong Liệt kê 6.

Liệt kê 6. Các mã số thuế của các nước khác nhau
<keyedReference tModelKey="" keyName="taxid" 
keyValue="11111111" />
<keyedReference tModelKey="" keyName="taxid" 
keyValue="22222222" />

Đó là nơi một tModel được dùng. Chúng ta có thể tạo một mô hình chính cho "mã số thuế của Hoa Kỳ" và một mô hình cho "mã số thuế của Mexico" và v.v. Một khi chúng ta tạo các mô hình đó, chúng ta có thể sử dụng các khóa tModel của các mô hình để đánh giá kỹ hơn nữa các keyedReferences. Xem Liệt kê 7.

Liệt kê 7. tModelskeyedReferences
<tModel tModelKey="902CDE50-D53A-11DA-B055-A74C17FA61A7">
   <name>United States codes</name>
</tModel>
<tModel tModelKey="062377D0-D5F5-11DA-8170-8ACF057FECAD">
   <name>Mexico codes</name>
</tModel>
<keyedReference tModelKey="902CDE50-D53A-11DA-B055-A74C17FA61A7" 
                keyName="taxid" keyValue="11111111" />
<keyedReference tModelKey="062377D0-D5F5-11DA-8170-8ACF057FECAD" 
                keyName="taxid" keyValue="22222222" />

Cách sử dụng khác của tModel là như một trình nhận dạng đặc tả. Ví dụ, Francis biết rằng Gene là sẽ tạo các mục cho ClassifiedService mà hai nhân viên này đã làm trong tháng trước. Dịch vụ này biểu thị một giao diện cụ thể và như vậy, người ta có thể nhận biết dịch vụ này bằng cách sử dụng một tModel. tModel này có thể trông giống như thứ được hiển thị trong Liệt kê 8.

Liệt kê 8. tModel
<tModel tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A" 
        operator="optional" authorizedName="optional">

   <name>Classified Service Interface</name>
   <description></description>

   <overviewDoc>
      <description></description>
      <overviewURL>
        http://www.daily-moon.com/ClassifiedService-interface.wsdl
      </overviewURL>
   <overviewDoc>

   <identifierBag>
...
   </identifierBag>

   <categoryBag>
      ...
   </categoryBag>
</tModel>

Cũng như với mọi đối tượng khác mà chúng ta đã xem xét tModel có một khóa duy nhất, đó là thông tin cần thiết duy nhất. Tuy nhiên, trong trường hợp này, chúng ta cũng muốn xác định overviewURL, có nghĩa là URL cho tệp WSDL của giao diện. (Chúng ta sẽ tạo nó trong phần tiếp theo).

Một lần nữa, người ta có thể nhận biết tModels bằng cách sử dụng một identifierBag và được phân loại bằng cách sử dụng một categoryBag. Hãy xem chúng hoạt động như thế nào.

identifierBag

Vì UDDI nhằm vào tính linh hoạt, nên không có cách cụ thể nào để nhận biết một businessEntity. UDDI không yêu cầu nhận biết một doanh nghiệp theo số D-U-N-S của nó hoặc theo mã số thuế của nó hoặc bằng bất kỳ phương pháp nhận biết cụ thể khác. Thay vào đó, UDDI cung cấp một thùng chứa (container) trong đó bạn có thể đặt bao nhiều trình nhận dạng tùy ý khi cần thiết, như bạn thấy trong Liệt kê 9.

Liệt kê 9. indentifierBag

Nhấp vào để xem mã nguồn

Liệt kê 9. indentifierBag

<identifierBag><keyedReference tModelKey="4064C064-6D14-4F35-8953-9652106476A9" 
                        keyName="DUNS Number" keyValue="55555555" /><keyedReference tModelKey="" keyName="US Tax ID" keyValue="111111111" /> 
</identifierBag>

Mỗi keyedReference được bạn thêm vào trong một identifierBag biểu thị cơ hội khác cho những người dùng tìm thấy đối tượng đang nói đến trong một tìm kiếm.

categoryBag

categoryBag hoạt động như identifierBag, trong đó nó có chứa một hoặc nhiều keyedReferences. Xem Liệt kê 10.

Liệt kê 10. categoryBag
<categoryBag> 
<keyedReference tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
           keyName="optional" keyValue="511110" /> 
</categoryBag>

Trong trường hợp này, Francis đã tạo một categoryBag cho thấy rằng tờ Daily Moon là một văn phòng chi nhánh của tờ báo. Bây giờ hãy xem cách sử dụng tất cả các đối tượng này.


Ánh xạ WSDL tới UDDI

Trước khi Gene có thể viết bất kỳ mã nào để gửi tất cả các thông tin này tới đăng ký UDDI, Gene phải thực hiện một kết nối quan trọng giữa các dịch vụ hiện tại của họ và UDDI. Gene phải làm thích nghi các dịch vụ hiện tại này với khái niệm của UDDI về các dịch vụ, các giao diện và các khuôn mẫu ràng buộc.

Các dịch vụ so với các giao diện

Cách nhìn của UDDI về một dịch vụ, như bạn có thể nhớ lại, bao gồm ba phần: giao diện, được xác định bằng cách sử dụng tModels; businessService; và bindingTemplate, liên kết hai trong số chúng lại với nhau. Vì vậy, bước đầu tiên của Gene là tìm hiểu tệp WSDL định nghĩa dịch vụ SOAP có thể khớp trong cấu trúc này như thế nào.

Bước đầu tiên của Gene là phân chia WSDL. May mắn thay, điều này khá đơn giản. Giao diện này bao gồm tất cả các mảnh của tệp WSDL trừ ra việc thực hiện thực tế của nó. Xem Liệt kê 11.

Liệt kê 11. Giao diện 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: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: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: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: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: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>
</wsdl:definitions>

Giao diện này bao gồm các định nghĩa kiểu (lược đồ XML), các thông báo bất kỳ portType ngay cả binding (ràng buộc), bởi vì ràng buộc không đặc trưng cho việc thực hiện cụ thể.

Việc thực hiện bao gồm phần tử dịch vụ thực tế. Xem Liệt kê 12.

Liệt kê 12. Việc thực hiện dịch vụ 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://www.daily-moon.com/ClassifiedService-interface"
      xmlns:axis2="http://ws.apache.org/axis2"
      xmlns:ns1="http://org.apache.axis2/xsd" 
      targetNamespace=
        "http://www.daily-moon.com/ClassifiedService-interface">

<wsdl:import namespace="http://ws.apache.org/axis2" 
   location=
"http://www.nicholaschase.com/ClassifiedService-interface.wsdl" 
/>

<wsdl:service name="ClassifiedService">
   <wsdl:port name="ClassifiedServicePort" 
               binding="axis2:ClassifiedServiceBinding">
      <soap:address 
         location=
 "http://www.daily-moon.com:8080/axis2/services/ClassifiedService" 
      />
   </wsdl:port>
</wsdl:service>

</wsdl:definitions>

Lưu ý rằng tệp thực hiện nhập khẩu tệp giao diện. Nói cách khác, tệp này là định nghĩa đầy đủ của dịch vụ.

Bây giờ hãy xem tệp đó tương ứng với các đối tượng UDDI của chúng ta như thế nào.

Ánh xạ giao diện tới một tModel

Đầu tiên Gene đã phải ánh xạ giao diện tới một tModel thích hợp. Xem Liệt kê 13.

Liệt kê 13. tModel
<tModel tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A">

  
 <name>http://www.daily-moon.com/ClassifiedService-
interface</name>
   <description>Interface for the Daily Moon Classified 
Department web application</description>

   <overviewDoc>
      <description>WSDL interface document</description>
      <overviewURL>
          http://www.daily-moon.com/ClassifiedService-interface.wsdl
      </overviewURL>
   <overviewDoc>

   <categoryBag>
      <keyedReference
 tModelKey="C1ACF26D-9672-4404-9D70-39B756E62AB4"
               keyName="uddi-org:types" keyValue="wsdlSpec" />
      <keyedReference
 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
               keyName="ntis-gov:naics:1997" keyValue="511110" />
   </categoryBag>
</tModel>

Bắt đầu từ phía dưới cùng, lưu ý categoryBag. Gene đã thêm vào hai keyReferences. Tham chiếu đầu tiên quy định rằng trên thực tế chúng ta đang xử lý một tệp WSDL. Người ta đã xác định trước tModelKey cụ thể đó để biểu thị vùng tên uddi-org:types. Tất cả các tệp WSDL phải được xác định theo cách này. Tham chiếu thứ hai được liên kết với vùng tên ntis-gov:naics:1997 do đó, thật dễ dàng cho những người dùng của Gene tìm định nghĩa này trong số tất cả các tệp WSDL biểu thị các dịch vụ phải làm với các tờ báo. Tiếp tục lên, chúng ta thấy overviewDoc. Ngoài mô tả tùy chọn, nó xác định URL thực tế mà chúng ta có thể tìm thấy tệp WSDL ở đó.

Cuối cùng, tên của tModel phải khớp với vùng tên đích của tệp WSDL.

Ánh xạ việc thực hiện với một khuôn mẫu ràng buộc

Tiếp theo Gene phải ánh xạ chính việc thực hiện này tới một bindingTemplate. Xem Liệt kê 14.

Liệt kê 14. bindingTemplate
<bindingTemplate serviceKey="" bindingKey="">

   <accessPoint>
      http://www.daily-moon.com:8080/axis2/services/ClassifiedService
   </accessPoint>

   <tModelInstanceDetails>
      <tModelInstanceDetail>
         <tModelInstanceInfo 
                 tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A">
            <instanceDetails>
               <description>The canonical implementation of 
                  the Daily Moon's classified service.</description>
               <overviewDoc>
                  <overviewURL>
                     http://www.daily-moon.com/ClassifiedService-impl.wsdl
                  </overviewURL>
               </overviewDoc>
            </instanceDetails>
         </tModelInstanceInfo>
      </tModelInstanceDetail>
   </tModelInstanceDetails>


</bindingTemplate>

Ở đây chúng ta thấy rằng Gene tạo một bindingTemplate mới, thiết lập accessPoint như URL cho dịch vụ thực tế modelInstanceDetails chủ yếu liên kết giao diện tModel (qua tModelKey) với tài liệu thực hiện (được quy định trong overviewDoc). Bây giờ Gene chỉ phải tham chiếu nó từ dịch vụ.

Tham chiếu bindingTemplate từ businessServicebusinessEntity

Bước cuối cùng là đặt bindingTemplate tất cả lại với nhau và tham chiếu businessServicebusinessService từ businessEntity. Xem Liệt kê 15.

Liệt kê 15. businessEntity đầy đủ
<businessEntity businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691">
   <name>The Daily Moon</name>
   <name lang="fr-ca">La Lune Quotidienne</name>
   <contacts>
      <contact>
         <personName>Pat Mooney</personName>
         <email>patm@daily-moon.com</email>
      </contact>
   </contacts>

   <businessServices>
      <businessService serviceKey="064B4170-D5F5-11DA-8170-A74C17FA61A7">
         <name>ClassifiedService</name>
         <bindingTemplates>
            <bindingTemplate 
                 bindingKey="904BD800-D53A-11DA-B055-850A1DA99D79">
               <accessPoint>
                  http://www.daily-moon.com:8080/axis2/services/ClassifiedService
               </accessPoint>

               <tModelInstanceDetails>
                  <tModelInstanceDetail>
                     <tModelInstanceInfo tModelKey=
                                 "66999A50-D5F4-11DA-9A50-FA44D6AD622A">
                        <instanceDetails>
                           <description>The canonical implementation of the 
                             Daily Moon's classified service.</description>
                           <overviewDoc>
                              <overviewURL>
                              http://www.daily-moon.com/ClassifiedService-impl.wsdl
                              </overviewURL>
                           </overviewDoc>
                        </instanceDetails>
                     </tModelInstanceInfo>
                  </tModelInstanceDetail>
               </tModelInstanceDetails>

            </bindingTemplate>
         </bindingTemplates>

         <categoryBag>
            <keyedReference 
                 tModelKey="C1ACF26D-9672-4404-9D70-39B756E62AB4"
                 keyName="uddi-org:types" keyValue="wsdlSpec" />
            <keyedReference 
                 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
                 keyName="ntis-gov:naics:1997" keyValue="511110" />
         </categoryBag>
      </businessService>
   </businessServices>

   <identifierBag>
      <keyedReference
         tModelKey="4064C064-6D14-4F35-8953-9652106476A9" 
         keyName="DUNS Number" keyValue="55555555" />
      <keyedReference tModelKey="" 
         keyName="US Tax ID" keyValue="111111111" />
   </identifierBag>

   <categoryBag>
      <keyedReference
          tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
          keyName="optional" keyValue="511110" />
   </categoryBag>
</businessEntity>

Nói cách khác, dịch vụ đã hoàn tất: bây giờ Gene có một businessEntity bao gồm một dịch vụ


Tìm và sử dụng thông tin

Bây giờ tất cả các thông tin có trong dịch vụ, ít nhất về mặt lý thuyết, Gene cần phải xem xét quá trình để tìm kiếm thông tin một lần nữa.

Các việc tìm kiếm của UDDI hoạt động như thế nào: tìm kiếm một doanh nghiệp

Việc tìm kiếm trong UDDI gồm hai bước. Đầu tiên, bạn tìm khóa của đối tượng mà bạn muốn và sau đó bạn lấy thông tin về đối tượng đó. Cuối cùng, để cho Gene tìm một doanh nghiệp, Gene cần tạo một yêu cầu find_business, như trong Liệt kê 16.

Liệt kê 16. Tìm một doanh nghiệp theo thể loại
<find_business generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <categoryBag>
      <keyedReference
           tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
           keyName="optional" keyValue="511110" />
   </categoryBag>
</find_business>

Yêu cầu này sẽ tìm tất cả các doanh nghiệp khớp với các thể loại được tham chiếu trong categoryBag. Các việc tìm kiếm về giá trị categoryBag được xử lý như một việc tìm kiếm ""VÀ" (AND). Nói cách khác, mục bất kỳ trùng khớp ít nhất là một trong các thể loại phải khớp. Bạn cũng có thể xác định một tìm kiếm identifierBag theo cách này. Tuy nhiên, Gene không thực sự quan tâm đến tìm kiếm theo thể loại. Vào lúc này, Gene chỉ muốn xem có hay không có doanh nghiệp trong đăng ký, do đó để thay thế Gene thích tìm kiếm theo tên hơn, như trong Liệt kê 17.

Liệt kê 17. Tìm một doanh nghiệp theo tên
<find_business generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <name>daily</name>
</find_business>

Lưu ý rằng một tìm kiếm theo tên được xử lý như thể tên mà bạn đang tìm kiếm tiếp sau là một ký tự đại diện. Nói cách khác, việc tìm kiếm ở đây là giống như thực hiện một tìm kiếm với "daily*", do đó cả Daily MoonDaily Star và bất kỳ doanh nghiệp khác nào bắt đầu với từ "daily" sẽ hiển thị. Những tìm kiếm này cũng phân biệt chữ hoa, chữ thường.

Việc tìm kiếm tìm thấy gì

find_business yêu cầu trả về một businessList. Xem Liệt kê 18.

Liệt kê 18. Một tìm kiếm trả về các doanh nghiệp
<businessList generic="2.0" operator="uddi.sourceOperator" 
    truncated="true" xmlns="urn:uddi-org:api_v2">

   <businessInfos>

      <businessInfo 
            businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691" >
          <name>The Daily Moon</name>
          <serviceInfos>
             <serviceInfo serviceKey=
                     "064B4170-D5F5-11DA-8170-A74C17FA61A7">
                <name>ClassifiedService</name>
             </serviceInfo>
          </serviceInfos>
      </businessInfo>

      <businessInfo>
         ...
      </businessInfo>

   </businessInfos>

</businessList>

businessList bao gồm một phần tử businessInfo cho mỗi businessEntity thỏa mãn tìm kiếm đó. Mỗi một trong số các phần tử serviceInfo đó có một businessKey cho businessEntity thực tế. businessList cũng bao gồm một phiên bản viết tắt của các thông tin sẽ được liệt kê trong businessEntity, để bạn có thể có được một ý tưởng về liệu đây có phải là một doanh nghiệp mà bạn đang tìm kiếm không.

Một khi bạn có businessKey, thích hợp, bạn cần phải có thêm thông tin về businessEntity này.

Một khi bạn có khóa

Để có thêm thông tin về một businessEntity cụ thể dựa trên businessKey, bạn cần phải thực hiện một yêu cầu get_businessDetail. Xem Liệt kê 19.

Liệt kê 19. Nhận thông tin về các doanh nghiệp
<get_businessDetail generic="2.0" xmlns="urn:uddi-org:api_v2" >
 <businessKey>1A3DB880-D5F4-11DA-B880-F94D3591C691
</businessKey>
</get_businessDetail>

Bạn có thể liệt kê càng nhiều businessKeys trong một yêu cầu get_businessDetail như bạn muốn. Mỗi một businessKeys sẽ có phần tử businessDetail riêng của mình trong các kết quả. Xem Liệt kê 20.

Liệt kê 20. Các chi tiết về doanh nghiệp được trả về
<businessDetail generic="2.0" operator="uddi.sourceOperator" 
    truncated="false" xmlns="urn:uddi-org:api_v2">

   <businessEntity
      businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691">
      <name>The Daily Moon</name>
      <name lang="fr-ca">La Lune Quotidienne</name>
      <contacts>
...
      <keyedReference 
              tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
              keyName="optional" keyValue="511110" />
      </categoryBag>
   </businessEntity> 

</businessDetail>

Mỗi phần tử businessDetail gồm toàn bộ businessEntity của doanh nghiệp có liên quan.

Thay đổi cách tìm kiếm hoạt động

Trong lúc tìm kiếm này hoạt động, có những lúc bạn muốn thay đổi hành vi của tìm kiếm đó. Ví dụ, có lẽ bạn muốn tìm kiếm một sự trùng khớp chính xác hơn là một sự trùng khớp của ký tự đại diện hoặc bạn muốn tìm kiếm theo chữ hoa hay chữ thường. Bạn có thể thay đổi hành vi của việc tìm kiếm bằng cách sử dụng findQualifiers. Xem Liệt kê 21.

Liệt kê 21. Sử dụng findQualifiers
<find_business generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <findQualifiers>
      <findQualifier>sortByNameAsc</findQualifier>
   <findQualifiers>
   <name>daily</name>
</find_business>

Trong trường hợp này, việc tìm kiếm sẽ tiến hành như bình thường, nhưng kết quả sẽ được trả về được sắp xếp theo tên. Bạn có thể thêm nhiều phần tử findQualifier như bạn muốn. Trong số các phần tử có sẵn để sử dụng là exactNameMatch, caseSensitiveMatch, sortByNameDesc, sortByDateAscsortByDateDesc, hay LikeKeys (báo cho đăng ký biết để xử lý các khóa trong một categoryBag hoặc identifierBag như là một điều kiện "HOẶC" (OR) nếu chúng chia sẻ cùng một tModelKey) và combineCategoryBags (xử lý tất cả các categoryBags của một businessEntity, liệu chúng có thuộc về businessEntity, businessService hoặc bindingTemplate, không, nếu như chúng thuộc về businessService đó).

Tìm một kiểu dịch vụ

Gene cũng muốn đảm bảo rằng những người dùng có thể tìm bất kỳ dịch vụ nào dựa trên một giao diện cụ thể. Ví dụ, truy vấn này sẽ định vị bindingTemplates mà bạn sử dụng giao diện ClassifiedService. Xem Liệt kê 22.

Liệt kê 22. Tìm một bindingTemplate
<find_binding generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <tModelBag>
     <tModelKey>66999A50-D5F4-11DA-9A50-FA44D6AD622A</tModelKey>
   </tModelBag>
</find_binding>

Truy vấn này trả về một serviceList. Xem Liệt kê 23.

Liệt kê 23. Các dịch vụ được trả về
<serviceList generic="2.0" operator="uddi.sourceOperator"    
                  xmlns="urn:uddi-org:api_v2">
   <serviceInfos>
      <serviceInfo 
            serviceKey="064B4170-D5F5-11DA-8170-A74C17FA61A7" 
            businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691">
          <name>ClassifiedService</name>
      </serviceInfo>
   </serviceInfos>
</serviceList>

Như trong trường hợp với find_business, sau đó bạn đã phải quay trở lại đó và yêu cầu thông tin về businessEntity, rồi bạn sẽ xác định thông tin yêu cầu trên các máy chủ dựa trên serviceKey. Xem Liệt kê 24.

Liệt kê 24. Nhận các chi tiết dịch vụ
<get_serviceDetail generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <serviceKey>064B4170-D5F5-11DA-8170-A74C17FA61A7
</serviceKey>
</get_serviceDetail>

Truy vấn này trả về một serviceDetail cho mỗi serviceKey cụ thể. Xem Liệt kê 25.

Liệt kê 25. Các chi tiết dịch vụ được trả về
<serviceDetail generic="2.0" operator="uddi.sourceOperator" 
    xmlns="urn:uddi-org:api_v2">
   <businessService 
          serviceKey="064B4170-D5F5-11DA-8170-A74C17FA61A7"
          businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691">
      <name>ClassifiedService</name>
      <bindingTemplates>
         <bindingTemplate 
             bindingKey="904BD800-D53A-11DA-B055-850A1DA99D79">
            <accessPoint>
      http://www.daily-moon.com:8080/axis2/services/ClassifiedService
            </accessPoint>
...
         <keyedReference 
              tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
              keyName="ntis-gov:naics:1997" keyValue="511110" />
      </categoryBag>
   </businessService>
   <businessService>
...
   </businessService>
</serviceDetail>

Bây giờ Gene biết những gì mình muốn làm, anh ta sẵn sàng bắt đầu viết mã.


Làm việc với UDDI theo chương trình

Công việc cuối cùng của Gene là thiết lập một nhóm các ứng dụng bằng chứng-cho-nội dung để hiển thị cho các nhóm khác có thể xây dựng các ứng dụng dựa trên đăng ký UDDI như thế nào.

Thiết lập

Bước đầu tiên trong khi làm việc với một đăng ký UDDI là phần mềm đăng ký của chính UDDI, nhưng Gene ngạc nhiên thích thú phát hiện ra rằng do tờ báo đang sử dụng Apache Geronimo làm máy chủ ứng dụng Web của mình, nên bước đó dễ dàng được Apache Geronimo quan tâm đến; Geronimo đi kèm với Apache jUDDI được cài đặt sẵn.

Điều đó đã được thực hiện, Gene phải quyết định cách anh ta thực sự sẽ truy cập vào đăng ký. Ở đây, Gene có hai sự lựa chọn. Sự lựa chọn đầu tiên là thực hiện đăng ký trực tiếp, sử dụng một UDDI dựa trên các API như một UDDI có trong jUDDI hoặc UDDI4J. Sự lựa chọn thứ hai là sử dụng một việc thực hiện JAXR (Java API cho Các đăng ký XML - Java API for XML Registries). JAXR được dự định để truy cập vào bất kỳ đăng ký nào, với sự hỗ trợ UDDI và ebXML là mục tiêu chính của nó.

Gene quyết định đi thẳng vào mã nguồn và tải UDDI4J. Nói cách khác, UDDI4J phụ thuộc vào một số các thư viện được phân phối cùng với Apache Axis, do đó Gene cũng tải Apache Axis. (Lưu ý rằng mặc dù các phần trước của dự án này đã sử dụng Axis2, UDDI4J phụ thuộc vào các thư viện phân phối cùng với Axis 1).

Việc thiết lập khá đơn giản, đòi hỏi Gene chỉ cần đảm bảo rằng tất cả các tệp UDDI4J và tệp Axis *. jar cần thiết có trên đường dẫn lớp (classpath) này. Xem Liệt kê 26.

Liệt kê 26. Việc thiết lập tập hợp
CLASSPATH=.;
<UDDI4J_HOME>\lib\uddi4j.jar;
<AXIS_HOME>\lib\axis.jar;
<AXIS_HOME>\lib\saaj.jar;
<AXIS_HOME>\lib\jaxrpc.jar;
<AXIS_HOME>\lib\log4j-1.2.8.jar;
<AXIS_HOME>\lib\commons-logging-1.0.4.jar;
<AXIS_HOME>\lib\commons-discovery-0.2.jar;

Cuối cùng, Gene cần một tên người dùng và mật khẩu để kết nối đến đăng ký. Về mặt này, mỗi đăng ký là khác nhau, vì vậy chúng ta sẽ không đi vào chi tiết. Việc cài đặt mặc định của UDDI trong Apache Geronimo sử dụng một tên người dùng và mật khẩu là "juddi".

Kết nối tới đăng ký

Bước đầu tiên trong bất kỳ ứng dụng nào là kết nối tới đăng ký. Xem Liệt kê 27.

Liệt kê 27. Kết nối tới đăng ký
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;

public class CreateNewBusiness {

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String transportClass = 
             "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                token.getAuthInfoString());

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

Bắt đầu từ đầu, Gene thiết lập các giá trị khác nhau mà Gene sẽ cần trong suốt ứng dụng. Cụ thể, Gene đặt tên lớp cho TransportFactory. UDDI4J có thể sử dụng số lượng bất kỳ của các lớp thích hợp, chẳng hạn như một lớp đi kèm với Apache Axis, như bạn thấy ở đây, một lớp đi kèm với gói Apache SOAP cũ hoặc bất cứ thứ gì tương tự.

Cuối cùng, Gene thiết lập các giá trị inquiryURLpublishURL cho đăng ký đó -- các giá trị này thường sẽ khác nhau, một phần vì việc xuất bản luôn được thực hiện bằng cách sử dụng SSL -- và yêu cầu một thẻ (token) ủy quyền.

Thẻ này rất quan trọng vì nó là cách mỗi yêu cầu biểu thị rằng nó đã được xác thực với máy chủ. Bởi vì mỗi đăng ký xử lý những thứ khác nhau, nên để duy trì việc gửi tên người dùng và mật khẩu với mỗi yêu cầu là không thực tế (hoặc an toàn).

Khi chạy ứng dụng này, Gene thấy một kết quả như sau:
Security authToken:authToken:505A7DE0-D897-11DA-A5BF-ADFF17B378CF

Tạo một thực thể kinh doanh

Tiếp theo Gene muốn tạo một thực thể kinh doanh. Xem Liệt kê 28.

Liệt kê 28. Tạo businessEntity
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;

import org.uddi4j.datatype.business.BusinessEntity; 
   import org.uddi4j.response.BusinessDetail; 
   import org.uddi4j.datatype.business.Contact; 
   import org.uddi4j.datatype.business.Contacts; 
   import org.uddi4j.util.KeyedReference; 
   import org.uddi4j.util.IdentifierBag; 
   import org.uddi4j.util.CategoryBag; 
   import org.uddi4j.datatype.tmodel.TModel; 
   import java.util.Vector;

public class CreateNewBusiness {

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String businessName = "The Daily Moon"; 
         String alt_businessName = "Daily Moon"; 
         String contact_personName = "Pat Moonie"; 
         String contact_phone = "212-555-1212"; 
         String identifier_homepage = "http://www.daily-moon.com"; 
         String category_NAICS = "511110";

      String transportClass = 
               "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                token.getAuthInfoString());

         Vector entities = new Vector(); 
            BusinessEntity newBusiness = new BusinessEntity("", businessName); 
            Contact newContact = new Contact(contact_personName); 
            Vector contactsVector = new Vector(); 
            contactsVector.addElement(newContact); 
            Contacts contacts = new Contacts(); 
            contacts.setContactVector(contactsVector); 
            newBusiness.setContacts(contacts); 
            KeyedReference taxid = new KeyedReference(TModel.HOMEPAGE_TMODEL_KEY, 
                                        identifier_homepage); 
            IdentifierBag idBag = new IdentifierBag(); i
            dBag.add(taxid); 
            newBusiness.setIdentifierBag(idBag); 
            KeyedReference category = new KeyedReference(TModel.NAICS_TMODEL_KEY, 
                                        category_NAICS); 
            CategoryBag catBag = new CategoryBag(); 
            catBag.add(category); 
            entities.addElement(newBusiness); 
            BusinessDetail bd = proxy.save_business(token.getAuthInfoString(), entities); 
            Vector businessEntities = bd.getBusinessEntityVector(); 
            BusinessEntity returnedBusinessEntity = (BusinessEntity)
                                             (businessEntities.elementAt(0)); 
            System.out.println("The new businessKey:" + 
                                     returnedBusinessEntity.getBusinessKey());

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

Quá trình kết hợp một businessEntity với nhau về cơ bản bao gồm các phần tử xây dựng giống như chúng đang ở trong XML, với dạng "số nhiều" (như "contacts" (các liên hệ), "tModelInfos" và v.v) được xử lý như các vectơ.

Trong trường hợp này, Gene xây dựng vector liên hệ identifierBagcategoryBag và thêm các vector liên hệ này vào đối tượng BusinessEntity. Đối tượng tự nó được thêm vào một Vector, tức là các phương thức save_business() này, cùng với thẻ uỷ quyền.

Kết quả là một đối tượng BusinessDetail có chứa một hoặc nhiều đối tượng BusinessEntity khi các đối tượng này có trong cơ sở dữ liệu. Trong trường hợp này, Gene gửi BusinessEntity đi mà không cần một giá trị cho businessKey, để cho đăng ký biết tạo một đối tượng mới và do đó tạo một khóa mới. Bằng cách lấy BusinessEntity đầu tiên từ vectơ, sau đó Gene có thể có được một businessKey mới.

Khi chạy ứng dụng này, Gene nhận được kết quả được hiển thị trong Liệt kê 29:

Liệt kê 29. Nhận được một businessKey mới
Security authToken:authToken:1D05DB90-D899-11DA-A5BF-D3513DE466CA
The new businessKey:1D359E20-D899-11DA-A5BF-F9EAF6D4E3F7

Tạo một giao diện dịch vụ tModel

Với doanh nghiệp tại chỗ, tiếp theo Gene bắt đầu thêm giao diện dịch vụ. Xem Liệt kê 30.

Liệt kê 30. Tạo một tModel
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;
import java.util.Vector;

import org.uddi4j.datatype.tmodel.TModel; 
   import org.uddi4j.response.TModelDetail; 
   import org.uddi4j.datatype.OverviewURL; 
   import org.uddi4j.datatype.OverviewDoc; 
   import org.uddi4j.util.CategoryBag; 
   import org.uddi4j.util.KeyedReference;

public class CreateNewInterface{

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String transportClass = 
            "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
            transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                   token.getAuthInfoString());

         Vector tModels = new Vector(); 
            TModel tModel = new TModel("", 
                           "http://www.daily-moon.com/classifieds-interface"); 
            tModel.setDefaultDescriptionString( 
                                 "Interface for the Daily Moon Classified "+ 
                                 "Department web application"); 
            OverviewDoc overviewDoc = new OverviewDoc(); 
            overviewDoc.setDefaultDescriptionString( "WSDL interface document"); 
            OverviewURL overviewURL = new OverviewURL( 
                   "http://www.nicholaschase.com/ClassifiedsService-interface.wsdl"); 
            overviewDoc.setOverviewURL(overviewURL); 
            tModel.setOverviewDoc(overviewDoc); 
            KeyedReference wsdlNotation = new KeyedReference(TModel.TYPES_TMODEL_KEY, 
                     "wsdlSpec", "C1ACF26D-9672-4404-9D70-39B756E62AB4"); 
            KeyedReference typeNotation = new KeyedReference("ntis-gov:naics:1997", 
                   "511110", "C0B9FE13-179F-413D-8A5B-5004DB8E5BB2"); 
            CategoryBag catBag = new CategoryBag(); 
            catBag.add(wsdlNotation); 
            catBag.add(typeNotation); 
            tModel.setCategoryBag(catBag); 
            tModels.add(tModel); 
            TModelDetail tModelDetail = proxy.save_tModel(token.getAuthInfoString(), 
                                            tModels); 
            Vector tModelVector = tModelDetail.getTModelVector(); 
            TModel tModelReturned = (TModel)(tModelVector.elementAt(0)); 
            System.out.println("TModel Saved: " + tModelReturned.getNameString()); 
            System.out.println("TModel Key : " + tModelReturned.getTModelKey());

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

Như trước, Gene bắt đầu tạo mô hình phần tử XML trong mã Java. Gene bắt đầu bằng cách tạo TModel, lại không có khóa để biểu thị rằng anh ta tạo một đối tượng mới và thiết lập sự mô tả. Sau đó Gene tạo OverviewDoc, bao gồm sự mô tả và OverviewURL. Tiếp theo, Gene tạo KeyedReferences cho CategoryBag. Lưu ý rằng Gene sẽ tham chiếu tModels, cụ thể, vì thế Gene cung cấp tModelKey cho mỗi một trong số chúng; giá trị này là tùy chọn. Cuối cùng, Gene lưu TModel, một lần nữa lấy ra đối tượng từ giá trị được trả về.

Việc chạy ứng dụng cung cấp cho Gene kết quả được hiển thị trong Liệt kê 31:

Liệt kê 31. Nhận được một khóa tModel mới
Security authToken:authToken:3312DF20-D8A1-11DA-A5BF-D754085751C9
TModel Saved: http://www.daily-moon.com/classifieds-interface
TModel Key  : uuid:332F67D0-D8A1-11DA-A5BF-DF15F533BFA1

Tạo một dịch vụ

Tạo chính dịch vụ đó theo cùng thủ tục cơ bản. Xem Liệt kê 32.

Liệt kê 32. Tạo dịch vụ
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;
import java.util.Vector;

import org.uddi4j.datatype.business.BusinessEntity; 
   import org.uddi4j.datatype.service.BusinessService; 
   import org.uddi4j.datatype.binding.BindingTemplate; 
   import org.uddi4j.datatype.binding.BindingTemplates; 
   import org.uddi4j.util.CategoryBag; 
   import org.uddi4j.util.KeyedReference; 
   import org.uddi4j.datatype.binding.AccessPoint; 
   import org.uddi4j.datatype.binding.TModelInstanceDetails; 
   import org.uddi4j.datatype.binding.TModelInstanceInfo; 
   import org.uddi4j.datatype.binding.InstanceDetails; 
   import org.uddi4j.datatype.OverviewDoc; 
   import org.uddi4j.datatype.OverviewURL; 
   import org.uddi4j.datatype.tmodel.TModel; 
   import org.uddi4j.response.ServiceDetail;

public class CreateNewService{

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";
      String businessKey = "1D359E20-D899-11DA-A5BF-F9EAF6D4E3F7";

      String transportClass = 
           "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                   token.getAuthInfoString());

         BusinessService businessService = new BusinessService(""); 
            businessService.setDefaultNameString( "ClassifiedService",null); 
            businessService.setBusinessKey(businessKey); 
            BindingTemplate bindingTemplate = new BindingTemplate(); 
            AccessPoint accessPoint = new AccessPoint( 
               "http://www.daily-moon.com:8080/axis2/services/ClassifiedService","http"); 
            bindingTemplate.setAccessPoint(accessPoint); 
            TModelInstanceDetails tModelDetails = new TModelInstanceDetails(); 
            TModelInstanceInfo tModelInstanceInfo = new TModelInstanceInfo( 
                                          "332F67D0-D8A1-11DA-A5BF-DF15F533BFA1"); 
            InstanceDetails instanceDetails = new InstanceDetails(); 
            OverviewDoc overviewDoc = new OverviewDoc(); 
            OverviewURL overviewURL = new OverviewURL( 
                            "http://www.nicholaschase.com/ClassifiedService-impl.wsdl"); 
            overviewDoc.setOverviewURL(overviewURL); 
            instanceDetails.setOverviewDoc(overviewDoc); 
            tModelInstanceInfo.setInstanceDetails(instanceDetails); 
            tModelDetails.add(tModelInstanceInfo); 
            bindingTemplate.setTModelInstanceDetails(tModelDetails); 
            BindingTemplates bindingTemplates = new BindingTemplates(); 
            bindingTemplates.add(bindingTemplate); 
            businessService.setBindingTemplates(bindingTemplates); 
            KeyedReference wsdlNotation = new KeyedReference(TModel.TYPES_TMODEL_KEY, 
                       "wsdlSpec", "C1ACF26D-9672-4404-9D70-39B756E62AB4"); 
            KeyedReference typeNotation = new KeyedReference("ntis-gov:naics:1997", 
                     "511110", "C0B9FE13-179F-413D-8A5B-5004DB8E5BB2"); 
            CategoryBag catBag = new CategoryBag(); 
            catBag.add(wsdlNotation); 
            catBag.add(typeNotation); 
            businessService.setCategoryBag(catBag); 
            Vector services = new Vector(); 
            services.addElement(businessService); 
            ServiceDetail serviceDetail = proxy.save_service( token.getAuthInfoString(),
                                                                   services); 
            Vector businessServices = serviceDetail.getBusinessServiceVector(); 
            BusinessService businessServiceReturned = (BusinessService)
                                     (businessServices.elementAt(0)); 
            String serviceKey = businessServiceReturned.getServiceKey(); 
            System.out.println("The Name: "+ 
                                 businessServiceReturned.getDefaultNameString()); 
            System.out.println("The ServiceKey: "+ serviceKey);

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

Đến nay Gene đã thấy mô hình quen thuộc; tạo các đối tượng như chúng tồn tại trong tài liệu XML. Hãy tạo BusinessService và thêm businessKey. Tạo BindingTemplate, bảo đảm tham chiếu tModelKey được tạo khi Gene đã tạo giao diện tModel và URL cho tệp WSDL thực tế. Tạo categoryBag thêm nó vào và lưu dịch vụ. Lấy ra dịch vụ và tên và khóa của nó. Việc chạy ứng dụng đã cho Gene kết quả đầu ra được hiển thị trong Liệt kê 33.

Liệt kê 33. Lấy ra khóa tên dịch vụ
Security authToken:authToken:E4203390-D8A5-11DA-A5BF-8F6C6FEDFEBD
The Name: ClassifiedService
The ServiceKey: E43F2D40-D8A5-11DA-A5BF-880A3C83523B

Tìm một doanh nghiệp

Tiếp theo Gene xem xét hướng đưa các tìm kiếm đó vào hoạt động. Gene bắt đầu một tìm kiếm doanh nghiệp, cố gắng đảm bảo rằng tờ báo này đã được nhập vào đăng ký và người ta chưa sao chép nó. Xem Liệt kê 34.

Liệt kê 34. Tìm một doanh nghiệp
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;
import java.util.Vector;

import org.uddi4j.datatype.Name; 
   import org.uddi4j.response.BusinessInfo; 
   import org.uddi4j.response.BusinessList; 
   import org.uddi4j.util.FindQualifier; 
   import org.uddi4j.util.FindQualifiers;

public class FindBusiness{

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String transportClass = 
             "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                    token.getAuthInfoString());

         String businessToFind = "The Daily Moon"; 
            Vector names = new Vector(); 
            names.add(new Name(businessToFind)); 
            FindQualifiers findQualifiers = new FindQualifiers(); 
            Vector qualifier = new Vector(); 
            qualifier.add(new FindQualifier("exactNameMatch")); 
            findQualifiers.setFindQualifierVector(qualifier); 
            BusinessList businessList = proxy.find_business(names, null, null, 
                                               null,null,findQualifiers,5); 
            Vector businessInfoVector = 
                         businessList.getBusinessInfos().getBusinessInfoVector(); 
            for( int i = 0; i < businessInfoVector.size(); i++ ){ 
              BusinessInfo businessInfo = (BusinessInfo)businessInfoVector.elementAt(i); 
              System.out.println(businessInfo.getDefaultNameString() + ": " 
                                 + businessInfo.getBusinessKey());
         }

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

Gene sẽ tìm kiếm một giá trị tên cụ thể, vì đó là kiểu tìm kiếm mà Gene xây dựng. Gene tạo một Vector của các đối tượng tên chỉ có một mục và tạo một FindQualifier để xác định rằng Gene chỉ tìm kiếm một sự so khớp chính xác. Cuối cùng, Gene cung cấp yêu cầu cho phương thức find_business(), để nhận các tên làm các tham số, bất kỳ discoveryURLs nào, một IdentifierBag, CategoryBag, TModelBag, FindQualifiers bất kỳ và số lượng tối đa của các kết quả để trả về.

Kết quả là một BusinessList, thông qua đó Gene lặp đi lặp lại để xem tất cả các giá trị của nó trong trường hợp thông tin được sao chép. Đối với mỗi giá trị, Gene in tên và businessKey như bạn thấy trong Liệt kê 35.

Liệt kê 35. Tên doanh nghiệp và businessKey
Security authToken:authToken:DBEAE280-D8A8-11DA-A5BF-A6D55D3D237D
The Daily Moon: 1D359E20-D899-11DA-A5BF-F9EAF6D4E3F7
The Daily Moon: 1A3DB880-D5F4-11DA-B880-F94D3591C691

Trong trường hợp này, Gene có thể thấy rằng thông tin được sao chép, vì vậy Gene có thể cung cấp businessKey bổ sung cho phương thức delete_business() của đối tượng UDDIProxy .

Tìm một dịch vụ

Tiếp theo, Gene muốn đảm bảo có thể tìm thấy ClassifiedService theo thể loại của nó. Xem Liệt kê 36.

Liệt kê 36. Tìm một kiểu dịch vụ
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;
import java.util.Vector;

import org.uddi4j.util.CategoryBag; 
   import org.uddi4j.util.KeyedReference; 
   import org.uddi4j.datatype.tmodel.TModel; 
   import org.uddi4j.datatype.binding.BindingTemplate; 
   import org.uddi4j.datatype.binding.TModelInstanceInfo; 
   import org.uddi4j.datatype.binding.TModelInstanceDetails; 
   import org.uddi4j.datatype.binding.AccessPoint; 
   import org.uddi4j.datatype.binding.InstanceDetails; 
   import org.uddi4j.datatype.service.BusinessService; 
   import org.uddi4j.response.ServiceDetail; 
   import org.uddi4j.response.ServiceInfo; 
   import org.uddi4j.response.ServiceList;

public class FindTypeOfService{

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String transportClass = 
                "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                 token.getAuthInfoString());
         KeyedReference wsdlNotation = new KeyedReference(TModel.TYPES_TMODEL_KEY, 
            "wsdlSpec", "C1ACF26D-9672-4404-9D70-39B756E62AB4"); 
          KeyedReference typeNotation = new KeyedReference("ntis-gov:naics:1997", 
             "511110", "C0B9FE13-179F-413D-8A5B-5004DB8E5BB2"); 
          CategoryBag catBag = new CategoryBag(); 
          catBag.add(wsdlNotation); 
          catBag.add(typeNotation); 
          ServiceList serviceList = proxy.find_service(null, null, catBag,null,null,5); 
          Vector serviceInfoVector = 
                                 serviceList.getServiceInfos().getServiceInfoVector(); 
          for( int i = 0; i < serviceInfoVector.size(); i++ ){ 
             ServiceInfo serviceInfo = (ServiceInfo)serviceInfoVector.elementAt(i); 
             System.out.println("Service name: " + serviceInfo.getDefaultNameString()); 
             System.out.println("Service key: " + serviceInfo.getServiceKey()); 
             ServiceDetail serviceDetail = proxy.get_serviceDetail
                                                (serviceInfo.getServiceKey()); 
             BusinessService thisService = (BusinessService)serviceDetail 
                                            .getBusinessServiceVector().elementAt(0); 
             if (thisService.getBindingTemplates().size() > 0){ 
                BindingTemplate thisBinding = (BindingTemplate)thisService 
                                                     .getBindingTemplates().get(0); 
                TModelInstanceDetails tModelDetails = 
                                      thisBinding.getTModelInstanceDetails(); 
                TModelInstanceInfo tModelInfo = tModelDetails.get(0); 
                InstanceDetails instanceDetails = tModelInfo.getInstanceDetails(); 
                String wsdlDocument = instanceDetails.getOverviewDoc() 
                                            .getOverviewURLString(); 
                System.out.println("Document located at " + wsdlDocument); 
             } 
          }

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

Bước đầu tiên của Gene là tạo một CategoryBag cho phép Gene tìm kiếm tất cả WSDL đã xác định các dịch vụ phải làm với các tờ báo. Kết quả của việc tìm kiếm đó là một ServiceList, thông qua đó Gene lặp đi lặp lại để có thêm thông tin. Một đối tượng ServiceInfo biểu thị từng dịch vụ trong kết quả và Gene kết nối qua mỗi một trong số các dịch vụ, hiển thị tên và serviceKey của các dịch vụ serviceKey.

Tuy nhiên, nếu Gene muốn biết thêm chi tiết, chẳng hạn như URL cho các tệp WSDL, Gene phải sử dụng serviceKey để yêu cầu ServiceDetail cho dịch vụ đó. ServiceDetail không có hay có nhiều BindingTemplates được liên kết với nó và nếu Gene tìm thấy một BindingTemplate, Gene thực hiện cách của mình xuống dưới thông qua đối tượng TModelInstanceDetails tới đối tượng InstanceDetails, trong đó bao gồm OverviewDoc và vì thế gồm cả OverviewURL. Kết quả hiển thị không chỉ tên và serviceKey của dịch vụ kết quả, mà còn là URL mà người dùng có thể tìm thêm thông tin ở đó. Xem Liệt kê 37.

Liệt kê 37. Các kết quả cuối cùng
Security authToken:authToken:59FE37C0-D8AF-11DA-A5BF-A79333DB92F9
Service name: ClassifiedService
Service key: E43F2D40-D8A5-11DA-A5BF-880A3C83523B
Document located at 
         http://www.nicholaschase.com/ClassifiedService-impl.wsdl

Tóm tắt

Một môi trường phân tán đòi hỏi một kho lưu trữ tập trung để những người dùng và các nhà phát triển biết cái gì có sẵn và nơi tìm nó và các dịch vụ Web không là ngoại lệ. Hướng dẫn này đã giải thích việc sử dụng UDDI, cung cấp một đăng ký thông tin về các doanh nghiệp và dịch vụ có sẵn.

Trong hướng dẫn này, bạn đã học:

  • UDDI là gì và tại sao nó lại quan trọng.
  • Làm thế nào để cấu trúc dữ liệu UDDI.
  • Làm thế nào để phân biệt giữa các giao diện và các việc hiện thực SOAP.
  • Làm thế nào để tìm dữ liệu trong một đăng ký UDDI.
  • Làm thế nào để tương tác với một đăng ký UDDI bằng cách sử dụng Java.

Các phần tiếp theo của loạt bài này sẽ bàn về các nhu cầu an ninh ngày càng tăng, xem xét Các ứng dụng Web-an ninh (WS-Security) và Các ứng dụng Web-Chính sách (WS-Policy).


Tải về

Mô tảTênKích thước
Source codeuddicode.zip6KB

Tài nguyên

Học tập

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

  • Tải Apache Geronimo.
  • Để tạo đăng ký UDDI riêng của bạn, tải Apache jUDDI.
  • Tải UDDI4J.
  • Tải Apache Axis 1.3.
  • Tải Java 1.4.2. Geronimo sẽ không chạy đúng với Java 1.5.
  • UDDI4Py là gói Python cho phép gửi các yêu cầu đến và xử lý các đáp ứng từ các API phiên bản 2 của UDDI.

Thảo luận

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=549829
ArticleTitle=Hiểu biết về Đặc tả các dịch vụ Web, Phần 3: Giao diện khám phá và mô tả thống nhất (UDDI)
publish-date=10102010