引言
SCA Java 實現模型提供了用於在 Java 中實現 SCA 組件的框架。組件實現可以提供服務,也可以充當其他服務的客戶機。本文將說明 SCA Java 組件實現和非 SCA Java 組件實現可以如何獲得對服務的訪問和調用服務方法。在本文中,所有元數據都使用 Java 2 Standard Edition (J2SE) 5 提供的 Annotation 功能定義。不過,SCA 服務客戶機和組件實現也可使用 J2SE 1.4。
基本組件實現模型
此模型描述本地或遠程服務的實現以及特定於實現的配置屬性。
實現服務
服務使用接口表示,而接口則是使用以下方法之一進行定義的:
Java 類組件實現會實現服務接口定義的所有操作,它使用 @Service Annotation 來指定服務通過使用 Java 實現而實現的服務接口。旨在用作服務實現的類並不必具有 @Service Annotation。@Service Annotation 具有兩個特性:
以下代碼片段顯示了名為 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();
}
遠程服務使用封送技術來交換復雜數據類型。在使用 Web 服務綁定時,會將服務數據對象 (Service Data Object) 或 JAXB 數據類型作為參數傳遞。遠程服務使用按值數據交換語義。
遠程服務的實現上的 @AllowPassByReference Annotation 用於聲明它是否允許在對其進行調用時通過引用數據交換語義進行傳遞。
以下代碼片段顯示了實現遠程服務並允許通過引用傳遞的 Java 組件實現。
清單 6. 具有遠程服務和允許通過引用傳遞的 Java 組件實現
以下為引用的內容:
package services.payrolldata;
Import org.osoa.sca.annotations.*;
@Service(PayrollDataService.class)
@AllowsPassByReference
public class PayrollDataServiceImp implements PayrollDataService {
. . . .
}
實現本地服務
本地服務僅能由屬於相同模塊的客戶機調用。Java 本地服務接口是在不使用 @Remotable Annotation 的情況下定義的。
以下代碼片段顯示了本地服務的 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,其值為范圍的名稱。
以下是當前支持的范圍值:
除了模塊范圍內的實現外,對於其他三個,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 的特性:
清單 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 的特性有:
清單 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 異步編程模型支持三種類型的異步調用。即:
通過使用非阻塞調用,客戶機可調用服務並立即繼續進行後續處理,而不必等待服務執行。非阻塞方法使用 @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 組件訪問服務的各種方式,還了解了各種錯誤處理機制、異步編程模型和各種異步調用。