Sun ONE logo     上一個      目錄      索引      下一個     
Sun ONE Application Server 7, Update 1 管理員指南



使用異動服務

異動是企業不可或缺的一個組成部分。典型的企業異動包含雙方或多方之間的資產轉移。通常將這類轉移的精確記錄儲存於一個或多個資料庫中。由於這些資訊對於企業的運作至關重要,因此必須保持其有效性、現時性與可靠性。異動處理對於程式設計的初學者而言,可能有些困難。J2EE 平台提供了數個抽象的概念來簡化可靠異動處理應用程式的開發程序。在本章中,我們將討論 Sun ONE Application Server 中的 J2EE 異動與異動支援。

本 module 對 Java 異動做了一般的討論,而專門討論了併入至 Sun ONE Application Server 的異動支援。

本 module 包括下列主題:

何為異動?

若要模仿企業的異動,一個程式可能需要執行數個步驟。例如,一個財務程式需要透過執行以下以虛擬碼列示的步驟,才能將資金從活期存款帳戶轉入儲蓄存款帳戶:

begin transaction

debit checking account

credit savings account

update history log

commit transaction

在上述的虛擬碼中,begincommit 敘述用於標記異動的界限。若要完成此異動,所有的三個步驟都必須成功地完成。如果未能成功地完成所有三個步驟,資料的完整性可能會受損。

這種保證被稱為 atomicity。異動可以用兩種方式結束:透過 commit 結束或透過 rollback 結束。異動確定之後,敘述在異動界限內所做的修改會被永久地儲存起來。這些變更具有持久性,也就是說,即使今後發生系統故障,它們也會保持不變。如果異動中的任何敘述失敗,該異動會回轉,並復原到目前為止異動內由已執行敘述產生的所有影響。例如,在虛擬碼中,如果磁碟機在執行 credit 步驟期間當機,異動會回轉並復原由 debit 敘述所做的資料修改。

即使異動失敗,資料仍會保持完好無缺,因為異動帳戶仍處於平衡狀態。該異動行為被稱為異動的一致性

異動服務還提供隔離,表示在異動確定或回轉之前,其他的應用程式或執行緒不能觀察該異動的各個階段。一旦異動確定之後,其便能夠安全地被應用程式與執行緒觀察。

J2EE 中的異動

J2EE 中的異動處理包括以下五個參與者:異動管理員、應用程式伺服器、資源管理員、資源配接卡以及使用者應用程式。透過執行不同的 API 與功能,它們當中的每個項目都有助於異動處理順利地進行,如下所述:

  • 異動管理員提供支援異動分隔、異動資源管理、同步化以及異動環境傳遞所需的服務與管理功能。
  • 應用程式伺服器提供支援應用程式執行環境 (包含異動狀態管理) 所需的基礎架構。
  • 資源管理員 (透過資源配接卡) 提供應用程式對資源的存取權。資源管理員參與分散式異動,其方法為:執行由異動管理員使用的異動資源介面來傳遞異動關聯、異動完成以及恢復工作。關聯式資料庫伺服器便是這樣一個資源管理員。
  • 資源配接卡是一個系統層級的軟體程式庫,應用程式伺服器或用戶端可使用該程式庫連接到資源管理員。資源配接卡通常專用於資料管理員。它可以作為程式庫,在使用它的用戶端位址空間中使用。JDBC 驅動程式便是這樣一個資源配接卡。
  • 異動使用者應用程式專門在 J2EE 應用程式伺服器環境中進行作業,使用 JNDI 查找異動資料來源,並選擇性地查找異動管理員。可以使用 EJB 的宣告性異動屬性設定值,或使用明確的程式化異動分隔。

術語資源管理員經常與資源配接卡相互替換使用,因為兩個實體之間有著緊密的聯繫。

異動資源管理員

J2EE 異動中支援以下異動資源管理員。

資料庫

資料庫是 J2EED 應用程式中最常遇到的異動資源管理員。JDBC 是 J2EE 組件用來存取資料庫的 API。資料庫資源被配置為 JDBC 資源。JDBC 資源由資源管理員或 JDBC 驅動程式進行管理。JDBC 驅動程式可以為本機異動或全域異動提供支援,在某些情況下,可同時支援本機異動與全域異動。

