1 Java 實現(xiàn)類型
1.1 簡介
該規(guī)范擴展自SCA裝配模型規(guī)范,定義了java類如何提供SCA組件的實現(xiàn),以及該類在SCA中是如何作為組件實現(xiàn)類型來使用的。
該規(guī)范需要用到所有《SCA的 Java注解和API規(guī)范v100》(本人正在翻譯)中定義的所有的注解和API。該文檔所引用的所有注解和API都是前者提到的規(guī)范所定義的,除非另行指定。SCA的 Java注解和API規(guī)范中定義的語義都是標(biāo)準(zhǔn)化的。
1.2 Java實現(xiàn)類型
這一節(jié)指出java類是如何提供SCA組件的實現(xiàn)的,包括各種屬性,如服務(wù),引用和屬性。另外,它詳細列出了在作為組件實現(xiàn)類型的Java類上下文中,SCA的 Java注解和API規(guī)范中的元數(shù)據(jù)和Java API的使用方法。
1.2.1 service
基于Java類的組件實現(xiàn)可以提供一個或多個服務(wù)。
由基于Java的實現(xiàn)所提供的服務(wù)可以擁有按如下方法之一定義的接口:
l Java接口
l Java類
l 產(chǎn)生自WSDL portType的Java接口
Java實現(xiàn)類必須實現(xiàn)service接口定義的所有操作。如果服務(wù)接口是由某個java接口定義的,那么基于java的組件或?qū)崿F(xiàn)該java接口,或?qū)崿F(xiàn)接口的所有操作。
與java接口相比,其接口是通過java類定義的服務(wù)不是遠程的。產(chǎn)生自WSDL portType的Java接口是遠程的,細節(jié)可以查看SCA java注釋和API規(guī)范的WSDL 2 Java和Java 2 WSDL節(jié)。
Java實現(xiàn)類型可以指定通過@Service顯式提供的服務(wù)。以上情形下,@Service的使用并不是必須的,Java實現(xiàn)類型提供的服務(wù)可以從實現(xiàn)類自身繼承而來。
1.2.1.1 @Service的使用
服
務(wù)接口可以作為Java接口來指定。是組件實現(xiàn)的Java類,可以通過實現(xiàn)指定服務(wù)契約的java接口來提供服務(wù)。因為一個java類可以實現(xiàn)多個接口,
而某些并沒有定義SCA 服務(wù),所以@Service注解可以用于表示由實現(xiàn)提供的服務(wù)以及他們相應(yīng)的Java接口定義。
如下是java服務(wù)接口和使用該接口提供服務(wù)的Java實現(xiàn)的例子:
Interface:
public interface HelloService {
String hello(String message);
}
Implementation class:
@Service(HelloService.class)
public class HelloServiceImpl implements HelloService {
public String hello(String message) {
...
}
}
該實現(xiàn)的組件類型的XML描述如下。沒有必要指定component type,因為可以從Java類反射得到。
<?xml version="1.0" encoding="ASCII"?>
<componentType xmlns="http://www.osoa.org/xmlns/sca/0.9">
<service name="HelloService">
<interface.java inter>"services.hello.HelloService"/>
</service>
</componentType>
和接口相比,Java類實現(xiàn)本身也能定義由組件提供的服務(wù)。這種情況下,@Service可以被用于顯式地聲明定義了實現(xiàn)所提供的服務(wù)的實現(xiàn)類。同情形下,組件只能用@Service提供服務(wù)。如下所示:
@Service(HelloServiceImpl.class)
public class HelloServiceImpl implements AnotherInterface {
public String hello(String message) {
...
}
…
}
在上述例子中,HelloWorldServiceImpl提供了一個服務(wù)。該服務(wù)在實現(xiàn)類上定義為public方法。AnotherInterface接口沒有指定組件所提供的服務(wù)。如下是內(nèi)省的組件類型的XML描述:
<?xml version="1.0" encoding="ASCII"?>
<componentType xmlns="http://www.osoa.org/xmlns/sca/1.0">
<service name="HelloService">
<interface.java inter/>
</service>
</componentType>
@Service可以用于指定由實現(xiàn)提供的多個服務(wù):
@Service(interfaces={HelloService.class, AnotherInterface.class})
public class HelloServiceImpl implements HelloService, AnotherInterface {
public String hello(String message) {
...
}
…
}
如下片段演示了該實現(xiàn)的內(nèi)省的組件類型:
<?xml version="1.0" encoding="ASCII"?>
<componentType xmlns="http://www.osoa.org/xmlns/sca/1.0">
<service name="HelloService">
<interface.java inter>"services.hello.HelloService"/>
</service>
<service name="AnotherService">
<interface.java inter>"services.hello.AnotherService"/>
</service>
</componentType>
1.2.1.2 本地和遠程服務(wù)
由接口定義的Java服務(wù)契約,可以使用@Remotable來聲明服務(wù)按照SCA裝配規(guī)范遵循遠程服務(wù)的語義。如下演示了@Remotable使用:
package services.hello;
@Remotable
public interface HelloService {
String hello(String message);
}
如果沒有聲明@Remotable,由Java接口定義的服務(wù)就被認為是SCA裝配模型規(guī)范里定義的本地服務(wù)。
如果實現(xiàn)類實現(xiàn)了沒有用@Remotable注解修飾的接口,那么該類被認為實現(xiàn)了單個本地服務(wù)。該本地服務(wù)的類型是由該類定義的。(注:本地服務(wù)可以使用Java接口或類指定類型)
某個實現(xiàn)類為SCA運行時提供關(guān)于是否能通過使用@AllowsPassByReference來完成不經(jīng)過copy而傳值語義工作的信息。
1.2.1.3 內(nèi)省Java實現(xiàn)提供的服務(wù)
上述情況下,由Java實現(xiàn)類提供的服務(wù)可以通過內(nèi)省來決定,而可以忽略使用@Service指定的必要。如下的算法被用來決定服務(wù)是如何從實現(xiàn)類內(nèi)省的。
如果SCA服務(wù)的接口在實現(xiàn)類上沒有用@Service注解指定,那么就假設(shè)所有的用@Remotable注解了的接口都是由組件提供的服務(wù)接口。如果沒有一個實現(xiàn)接口是遠程的,那么默認實現(xiàn)提供了單個服務(wù),該服務(wù)的類型就是實現(xiàn)的class。
1.2.1.4 非堵塞型服務(wù)操作
由java接口或?qū)崿F(xiàn)類定義的服務(wù)操作可以使用@OneWay來聲明SCA 運行時在客戶程序調(diào)用服務(wù)操作的時候必須遵循非堵塞性語義。該非堵塞性語義由SCA裝配規(guī)范(本人正在翻譯)定義了。
1.2.1.5 非會話和會話服務(wù)
Java實現(xiàn)類型支持所有的會話服務(wù)注解,這些會話注解在SCA Java注解和API規(guī)范中定義:@Conversational,@EndsConversational和@ConversationAttributes。
以
下的語義控制由Java接口或?qū)崿F(xiàn)類定義的服務(wù)契約。由Java接口或?qū)崿F(xiàn)類定義的服務(wù)契約隱式地表示非會話除非使用了@Conversational注
解修飾。一旦使用了@Conversational注解修飾,@Conversational就用于聲明提供服務(wù)的組件實現(xiàn)實現(xiàn)了會話語義。
1.2.1.6 回調(diào)服務(wù)
回調(diào)接口通過在某個Java類實現(xiàn)的服務(wù)接口上使用@Callback注解來聲明。
1.2.2 引用
引用可以通過注入或SCA Java 注解和API規(guī)范中定義的ComponentContext API來維護。只要可能,推薦使用注入方式來訪問引用。
1.2.2.1 引用注入
某個Java實現(xiàn)類型可以通過使用@Reference顯式地指定其引用,如下所示:
public class ClientComponentImpl implements Client {
private HelloService service;
@Reference
public void setHelloService(HelloService service) {
this.service = service;
}
}
如 果@Reference標(biāo)記了某個public或protected
的setter方法,那么就要求SCA運行時提供指定了方法參數(shù)類型的服務(wù)引用契約的相應(yīng)實現(xiàn)。通過調(diào)用實現(xiàn)實例的setter方法來完成這個工作。注入
什么時候發(fā)生是由實現(xiàn)的作用域(scope)定義的。然而,它總是在第一個服務(wù)方法被調(diào)用之前發(fā)生注入。
如果@Reference標(biāo)記了某個public或protected的屬性域,那么就要求SCA運行時提供指定了屬性域類型的服務(wù)引用契約的相應(yīng)實現(xiàn)。通過設(shè)置實現(xiàn)實例的該屬性域來完成。什么時候發(fā)生注入由實現(xiàn)的作用域定義。
如果@Reference標(biāo)記構(gòu)造函數(shù)的某個參數(shù)上,那么就要求SCA運行時提供在實現(xiàn)初始化時期指定了構(gòu)造函數(shù)參數(shù)的服務(wù)引用契約的相應(yīng)實現(xiàn)。
引用也可以根據(jù)XXX(這里原文有問題)節(jié)定義的規(guī)則通過內(nèi)省實現(xiàn)類來指定。
引用可以是聲明選項(聲明選項在SCA Java注解和API規(guī)范中定義了)。
1.2.2.2 動態(tài)引用訪問
引用可以通過ComponentContext.getService()和ComponentContext.getServiceReference(.)方法來動態(tài)訪問。
1.2.3 屬性(Property)
1.2.3.1 屬性注入
屬性可以通過注入或ComponentContext API來維護。只要可能,推薦使用注入方式來訪問屬性。
Java實現(xiàn)類型可以通過使用@Property注解顯式指定它的屬性,如下所示:
public class ClientComponentImpl implements Client {
private int maxRetries;
@Property
public void setRetries(int maxRetries) {
this. maxRetries = maxRetries;
}
}
如果@Property標(biāo)記了某個public或protected屬性域,那么就要求SCA運行時提供相應(yīng)的屬性值。什么時候發(fā)生注入由實現(xiàn)的作用域(scope)定義。
如果@Property標(biāo)記在構(gòu)造函數(shù)的某個參數(shù)上,那么就要求SCA運行時在實現(xiàn)實例初始化期間提供相應(yīng)的屬性值。
屬性也可以根據(jù)XXX(這里原文有問題)節(jié)定義的規(guī)則通過內(nèi)省實現(xiàn)類來指定。
1.2.3.2 動態(tài)屬性訪問
屬性可以通過ComponentContext.getService()和ComponentContext.getServiceReference(.)方法來動態(tài)訪問。這問mponentContext.getServiceReference()
1.2.4 實現(xiàn)實例的初始化
Java實 現(xiàn)類必須提供一個public或protected
構(gòu)造函數(shù),以便SCA運行時用于初始化實現(xiàn)的實例。構(gòu)造函數(shù)可以有參數(shù);當(dāng)存在參數(shù)時,SCA容器會在調(diào)用構(gòu)造函數(shù)的時候傳遞可用的屬性或引用值。在任何
一個服務(wù)方法被調(diào)用之前,所有的屬性或引用值,都將會設(shè)置給屬性域或傳遞給與屬性相關(guān)的setter方法。
構(gòu)造函數(shù)的選用由容器選擇,如下所示:
1. 用@Constructor注解標(biāo)注的聲明的構(gòu)造函數(shù)
2. 無二義性的標(biāo)識所有屬性和引用值的聲明的構(gòu)造函數(shù)
3. 無參數(shù)的構(gòu)造函數(shù)
@Constructor注解只能在一個構(gòu)造函數(shù)上指定;如果多個構(gòu)造函數(shù)標(biāo)注了@Constructor,SCA容器將報錯。
與構(gòu)造函數(shù)的每個參數(shù)相關(guān)的屬性或引用用下列方式標(biāo)識:
l @Constructor注解的by name(如果存在)
l 通過在參數(shù)聲明上使用的@Property或@Reference注解
l 通過唯一地與屬性或引用的類型匹配參數(shù)類型
組件間的循環(huán)引用發(fā)生的話,容器會用以下辦法之一進行處理:
l 如果循環(huán)中的任意引用是可選的(不是必須的),那么容器就會在構(gòu)造期間注入null值。保證調(diào)用任何服務(wù)之前都已經(jīng)注入了目標(biāo)的引用。
l 容器也可以注入一個目標(biāo)服務(wù)的代理;在代理上的方法調(diào)用可能會導(dǎo)致ServiceUnavailableException異常。
以下是合法的Java組件構(gòu)造函數(shù)聲明的例子:
/** Simple class taking a single property value */
public class Impl1 {
String someProperty;
public Impl1(String propval) {...}
}
/** Simple class taking a property and reference in the constructor;
* The values are not injected into the fields.
*//
public class Impl2 {
public String someProperty;
public SomeService someReference;
public Impl2(String a, SomeService b) {...}
}
/** Class declaring a named property and reference through the constructor */
public class Impl3 {
@Constructor({"someProperty", "someReference"})
public Impl3(String a, SomeService b) {...}
}
/** Class declaring a named property and reference through parameters */
public class Impl3b {
public Impl3b(
@Property("someProperty") String a,
@Reference("someReference) SomeService b) {...}
}
/** Additional property set through a method */
public class Impl4 {
public String someProperty;
public SomeService someReference;
public Impl2(String a, SomeService b) {...}
@Property public void setAnotherProperty(int x) {...}
}
1.2.5 實現(xiàn)作用域和生命周期回調(diào)
Java實現(xiàn)類型支持在SCA Java注解和API規(guī)范中定義的所有作用域:STATELESS,REQUEST,CONVERSATION和COMPOSITE。實現(xiàn)通過使用@Scope注解指定它們的作用域:
@Scope(”COMPOSITE”)
public class ClientComponentImpl implements Client {
// …
}
當(dāng)沒有在實現(xiàn)類上指定@Scope注解,默認為STATELESS。
Java組件的實現(xiàn)通過分別使用@Init和@Destroy來指定init和destroy回調(diào)。例如:
public class ClientComponentImpl implements Client {
@Init
public void init() {
//…
}
@Destroy
public void destroy() {
//…
}
}
1.2.5.1 作用域為CONVERSATION的Java實現(xiàn)類可能會使用@ConversationID注解來持有當(dāng)前的會話ID。該會話ID通過public或protected屬性域或setter方法注入??蛇x地,Conversation API(在SCA Java注解和API規(guī)范中定義)能用來獲取當(dāng)前的會話ID。
會話性的實現(xiàn)
作為會話服務(wù)的提供者,有必要在單個會話的連續(xù)的方法調(diào)用之間維持狀態(tài)數(shù)據(jù)。對于Java實現(xiàn)類型,有兩種可能的策略用于處理該狀態(tài)數(shù)據(jù):
1. 實現(xiàn)可以構(gòu)建為無狀態(tài)的代碼片(本質(zhì)上來說,代碼認為對于每個函數(shù)調(diào)用都是新的實例)。代碼必須負責(zé)訪問會話的conversationID,該會話由SCA運行時維護。然后,在方法的處理過程期間和需要訪問持久化的狀態(tài)數(shù)據(jù)時,由實現(xiàn)來負責(zé)持久化任何必要的狀態(tài)數(shù)據(jù),而所有都是以conversationID作為key來使用。
2. 實現(xiàn)可以構(gòu)建為有狀態(tài)的代碼片,也就意味著實現(xiàn)把所有的狀態(tài)數(shù)據(jù)存儲在java類實例的屬性域中。實現(xiàn)必須用@Scope注解聲明為會話作用域。這就告訴SCA運行時環(huán)境,實現(xiàn)是有狀態(tài)的,并且SCA運行時必須在客戶函數(shù)調(diào)用與服務(wù)實現(xiàn)的某個特定實例之間扮演中介角色。如果運行時因為某種原因需要將實例清除出內(nèi)存,運行時環(huán)境還要負責(zé)持久化和存儲實現(xiàn)的實例。(注:會話是非常長的生命期限,SCA運行時可以使用集群系統(tǒng)。在集群系統(tǒng)中給定的實例對象可以在集群的各個節(jié)點中移動,以實現(xiàn)負載均衡)
1.2.6訪問回調(diào)服務(wù)
Java實現(xiàn)類用@Callback注解來要求回調(diào)服務(wù)。該@Callback注解引用了在某個public或protected屬性域或setter方法上與當(dāng)前調(diào)用注入相關(guān)的回調(diào)服務(wù)。
1.2.7未注解的實現(xiàn)的語義
這一節(jié)定義了并未使用@Reference或@Property顯式聲明的Java組件實現(xiàn)的屬性和引用的判定規(guī)則。
在沒有@Property和@Reference注解的時候,類的屬性和引用按以下規(guī)則定義:
1. 如果Java類型是由@Remotable注解的接口,就是引用。
2. 否則,如果Java類型是一個數(shù)組,并該數(shù)組元素的類型是由@Remotable注解的接口,那么就是引用。
3. 否則,如果Java類型是java.util.Collection的子接口或子類,并且collection的參數(shù)化類型是由@Remotable注解的接口,那么就是引用。
4. 否則就是屬性。
1.2.8在裝配中指定java實現(xiàn)
如下定義了用于java實現(xiàn)類型的實現(xiàn)元素schema:
<implementation.java class="NCName" />
Implementation.java元素有如下屬性:
class(必須) –實現(xiàn)的java類全名。
1.2.9指定component type
對于Java實現(xiàn)類,組件類型一般都是直接來自java類的內(nèi)省。
在配置文件中component type的指定是可選的。組件類型配置文件由裝載java類的同一個類裝載器發(fā)現(xiàn)。配置文件必須在與實現(xiàn)的名稱空間一致的目錄下,并與java類擁有相同的名字,并用.componentType擴展名替代.class擴展名。
componentType side文件是如何加入到從組件的實現(xiàn)反射而來的組件類型信息中的規(guī)則在SCA裝配模型規(guī)范中定義了。如果組件類型信息與實現(xiàn)沖突,將產(chǎn)生錯誤。
如果componentType side文件用WSDL接口指定了服務(wù)接口,那么java類應(yīng)該實現(xiàn)由JAX-WS的WSDL到java接口的映射而產(chǎn)生的接口。請查看”WSDL 2 Java和Java 2 WSDL”節(jié)