用于Java的SCA客戶機和實現模型
SCA Java 實現模型提供了用于在 Java 中實現 SCA 組件的框架。組件實現可以提供服務,也可以充當其他服務的客戶機。本文將說明 SCA Java 組件實現和非 SCA Java 組件實現可以如何獲得對服務的訪問和調用服務方法。在本文中,所有元數據都使用 Java 2 Standard Edition (J2SE) 5 提供的 Annotation 功能定義。不過,SCA 服務客戶機和組件實現也可使用 J2SE 1.4。基本組件實現模型
此模型描述本地或
實現服務
服務使用接口表示,而接口則是使用以下方法之一進行定義的:
- Java 接口(SCA 的首選方式)
- Java 類
- 從 Web 服務描述
語言 (Web Services Description Language,WSDL)端口類型生成的 Java 接口
Java 類組件實現會實現服務接口定義的所有操作,它使用 @Service Annotation 來指定服務通過使用 Java 實現而實現的服務接口。旨在用作服務實現的類并不必具有 @Service Annotation。@Service Annotation 具有兩個特性:
- Interfaces——此值是應該由其組件作為服務公開的接口或類對象的值。
- Value——僅在提供單個服務接口時的快捷方式。沒有特性的 @Service 沒有意義。
以下代碼片段顯示了名為 PayrollDataService 的 Java 服務接口和名為 PayrollDataServiceImpl 的 Java 接口的 Java 實現類。
清單 1. Java 服務接口
package services.payrolldata;
public interface PayrollDataService {
float getBasic(String employeeID);
float getvariablePay(String employeeID);
float getHRA(String employeeID);
float getProfessionalTax(String employeeID);
float getNetPay(String employeeID);
}
清單 2. Java 服務組件實現
package services.payrolldata;
Import org.osoa.sca.annotations.*;
@Service(PayrollDataService.class)
public class PayrollDataServiceImp implements PayrollDataService {
public float getBasic(String employeeID){ . . . }
public float getVariablePay(String employeeID){ . . . }
public float getHRA(String employeeID){ . . . }
float getProfessionalTax(String employeeID){ . . . }
public float getNetPay(String employeeID){ . . . }
}
如果在 Java 實現類中,服務接口由類本身定義,則上述代碼中的 @Service Annotation 將替換為 @Service(PayrollDataServiceImp.class)。下面將說明此組件實現的組件類型,如清單 3 中所示。
清單 3. 組件類型
<!--<?xml version="1.0" encoding="ASCII"?>
<componentType xmlns=http://www.osoa.org/xmlns/sca/0.9>
<service name="PayrollDataService">
<interface.java interface="services.payrolldata. PayrollDataService"/>
</service>
</componentType> -->
使用了接口的子類來提供具有相同接口的兩個服務。@Service Annotation 同時列出了這兩個接口。
實現遠程服務
通過入口點發布遠程服務,以提供訪問外部組件的方法。為了定義遠程服務,將在服務的 Java 接口中添加 @Remotable Annotation。接口不由 Java 類定義的服務不是遠程服務。從 WSDL 端口類型生成的 Java 接口是遠程接口。
以下將對帶 @Remotable Annotation 的遠程服務的 Java 接口進行說明:
清單 4. 帶 @Remotable Annotation 的遠程服務的 Java 接口
package services.payroll;
import org.osoa.sca.annotations.Remotable;
@Remotable
public interface PayrollService{
public PayrollStatement getPayrollStatement(String employeeID);
}
下一個代碼片段顯示了 PayrollStatement Java 接口。
清單 5. PayrollStatement Java 接口
package services.payroll;
import java.util.List;
public interface PayrollStatement {
List getPayrollDetails();
float getNetPay();
}
遠程服務使用封送
遠程服務的實現上的 @AllowPassByReference Annotation 用于聲明它是否允許在對其進行調用時通過引用數據交換語義進行傳遞。
以下代碼片段顯示了實現遠程服務并允許通過引用傳遞的 Java 組件實現。
清單 6. 具有遠程服務和允許通過引用傳遞的 Java 組件實現
package services.payrolldata;
Import org.osoa.sca.annotations.*;
@Service(PayrollDataService.class)
@AllowsPassByReference
public class PayrollDataServiceImp implements PayrollDataService {
. . . .
}
實現本地服務
本地服務僅能由屬于相同模塊的客戶機調用。
以下代碼片段顯示了本地服務的 Java 接口。
清單 7. 本地服務的 Java 接口
package services.payrolldata;
public interface PayrollDataService {
float getBasic(String employeeID);
float getvariablePay(String employeeID);
float getHRA(String employeeID);
float getProfessionalTax(String employeeID);
float getNetPay(String employeeID);
}
本地服務的調用的數據交換語義是以引用為基礎的,其中,客戶機或服務提供者會看到對參數的更改。
實現有狀態
確定了范圍的服務通過在服務的接口定義或服務類上使用 @Scope Annotation 加以表示。@Scope Annotation 具有一個參數,即 value,其值為范圍的名稱。
以下是當前支持的范圍值:
- Stateless(缺省)——每個請求分開處理。Java 實例可以從服務實例池獲得。
- request——對于在處理
遠程 服務請求時出現的所有本地服務調用,服務請求都被委托給相同的 Java 接口。 - Session——對于相同“會話”中的所有請求,服務請求都被委托給相同的 Java 實例。
- module——對于相同“模塊”中的所有請求,服務請求都被委托給相同的 Java 實例。
除了模塊范圍內的實現外,對于其他三個,SCA 運行時都將防止對該實現的實例并發執行方法。
以下代碼片段顯示了會話范圍內的服務的接口。
清單 8. 會話范圍服務的接口
package services.profile;
import org.osoa.sca.annotations.Scope;
@Scope("session")
public interface ProfileService{
public String getFirstName();
public void setFirstName(String pName);
public String getLastName();
public void setLastName(String pName);
public boolean isLoggedIn();
public void setLoggedIn(boolean pStatus);
public String getId();
public void setId(String pId);
}
范圍服務可以使用 @Init Annotation 和 @Destroy Annotation 在其 Java 實現上實現生命周期方法。@Init——方法僅在其范圍開始處且已注入了其屬性和引用后調用一次。@Destroy——方法在其范圍結束時調用。
清單 9 顯示了具有生命周期方法的 Java 實現類。
清單 9. 具有生命周期方法的 Java 實現類
package services.profile;
import org.osoa.sca.annotations.*;
@Service(ProfileService.class)
public class ProfileServiceImpl implements ProfileService {
public String getFirstName( ) { ....}
@Init
public void start() { . . . }
@Destroy
public void stop() { . . . }
}
實現配置屬性
Java 類中字段或方法上的 @Property Annotation 用于定義 Java 組件實現的配置屬性。以下是 @Property Annotation 的特性:
- name——屬性的名稱,缺省值為 Java 類的字段的名稱。
- require——指定是否需要注入,缺省值為 false。
清單 10 顯示了使用 @Property Annotation 的配置屬性的定義。
清單 10. 使用 @Property Annotation 的配置屬性的定義
package services.payroll;
import org.osoa.sca.annotations.Property;
import org.osoa.sca.annotations.Reference;
import services.payrolldata.PayrollDataService;
public class PayrollServiceImpl implements PayrollService {
@Property
private String currency = "INR";
@Reference
private PayrollDataService payrollDataService;
public PayrollStatement getPayrollStatement (String employeeID) { . . . . }
}
基本客戶機模型
客戶機可以從 SCA 組件和非 SCA 組件獲得對服務的訪問。
從 SCA 組件實現訪問服務
獲得對服務的訪問的不同方法如下:
使用引用注入 通過定義服務的類型接口的 Java 類數據成員指定和通過 @Reference Annotation 加標注,可使用引用注入獲得對服務的訪問。@Reference Annotation 的特性有:
- name——引用的名稱。
- required——是否需要服務的注入。
清單 11 顯示了使用 @Reference Annotation 的 Java 實現。
清單 11. 使用 @Reference Annotation 的 Java 實現
package services.profile;
import org.osoa.sca.annotations.Service;
import org.osoa.sca.annotations.Reference;
@Service(LoginService.class)
public class LoginServiceImpl implements LoginService{
@Reference(name="profileService", required=true)
private ProfileService profileService;
public int login(String employeeID, String password) { .... }
}
以下是上述組件實現對應的組件類型。
清單 12. 組件類型
<?xml version="1.0" encoding="ASCII"?>
<componentType xmlns="http://www.osoa.org/xmlns/sca/0.9">
<service name="ProfileService ">
<interface.java interface="services.profile.LoginService"/>
</service>
<reference name="profileService">
<interface.java interface="services.profile.ProfileService"/>
</reference>
</componentType>
使用模塊上下文
使用模塊上下文訪問服務的必要事項有:
- 字段必須定義為能接受注入的模塊上下文。
- 必須對注入的模塊上下文調用方法。
通過將字段定義為 ModuleContext 類型,或使用 @Context Annotation,可指定使用模塊上下文進行服務訪問。清單 13 顯示了 ModuleContext 接口及其 locateService() 方法。
清單 13. ModuleContext 接口
package org.osoa.sca;
public interface ModuleContext {
...
Object locateService(String serviceName);
}
清單 14 顯示了使用 @Context Annotation 的模塊上下文定義示例:
清單 14. 使用 @Context Annotation 的模塊上下文定義
package innovasolutions.web.ui;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.osoa.sca.CurrentModuleContext;
import org.osoa.sca.ModuleContext;
import services.profile.LoginService;
public class LoginServlet extends HttpServlet{
private ServletContext mContext;
public void init(ServletConfig pCfg) throws ServletException{
mContext = pCfg.getServletContext();
}
public void doPost(HttpServletRequest pReq,
HttpServletResponse pResp) throws ServletException{
LoginService loginMgr = (LoginService)CurrentModuleContext.getContext().
locateService("LoginServiceComponent");
if (loginMgr == null){
throw new ServletException("LoginManager not found");
}
. . . .
}
從非 SCA 組件實現訪問服務
屬于 SCA 模塊一部分的非 SCA 組件使用模塊上下文獲取對服務的訪問。它們在其實現中使用 ModuleContext 查找服務。它們通過 CurrentModuleContext 類獲取對 current ModuleContext 的訪問,如清單 15 中所示。
清單 15. CurrentModuleContext 類
package org.osoa.sca;
public final class CurrentModuleContext {
public static ModuleContext getContext() {... }
}
非 SCA 組件實現將包括與以下所示類似的代碼行,以獲取對模塊上下文的訪問:ModuleContext moduleContext = CurrentModuleContext.getContext();
錯誤處理
調用服務方法客戶機時可能會遇到以下異常:
- 業務異常——由被調用的服務方法的實現引發。
- SCA 運行時異常——由 SCA 運行時引發,指示組件的異常管理及與遠程服務的交互中存在的問題。當前受支持的 SCA 運行時異常有服務運行時異常和服務不可用異常。
異步編程
在服務的異步編程中,客戶機調用服務,并在不等待服務執行的情況下繼續進行自身的執行。
SCA 異步編程模型支持三種類型的異步調用。即:
- 非阻塞方法調用
- 對話服務
- 回調
- 非阻塞調用
通過使用非阻塞調用,客戶機可調用服務并立即繼續進行后續處理,而不必等待服務執行。非阻塞方法使用 @Oneway Annotation 進行調用。當前 SCA 支持對返回“void”且沒有已聲明異常的方法進行非阻塞調用。
對話服務
服務的客戶機和服務提供者之間的對話經常在遠程服務執行期間發生。傳統編程模型要求編寫大量的代碼來支持此模式。SCA 簡化了對話服務的設計,而將 ID 生成、狀態管理和路由的細節留給 SCA 容器處理。
在 SCA 中,使用會話來維護有關客戶機和遠程服務間的單個對話的信息。SCA 使用 @Scope、@Session 和 @SessionID Annotation 來實現對話服務。
回調
回調服務提供從服務提供者回到其客戶機的異步通信。雙向服務使用的回調是具有兩個接口的服務,一個供服務提供者使用,另一個供客戶機使用。
SCA 通過在遠程服務接口上使用 @Callback Annotation 來提供回調服務(接受接口的 Java Class 對象作為參數)。
清單 16 顯示了 @Callback Annotation 的使用。
清單 16. @Callback Annotation
package somepackage;
import org.osoa.sca.annotations.Callback;
import org.osoa.sca.annotations.Remotable;
@Remotable
@Callback(MyServiceCallback.class)
public interface MyService {
public void someMethod(String arg);
}
@Remotable
public interface MyServiceCallback {
public void receiveResult(String result);
}
開放源代碼運行時和工具
有一個開放源代碼項目提供服務組件體系結構的運行時實現,可用于運行 SCA 應用程序。此項目稱為 Tuscany,目前在 Apache 處于孵化期。此項目的主要參與者有 IBM、BEA、Oracle、Sybase、SAP、IONA 和 Siebel。
結束語
本文分別通過 Java 接口和 Java 類組件實現描述了服務的表示形式和實現。文中說明了使用 Java Annotation 的服務實現的配置屬性。您了解了從 SCA 和非 SCA 組件訪問服務的各種方式,還了解了各種錯誤處理機制、異步編程模型和各種異步調用。
posted on 2008-03-11 14:03 gembin 閱讀(431) 評論(0) 編輯 收藏 所屬分類: SCA 、SOA