Sun ONE Application Server 支援經由各種 J2EE 組件使用 JDBC 與異動。如需有關如何註冊與配置 JDBC 資源的更多詳細資訊,請參閱「關於 JDBC 資源」。應用程式伺服器負責提供異動的連續性 (即,初始化異動,並經由多個應用程式組件存取資料庫)。例如,Servlet 可以啟動異動、存取資料庫、呼叫企業 Bean (作為同一異動的一部分存取同一資料庫),最後確定異動。

JMS 供應程式

JMS 代表 Java Message Service。JMS 供應程式是用於訊息代理程式服務的 J2EE 術語。JMS API 在應用程式之間提供可靠的異動訊息交換。對異動 JMS 資料來源的支援是 J2EE 中的一項必備功能。JMS 資源和 JDBC 資源可以參與同一項異動。

Sun ONE Application Server 與 Sun ONE Message Queue 整合使用,後者是一個功能齊全的 JMS 供應程式,並且是相應的異動資源管理員。透過這種方式,Sun ONE Application Server 可以經由 Servlet、JSP 頁面以及企業 Bean 啟用異動 JMS 存取。也可以將協力廠商 JMS 供應程式與 Sun ONE Application Server 結合使用。如需更多詳細資訊,請參閱「使用 JMS 服務」

J2EE 連接器

Sun ONE Application Server 支援將 XATransaction 模式作為異動資源管理員使用的資源配接卡。平台必須經由 Servlet、JSP 頁面、以及企業 Bean 啟用對資源配接卡的異動存取。也可以經由單一異動內的多個應用程式組件存取資源配接卡。例如,Servlet 可能要啟動異動、存取資源配接卡、呼叫企業 Bean (也作為同一異動的一部分存取資源配接卡),最後確定異動。

本機異動與分散式異動

僅包含一種資源的異動可以使用本機異動完成。本機異動也需要所有參與的應用程式組件在一個程序中執行。包含多種資源,或多個參與程序的異動會變為分散式異動或全域異動。本機異動最佳化使用特定的資源管理員最佳化,可以使 J2EE 應用程式對其進行觀察。

異動類型在很大程度上由相關資源管理員執行的介面所決定。例如,執行 javax.sql.DataSource 介面的 JDBC 資料來源可以參與本機異動。執行 javax.sql.XADataSource 介面的資料來源能夠參與全域異動。某些 JDBC 資源執行兩種介面,當這樣的 JDBC 資源透過 Sun ONE Application Server 註冊時,可能需要在 Sun ONE Application Server 配置中提供附加配置資訊,以指出該資源優先使用的功能。

與全域異動相比,本機異動更為簡單,並且自然更為有效。當需要轉變的資料在多個資料來源中展開的時候,本機異動便無法勝任該項作業。有時,不可能預知異動內需要利用的資料來源數目。因此,我們在工作中經常會遇到全域異動。全域異動可以執行某些效能增強的最佳化作業。

J2EE 支援異動應用程式結合使用 Servlet 或 JSP,在一項異動中存取多個企業 Bean。每個組件可以使用一個或多個連接來存取一個或多個異動資源管理員。在下圖中,呼叫樹經由存取多個企業 Bean 的 Servlet 或 JSP page 啟動,這樣反過來可能會存取其他企業 Bean。組件通過連接存取資源管理員。

異動中的 J2EE 組件存取資源
該圖描述了顯示異動中所有組件的呼叫樹。

例如,應用程式可能要求上圖中的所有組件作為單一異動的一部分存取資源。應用程式伺服器供應程式必須提供異動功能來支援這樣的方案。

J2EE 異動管理支援平面異動。平面異動不能包含任何子異動 (嵌套式)。

異動恢復是分散式異動的一個重要方面。如果資源在關鍵時刻不可存取,或者發生其他不可恢復的錯誤,則分散式異動的狀況可能有問題。自動與手動恢復孤立/不完全的異動是 Sun ONE Application Server 中的一項重要功能。您可以使用管理介面啟用自動異動恢復功能。如需有關如何控制異動恢復的更多資訊,請參閱「異動服務管理」

連接 (在此處作為資源的同義詞) 可被標示為可共用或不可共用。要以不可共用的方式使用連接的 J2EE 應用程式必須提供大意如此的佈署資訊,以避免容器共用該連接。在已變更的安全屬性、隔離層、字元設定值,以及本土化配置的情形下需要該資訊。

容器不應該嘗試共用標示為不可共用的連接。如果未將連接標示為不可共用,則必須讓應用程式知曉實際上是否共用這些連接。

J2EE 應用程式組件可以使用選擇性的佈署描述元元素 res-sharing-scope,指示是否可以共用與資源管理員的連接。如果尚未提供佈署提示,容器應該假定連接是可共用的。J2EE 應用程式組件可以快取連接物件,並且可以在多個異動中重複使用這些連接物件。提供連接共用的容器應該透通地切換此類快取連接物件 (在派送時間),以在正確的異動範圍內指向適當的共用連接。

設計企業 Bean 應用程式時,開發人員必須確定指定界限的方式。

容器管理異動

在具有容器管理異動的企業 Bean 中,EJB 容器設定異動的界限。您可以使用任何企業 Bean 類型的容器管理異動:階段作業 Bean、實體 Bean 或訊息導引 Bean。容器管理異動簡化了開發程序,因為企業 Bean 程式碼不會明確地標示異動的界限。程式碼不包括開始與結束異動的敘述。

通常,容器會在企業 Bean 方法啟動前的瞬間開始一項異動。並在方法結束前的瞬間確定異動。每一種方法均可以與一項單一的異動關聯。在一種方法中不允許有嵌套式異動或多項異動。

容器管理異動不要求所有方法均與異動相關聯。佈署 Bean 時,您可以經由設定異動的屬性來指定與異動相關聯的 Bean 方法。

本章節涵蓋以下主題:

異動屬性

異動屬性控制異動的範圍。下圖展示了控制範圍重要的原因。在圖中,方法 A 開始一項異動,然後呼叫 Bean 2 的方法 B,當方法 B 執行時,其會在由方法 A 啟動的異動範圍內執行,還是在一個新的異動範圍內執行?答案取決於方法 B 的異動屬性。

  
圖中顯示了異動的範圍。
異動屬性

異動屬性可以含有以下其中一個值:

Required

如果用戶端正在異動中執行,並呼叫企業 Bean 方法,則方法會在用戶端的異動中執行。如果用戶端與異動無關聯,容器會在執行方法之前啟動新的異動。

Required 屬性適用於大多數異動。因此,您可能想要將該屬性作為預設值使用,至少在開發的早期階段這樣做。由於異動屬性具有宣告性,因此,以後您可以輕鬆地對其進行變更。

RequiresNew

如果用戶端正在異動中執行,並呼叫企業 Bean 方法,則容器會採取以下步驟:

  • 暫停用戶端的異動
  • 啟動新的異動
  • 將呼叫授權給方法
  • 方法完成之後,繼續用戶端的異動

如果用戶端與異動無關聯,容器會在執行方法之前啟動新的異動。

如果要保證方法總在新的異動中執行,請使用 RequiresNew 屬性。

Mandatory

如果用戶端正在異動中執行,並呼叫企業 Bean 方法,則方法會在用戶端的異動中執行。如果用戶端與異動無關聯,容器會拋出 TransactionRequiredException

如果企業 Bean 方法必須使用用戶端的異動,則使用 Mandatory 屬性。

NotSupported

如果用戶端正在異動中執行,並呼叫企業 Bean 方法,則容器在呼叫方法之前會暫停用戶端的異動。方法完成之後,容器會繼續用戶端的異動。

如果用戶端與異動無關聯,容器在執行方法之前不會啟動新的異動。

對於不需要異動的方法,請使用 NotSupported 屬性。由於異動包含耗用時間,因此該屬性可能會提昇效能。

Supports

如果用戶端正在異動中執行,並呼叫企業 Bean 方法,則方法會在用戶端的異動中執行。如果用戶端與異動無關聯,容器在執行方法之前不會啟動新的異動。

由於方法的異動行為可能變化,因此您應該慎用 Supports 屬性。

Never

如果用戶端正在異動中執行,並呼叫企業 Bean 方法,則容器會拋出 RemoteException。如果用戶端與異動無關聯,容器在執行方法之前不會啟動新的異動。

屬性摘要

下表概括了異動屬性的作用。T1 與 T2 異動均由容器控制。T1 異動與在企業 Bean 中呼叫方法的用戶端相關聯。在多數情況下,用戶端是另一個企業 Bean。T2 異動由容器在方法執行前的瞬間啟動。

在最後一欄中,術語「無」表示企業方法不在由容器控制的異動中執行。但是,這種企業方法中的資料庫呼叫可能由 DBMS 的異動管理員控制。

   異動屬性

異動屬性

 

用戶端的異動

 

企業方法的異動

 

Required

 

T2

 

T1

 

T1

 

RequiresNew

 

T2

 

T1

 

T2

 

Mandatory

 

錯誤

 

T1

 

T1

 

NotSupported

 

 

T1

 

 

Supports

 

T1

 

T1

 

設定異動屬性

由於異動屬性儲存在佈署描述元中,因此可以在 J2EE 應用程式開發的以下幾個階段中進行變更:企業 Bean 的建立階段、應用程式的組譯階段以及佈署階段。但是,開發人員還應該在建立 Bean 時負責指定屬性。只有將各組件組譯到大型應用程式的應用程式開發人員才能修改屬性。佈署 J2EE 應用程式的人員不負責指定異動屬性。

您可以為整個企業 Bean 或個別方法指定異動屬性。如果您為方法指定了一個屬性,而為 Bean 指定了另一個屬性,則方法屬性優先。為個別方法指定屬性時,Bean 的類型與需求不一致。階段作業 Bean 需要為企業方法定義的屬性,但是禁用 create 方法的屬性。實體 Bean 需要企業方法、create 方法、remove 方法以及 finder 方法的異動屬性。訊息導引 Bean 需要 onMessage 方法的異動屬性 (RequiredNotSupported)。

回轉容器管理異動

有兩種方法可以回轉容器管理異動。第一種,如果拋出一個系統異常,容器將會自動回轉異動。第二種,透過呼叫 EJBContext 介面中的 setRollbackOnly 方法,Bean 方法指導容器回轉異動。如果 Bean 拋出一個應用程式異常,則回轉不能自動進行,但可以呼叫 setRollbackOnly 來引發回轉。

在以下範例中,BankEJB 範例的 transferToSaving 方法展示了 setRollbackOnly 方法。如果發生活期存款帳戶結欠,transferToSaving 會呼叫 setRollBackOnly 並拋出一個應用程式異常 (InsufficientBalanceException)。updateCheckingupdateSaving 方法會更新資料庫表格。如果更新失敗,這些方法會拋出一個 SQLException,而 transferToSaving 方法會拋出一個 EJBException。由於 EJBException 是系統異常,因此,其會導致容器自動回轉異動。以下為 transferToSaving 方法的程式碼:

public void transferToSaving(double amount) throws
   InsufficientBalanceException {

   checkingBalance -= amount;
   savingBalance += amount;

if (checkingBalance < 0.00) {
context.setRollbackOnly();

throw new InsufficientBalanceException();
}
   try {
      updateChecking(checkingBalance);

   updateSaving(savingBalance);
   } catch (SQLException ex) {
      throw new EJBException
         ("Transaction failed due to SQLException: "
         + ex.getMessage());
}
}

當容器回轉異動的時候,總會復原 SQL 呼叫在異動內對資料所做的變更。但是,只有在實體 Bean 中,容器才會復原對實例變數所做的變更。(透過自動呼叫實體 Bean ejbLoad 方法 [可經由資料庫載入實例變數],可以執行該項作業。)發生回轉的時候,階段作業 Bean 必須明確地重設在異動內變更的所有實例變數。若要重設階段作業 Bean 的實例變數,最簡單的方法是執行 SessionSynchronization 介面。

您也可以透過指令行介面傳送異動 ID,來回轉異動。如需更多詳細資訊,請參閱「使用指令行介面管理異動」

同步化階段作業 Bean 的實例變數

SessionSynchronization 介面 (選擇性) 可讓您同步化實例變數及其在資料庫中相應的值。容器在異動的每個主要階段都會呼叫 SessionSynchronization 方法 — afterBeginbeforeCompletion 以及 afterCompletion

afterBegin 方法會在新的異動開始後通知實例。容器首先呼叫 afterBegin,然後才呼叫異動中的第一個企業方法。afterBegin 方法是經由資料庫載入實例變數的絕佳位置。例如,BankBean 類別使用 afterBegin 方法載入 checkingBalancesavingBalance 變數:

public void afterBegin() {

   System.out.println("afterBegin()");
   try {
      checkingBalance = selectChecking();
      savingBalance = selectSaving();
   } catch (SQLException ex) {
      throw new EJBException("afterBegin Exception: " +
         ex.getMessage());
   }
}

在企業方法完成之後、而異動確定之前的瞬間,容器呼叫 beforeCompletion 方法。beforeCompletion 方法是階段作業 Bean 回轉異動的最後機會 (透過呼叫 setRollbackOnly)。如果還沒有透過實例變數的值更新資料庫,則階段作業 Bean 會使用 beforeCompletion 方法執行這項作業。

afterCompletion 方法表示異動已經完成。它只有一個單一的布林參數,如果異動被確定,其值為 true,如果異動被回轉,則其值為 false。如果發生回轉,階段作業 Bean 便可以使用 afterCompletion 方法,重新顯示其資料庫中的實例變數:

public void afterCompletion(boolean committed) {

   System.out.println("afterCompletion: " + committed);
   if (committed == false) {
      try {
         checkingBalance = selectChecking();
         savingBalance = selectSaving();
} catch (SQLException ex) {
         throw new EJBException("afterCompletion SQLException:
         " + ex.getMessage());
}
}
}

容器管理異動中禁用的方法

您不應該呼叫任何可能干擾異動界限 (由容器設定) 的方法。禁用的方法列示如下:

  • java.sql.Connection 的 commit、setAutoCommit 以及 rollback 方法
  • javax.ejb.EJBContextgetUserTransaction 方法
  • javax.transaction.UserTransaction 的任何方法

但是,您可以使用這些方法在 Bean 管理式的異動中設定界限。

Bean 管理式的異動

在 Bean 管理式的異動中,階段作業或訊息導引 Bean 中的程式碼明確地標示了異動的界限。實體 Bean 不能具有 Bean 管理式的異動,其必須使用容器管理異動作為替代。儘管具有容器管理異動的 Bean 需要較少的編碼,但是它們有一個限制條件:方法在執行時可以與單一的異動關聯,也可以根本不與任何異動關聯。如果該限制條件令您在編碼 Bean 時感到困難,應該考慮使用 Bean 管理式的異動。

以下虛擬碼展示了您可以透過 Bean 管理式的異動取得的細紋控制。透過檢查各種情況,虛擬碼決定是否啟動或停止企業方法內的異動。

begin transaction
...
update table-a
...
if (condition-x)
   commit transaction
else if (condition-y)
   update table-b
   commit transaction
else
   rollback transaction
   begin transaction
   update table-c
   commit transaction

異動服務管理

您可以使用管理介面或指令行介面管理異動。

本章節涵蓋以下主題:

使用管理介面管理異動

使用管理介面,您可以啟用對異動的監視、設定其日誌層級以及指定其進階選項。

您可以控制實例的異動服務屬性,例如恢復策略和逾時。您在此處指定的特性與配置儲存在 server.xml 檔案中。

若要配置異動服務選項,請執行以下工作:

  1. 在管理介面的左窗格中,開啟您要修改其異動配置的 Sun ONE Application Server 實例樹。
  2. 從顯示的 J2EE 服務清單中選取 [Transaction Service]。在管理介面右窗格的視圖「配置異動服務選項」中,您將看到以下視窗:

   配置異動服務選項
該圖顯示了 Java 異動服務的可配置進階服務選項。

  1. 若要啟用對異動的監視,請標示 [Monitoring Enabled] 核取方塊。下表列示了 Java 異動服務中可被監視的功能:
  2.    Java 異動服務的可監視屬性

    特性

     

    類型

     

    描述

     

    transactionsCompleted

     

    int

     

    啟用監視後所完成的異動數目

     

    transactionsRolledBack

     

    int

     

    啟用監視後已回轉的異動數目

     

    transactionsRecovered

     

    int

     

    啟用監視後已恢復的異動數目

     

    transactionsInFlight

     

    int

     

    正在處理的異動數目

     

    timeStamp

     

    long

     

    以毫秒表示,記錄產生統計資料的時間。這將是由 System.getCurrentTimeInMillis() 報告的任何內容

     

  3. 從 [Log Level] 下拉式清單中,選取您要為異動設定的日誌層級。如需有關日誌層級及其併入方式的更多資訊,請參閱「使用記錄功能」
  4. 標示 [Recover on Restart] 核取方塊,以在伺服器重新啟動時自動恢復失敗的異動。當資源在異動確定協定的關鍵時刻不可存取時,異動也許不會完成,並繼續駐留在異動日誌檔中。如果已經標示了該核取方塊,伺服器會在重新啟動時嘗試恢復孤立的異動。如果有關資源仍然不可存取,也許會延遲伺服器的重新啟動。依預設,不標示該核取方塊。
  5. 對於具有容器管理異動的企業 Bean,您可以透過設定異動逾時 (秒) 特性的值來控制異動逾時間隔時間。
  6. 如果將該特性的值設定為 0,則異動便不會逾時。

    在 [Transaction Timeout] (以秒表示) 欄位中,指定異動逾時間隔時間。如果異動沒有在指定的時間內完成,其便會被回轉。如果該屬性的值設定為 0,則異動便不會逾時。

  7. 在 [Transaction Log Location] 欄位中,指定要儲存日誌檔的絕對目錄路徑。您需要重新啟動伺服器,以使新的異動日誌目錄生效。
  8. 從 [Heuristic Decision] 下拉式方塊中,選取您要套用至異動的啟發式決策。從指示的選項中選取 [Commit] 或 [Rollback],以便在不能明確地確定異動結果時,指定應用程式伺服器在恢復期間應該如何確定一個不確定異動的結果。如果將 [Heuristic Decision] 設定為 [Rollback],其便會將異動回轉。在某些情況下,也可以確定這樣的異動。
  9. 在 [Keypoint Interval (transactions)] 欄位中,指定日誌中要點事件作業之間異動的數目。透過移除已完成異動的項目,並壓縮檔案,要點事件作業可以縮小異動日誌檔的大小。如果該屬性值較大,則異動日誌檔也會較大,但是減少要點事件作業意味著更高的潛在效能。如果屬性值較小 (例如,100),則日誌檔也會較小,但是由於要點事件作業的頻率較大,會稍微降低效能。

使用指令行介面管理異動

您可以使用指令行介面 (CLI) 管理並監視資料庫異動,將在以下章節中加以解釋:

這些章節解釋了如何使用指令行介面管理並監視異動。

列示執行中的異動

以下指令應該用於取得執行中的異動資料 (假定您處於多模式下,並且已設定使用者名稱與密碼):

- asadmin> get --monitor <instanceName>.transaction-service.inflight-tx

多行輸出的形式為:

Transaction Id State Elapsed Time (ms)

txnid1 Prepared 20

txnid2 Active 100

txnid3 Active 120

... ... ...

管理異動

列示執行中的異動中給定的範例內,讓我們假定您要透過以下異動 Id 來回轉異動:txn-idstxnid2 以及 txnid3。回轉所選異動的指令範例如下:

asadmin> set --monitor <instanceName>.transaction-service.rollback-list=txnid2,txnid3

凍結異動服務

若要凍結異動服務,請執行以下指令:

asadmin> set --monitor <instanceName>.transaction-service.freeze=true

凍結異動服務期間,應用程式伺服器中的異動管理員會暫停執行中的所有異動。在生產佈署系統中,不建議使用凍結指令。

若要取消凍結異動服務,請執行以下指令:

asadmin> set --monitor <instanceName>.transaction-service.freeze=false

當異動服務重新設定為進行動作時,系統將在停止處開始繼續作業。如果活性系統保持的凍結狀態時間太長,某些資料庫連接可能逾時,導致異動被回轉。

監視異動

若要取得異動的監視資料 (包括執行中異動的資料),請執行以下指令:

asadmin> get --monitor <instanceName>.transaction-service.*

當您執行該指令時,如果沒有作用中的異動,將會得到以下輸出結果:

total-tx-completed = 5

total-tx-rolledback = 2

total-tx-inflight = 0

isFrozen = false

tx-inflight = No active transactions found.

當您執行該指令時,如果存在作用中的異動,將會得到以下輸出結果:

total-tx-completed = 5

total-tx-rolledback = 2

total-tx-inflight = 2

isFrozen = false

tx-inflight =

Transaction Id State Elapsed Time (ms)

txnid1 Prepared 500

txnid2 Active 360


上一個      目錄      索引      下一個     
Copyright 2003 Sun Microsystems, Inc. All rights reserved.