SCA的java注解和API规范v100

注:

翻译风格:还不能很确定的内容用 还不能很确定的内容 格式表示
案例代码用 code to example斜体来表示
 
1.       通用Annotation,API,客户程序和实现模型
1.1    简介
       SCA通用注解(annotaion),API函数,客户程序和实现模型为SCA装配模型规范中定义的编程理念制定了Java语法规则。他规定了一系列能用于基于Java的SCA规范的API和注解。
       特别地,该规范包括以下内容:
1. 实现了指定组件服务,引用和属性的元数据
2. 客户端和组件API的J3. 元数据,用于异步和同步的服务。
3. 回调机制的元数据
4. 标准组件实现范围的定义
5. Java到WSDL和WSDL到Java的映射
6. 安全策略注解
注意个别的编程模型在某些适当的时机也许会选择用本地的API和本地方言来实现自己对装配模型理念的映射。
规范注解,API,客户端以及实现模型的目标是提升一致性以减少各种Java相关的组件实现类型规范的副本。本规范中制定的注解,API,客户端以及实现模型是为被其他基于Java的SCA规范所使用而设计的。
本文档使用J2SE 5的注解技术来实现元数据。然而,SCA也允许服务的客户端和实现用J2SE1.4来开发。所有注释代表的元数据也可以使用组件类型文件来表述,该组件类型文件也在SCA装配规范中定义了。
 
1.2    实现元数据
       这一节描述了基于Java技术的SCA元数据是如何应用到基于Java的实现中的。
1.2.1          Service元数据
1.2.1.1    @Service
       @Service注解被用在java类上来指定服务实现的接口。一般来说,服务接口用以下的方法之一来定义:
l         作为一个Java接口
l         作为一个Java类
l         作为一个从Web service描述语言产生的Java接口(一般总是远程接口)
1.2.1.2    远程服务的Java语义
       远程服务在定义了服务的Java接口上使用@Remotable注解来定义。远程服务规定用语粗粒度的服务,参数以传值的方式传递。
1.2.1.3    本地服务的Java语义
       本地服务只能被和本地服务组件实现部署在同一个地址空间的客户端程序访问。本地接口可以是不带@Remotable注解的java接口或java类
下面的代码片段显示了本地服务的Java接口
package services.hello;
  public interface HelloService {
  String hello(String message);
  }
本地接口一般是细粒度的,用于紧密联系的交互。
调用本地接口的数据交换语义是通过引用 (by-reference) 。这个意味着代码必须由知道参数的改变模式的客户端或服务的提供者所开发出来。
1.2.2    @Reference
    通过定义服务接口的属性域、 setter 方法或构造函数并加入 @Reference 注解来使用引用注入来访问服务。
1.2.3    @Property
    实现能通过属性来进行配置,属性在 SCA 的装配规范里也定义了。 @Property 注解用于定义 SCA 属性。
1.2.4          实现的作用域:@Scope,@Init,@Destroy
       组件实现也能管理他们自己的状态或让SCA运行时环境来做这些工作。后一种情况下,SCA定义实现作用域,该作用域指定了实现和SCA运行时环境的可见性和生命周期契约。组件提供的服务调用由SCA运行时环境根据实现作用域的语义来分发到每个实现的实例上去。
作用域在实现类上用@Scope注解来指定。
该文档定义了四种基本的作用域:
l         STATELESS
l         REQUEST
l         CONVERSTATION
l         COMPOSITE
基于Java的实现可以选择去支持这些作用域,也可以定义一个新的作用域。
实现的类型也允许组件实现声明生命周期方法,用于实现被实例化或作用域过期时调用。 @Init指示在作用域的生命周期中第一次使用实例的时候被调用。@Destroy表示函数当作用域结束的时候被调用。注意,只有公共的无参数的方法才能做为生命周期函数被注解。
@Init
  public void start() {
...
}
@Destroy
public void stop() {
...
}
 
接下来的章节给出四个标准的基于Java的实现类型作用域。
1.2.4.1 Stateless
       对于无状态组件,服务请求之间没有隐式的关联。
1.2.4.2 Request
       请求作用域的生命周期是从远程接口上的请求进入到SCA运行时环境开始,一个线程处理该请求,直到线程同步地完成此请求为止。这期间,所有的服务请求将被委托给相同请求作用域组件的实现实例。
       很多次,当本地的请求作用域服务被调用,在调用栈中没有早期的远程服务。例如,本地服务被非SCA实体调用的时候。这些情况下,远程请求总是被认为是存在的,但请求的生命期限依赖于实现。比如,一个时间事件将作为一个远程请求对待。
1.2.4.3 Composite
       所有的服务请求被分发到同一个实现的实例,是因为容器构件的生命期限。容器构件的生命期限是作为激活和钝化的时间来定义的,可以是正常的也可以是异常的。
       构件作用域的实现也许还会用@EagerInit注解来指定渴望初始化。当标注了渴望初始化的话,在容器组件启动的时候就会创建构件作用域的实例。假如一个方法被标住了@Init注解,当实例创建的时候就会被调用。
1.2.4.4 Conversation
       会话是指定义了客户与目标服务之间的一系列相关的交互。当第一个服务请求被分发到某个提供了会话服务的实现实例的时候,会话作用域就开始了。当服务契约定义的某个终端操作被调用之后,并完成处理或会话过期,会话作用域就完成。一旦这个发生,运行时必须保证保存有实现实例的状态。
       注意,当一个会话服务是被一个标注了会话范围的Java类实现的时候,SCA运行时环境将会透明地处理实现的状态。当然,也可能由实现自己来管理自己的状态。比如,一个stateless或其他作用域的Java类能实现会话服务。
1.3    接口元数据
这一节为Java接口描述SCA元数据
1.3.1          @Remotable
       用于接口上的@Remotable注解表示该接口是被设计来用于远程通讯的。远程接口就意味着用于粗粒度的服务。操作参数和返回值都是传值的方式传递。
1.3.2          @Conversational
       Java服务接口也许会使用@Conversational注解来指定是否他们的契约是会话的。会话服务表示服务的请求在一定程度上是相互关联的。
当一个服务接口没有指定@Conversational注解,该服务的契约就是无状态的。
1.4    客户API
这一节讲述SCA服务是如何被组件和非管理代码(比如不是作为SCA组件来运行的代码)通过编程方式来访问的。
1.4.1          访问某个SCA组件提供的服务
一个SCA组件也许通过注入或编码方式地通过组件Context API包含了某个服务的引用。使用引用注入是访问服务所推荐的方式,因为这样可以让代码最小程度使用中间件API。只有在引用注入不可能的情况下才使用组件Context API。
1.4.1.1    使用组件Context API
当组件的实现需要访问某个服务,而该服务的引用在编译期是所无法识辨,引用就可以使用组件的ComponentContext来定位。
1.4.2          访问非SCA组件实现提供的服务
这节描述了对于并未作为SCA组件的java代码是如何通过引用来访问SCA服务的。
1.4.2.1    ComponentContext
非SCA客户代码能通过使用ComponentContext API来执行某个SCA 域中的操作。客户代码如何获取一个ComponentContext的引用是与运行时相关的。以下示例代码给出了非SCA代码是如何使用ComponentContext API的。
ComponentContext context = // 通过主机环境规范所获取到的
HelloService helloService = context.getService(HelloService.class,”HelloService”);
String result = helloService.hello(“Hello World!”);
1.5    错误处理
客户调用服务的方法也许会引发业务异常和SCA运行时异常。被调用的服务方法的实现抛出业务异常,该业务异常定义为服务接口的checked异常。
SCA运行时异常是由SCA运行时和组件执行和与远程服务交互的管理中信号问题所产生的。会用到SCA运行时异常ServiceRuntimeException和ServiceUnavailableExecption,他们在1.5节中定义了。
1.6    异步和会话编程
服务的异步编程会在客户调用某个服务,但不需要等待服务执行而自己继续执行的时候使用。典型的情况是被调用的服务会在以后的某个时刻执行。被调用服务的输出即便是有,也必须通过一个单独的机制来返回给客户程序,因为在服务调用的那个时点没有有效的输出。而同步的调用-返回类型的契约要求被调用的服务执行并在客户程序继续执行之前返回给客户输出。SCA异步编程模型由支持 非堵塞方法调用会话服务回调组成。以上的这些话题都会在后面的章节中讨论。
会话服务是指在客户和服务提供者之间存在正在进行着的一系列交互的服务。与简单的无状态交互相比,服务提供者维护某些状态数据。尽管不是强制性的,但异步服务经常会伴随这会话的使用。
1.6.1 @OneWay
非堵塞调用是异步编程里的最简单的形式。这种情况服务的客户程序调用服务,并立即继续执行,而不需要等待服务的执行。
任何返回void类型和无声明异常的的方法都会用@OneWay注解来注释。这意味着该方法是非堵塞的,在后续的某个时刻和服务提供者的通讯会用到缓冲了请求和发送的绑定机制。
SCA 当前还没有为有返回值的或被定义为有异常抛出的方法标注非堵塞性方法调用的定义机制。推荐服务的设计者尽量定义one-way方法,以便为部署者提供最大的绑定灵活度。
1.6.2 会话服务
某个服务可以通过用@Conversational来标注它的Java接口来声明为会话性的服务。如果没有用@Conversational注解,则表示是无状态的。
1.6.2.1 ConversationAttributes
基于Java的实现类也许会用@ConversationAttributes来修饰,该注解用于为会话实现的实例指定过期规则。以下是@ConversationAttributes的例子代码:
package com.bigbank;
import org.osoa.sca.annotations.Conversation;
import org.osoa.sca.annotations.ConversationID;
 
@ConversationAttributes(maxAge="30 days");
public class LoanServiceImpl implements LoanService {
}
1.6.2.2 @EndsConversation
某个会话接口的方法可以用@EndsConverstation注解来标注。一旦标注了@EndsConversation注解的方法被调用,客户和服务提供者的会话就会终止。也就是说在同一个会话中不能再调用该服务的其他方法了。这会让客户和服务提供者都释放会话相关的资源。
在一个回调接口的方法上也可能会用@EndsConversation来标注,以便服务提供者也能选择终止会话。
如果在会话已经终止后调用了会话接口上的某个方法,会抛出ConversationEndedException(继承自ServiceRuntimeException),在客户和服务提供者调用了各自的@EndsConversation方法的条件下也会发生异常。
1.6.3 将会话服务做为参数传递
描述了单个会话的服务引用能作为参数传递给其他的服务,即便这些其他服务是远程的。其用于某个组件来继续由其他组件启动的会话。
服务提供者也可以为自身创建一个服务引用,并把自己传递给其他服务。服务的实现使用以下方式来完成此项工作
interface ComponentContext{
 
<B> ServiceReference<B> createSelfReference (Class businessInterface);
<B> ServiceReference<B> createSelfReference (Class businessInterface,
                                              String serviceName);
}
如果组件实现了多个服务,必须使用带有附加serviceName参数的第二个变量。
1.6.4 会话客户程序
会话服务的客户程序不需要特定方式的编码。客户程序可以通过接口中不同方法以及他们共有共享的数据之间的关系来使用接口的会话特性。如果服务是异步的,客户程序也许更喜欢使用特性,如conversationID来保持对会话相关状态数据的跟踪。
客户程序的开发者通过内省服务契约来了解服务的会话性。
以下代码展示了客户程序如何访问以上所描述的会话服务的:
@Reference
  LoanService loanService;
  // Known to be conversational because the interface is marked as
  // conversational
 
  public void applyForMortgage(Customer customer, HouseInfo houseInfo,
                                                               int term)
  {
  LoanApplication loanApp;
  loanApp = createApplication(customer, houseInfo);
  loanService.apply(loanApp);
  loanService.lockCurrentRate(term);
  }
 
  public boolean isApproved() {
  return loanService.getLoanStatus().equals("approved");
  }
  public LoanApplication createApplication(Customer customer,
  HouseInfo houseInfo) {
  return …;
  }
1.6.5 会话生命周期摘要
启动会话
当以下情况下会话由客户端发起
l         会话服务的@Reference是被注入的
l         调用了CompositeContext.getServiceReference再调用了服务的某个函数
继续会话
客户程序继续某个已存在的会话,如下情况:
l         持有服务引用,该服务引用是会话启动时创建的。
l         作为参数从其他的服务获取到服务引用的对象,甚至是远程的服务。
l         从某种持久化存储中装载某个服务引用。
结束会话
会话结束,任何与会话相关的状态都会释放,当如下情况:
l         某个有@EndsConversation注解的服务操作被调用
l         服务会话生命时限超时
l         客户程序调用Conversation.end()
l         由会话的操作抛出的任何非业务异常
在注解了@EndsConversation的方法被调用后,如果调用服务引用的某个方法会自动开启一个新的会话,但在下一个会话启动之前,它将返回null。
1.6.6 会话ID
如果在某个protected或public的属性域或setter方法上标注了@ConversationID,那么该会话的会话ID就会注入到属性域上。(注:属性域没有必要是String类型)系统产生的会话ID总是字符串,但应用产生的会话ID可以是其他的复杂数据类型。
1.6.6.1 应用指定的会话ID
当使用了由客户提供的会话ID,就有可能会利用到会话服务的状态管理功能。要做到这些,客户程序不能使用引用注入,而要使用ServiceReference.setConversationID() API。
传入该函数的conversation ID应该是一个String或能序列化为XML的object的实例。此ID对于客户组件整个生命周期都必须是唯一的。如果客户程序是非SCA组件,ID必须是全局唯一。
不是所有的会话服务绑定都支持由应用指定的会话ID,或可能只支持应用指定的ID必须是String类型。
1.6.6.2 客户程序访问会话ID
不管会话ID是由客户程序选择还是由系统产生的,客户程序都能通过调用ServcieReference.getConversationID()来访问会话ID。
如果会话ID不是应用指定的,那么方法ServcieReference.getConversationID()仅仅保证在第一个操作调用之后返回一个有效的值,否则返回null。
1.6.7 回调
回调服务用于从某个服务提供者回到它的客户程序的异步通讯,该异步通讯与同步操作返回值是相反的。回调用于双向服务,该服务有两个接口:
l         服务提供的接口
l         回调接口,由客户程序提供
回调能同时用于远程和本地服务。双向服务的两个接口必须同时是远程或同时是本地的。混用两种是不合法的。回调有两种基本的形式:无状态的回调和有状态的回调。
回调接口是在远程服务接口上使用@Callback注解来声明的。该远程服务接口将接口的Java类对象作为参数。@Callback注解也能应用于实现的某个方法或属性域上。在下节将介绍到,为了实现回调注入而使用@Callback注解。
1.6.7.1 有状态回调
有状态回调用于描述某个服务的客户组件的特定实现的实例。有状态回调的接口应该用conversational标注。
以下例子的接口定义了一个有状态回调的交互。
package somepackage;
import org.osoa.sca.annotations.Callback;
import org.osoa.sca.annotations.Conversational;
import org.osoa.sca.annotations.Remotable;
@Remotable
@Conversational
@Callback(MyServiceCallback.class)
public interface MyService {
public void someMethod(String arg);
}
@Remotable
public interface MyServiceCallback {
public void receiveResult(String result);
}
这个例子中的服务实现使用@Callback注解来请求注入有状态回调。以下是例子中服务实现的代码片段。在这个例子中,请求被传递给某个其他的组件,以便服务能起到一个中介的作用。因为服务是会话作用域(conversation scoped),所以当后端服务回送它的异步相应时,回调仍然有效。
@Callback
protected MyServiceCallback callback ;
@Reference
protected MyService backendService;
public void someMethod(String arg) {
backendService.someMethod(arg);
}
public void receiveResult(String result) {
callback.receiveResult(result);
}
这个代码片段必须来自提供了两个服务的实现。这两个服务,一个提供给它的客户程序(MyService),一个用于从后端接受回调(MyServiceCallback)。该服务的客户程序也要实现MyServiceCallbakc中定义的方法。
private MyService myService;
@Reference
public void setMyService(MyService service){
myService = service;
}
public void aClientMethod() {
...
myService.someMethod(arg);
}
public void receiveResult(String result) {
// code to process the result
}
有状态回调支持    将服务引用作为参数传递的能力。主要的不同是有状态回调不需要任何附加参数传递给服务操作。这个带来了很大的便利。如果服务有很多操作,并且那些操作的任意一个都应该是会话的第一个操作。必须要将回调参数作为每个启动会话的操作的一部分是非常繁琐的。它自然也比要求应用开发者去调用显式的操作更自然,而该显式操作仅仅是传递需要用到的回调对象而已。
1.6.7.2 无状态回调
无状态回调接口是没有标注conversational的回调接口。与无状态服务不一样,使用无状态回调的客户程序不会有路由到客户实例的回调函数,并且其由客户程序来维护与会话相关的任何状态信息。比如客户程序自身来完成持久化状态管理的职能。客户程序必须用到的信息就是回调ID对象。该回调ID对象随着服务的请求被传递,并确保被任何回调返回。
以下是上面客户代码片段的一个重复,但假定MyServiceCallback是无状态的。这中情形下,客户程序需要在调用服务之前设置回调ID,当接收响应的时候获取回调ID。
private ServiceReference< MyService> myService;
@Reference
public void setMyService(ServiceReference<MyService> service){
myService = service;
}
public void aClientMethod() {
String someKey = "1234";
...
myService.setCallbackID(someKey);
myService.getService().someMethod(arg);
}
public void receiveResult(String result) {
Object key = myService.getCallbackID();
// Lookup any relevant state based on "key"
// code to process the result
}
正如无状态回调一样,服务实现通过用@Callback注解来注释属性域或setter方法来访问回调对象。如下所示:
@Callback
protected MyServiceCallback callback ;
无状态服务的不同就在于,如果组件正服务于除了原始客户程序的任何请求,回调域都是无效的。所以,前面章节使用的技术,前面章节存在来自backendService的响应,而backendService作为MyService的回调被传递是无法工作的,因为当接收到后端系统的消息的时候回调域还是null。
1.6.7.3 实现多双向接口
既然有单个实现类可能实现多个服务,自然也可能为每个实现的服务定义回调。服务的实现能为每个回调包含一个注入域。运行时环境会根据回调的类型注入回调到相应的域中。下面演示了两个域的定义,每个域都对应于由实现所提供的特定的服务。
@Callback
protected MyService1Callback callback1 ;
@Callback
protected MyService2Callback callback2 ;
如果单个回调中有某个与多个声明的回调域相兼容的类型,那么所有的回调域都会被设置。
1.6.7.4 访问回调
除了注入回调服务的引用外,也可以通过用@Callback注释某个属性域或函数的方式来维护一个回调实例的引用。
to be continue......
目录 ................................................................................................................................................................................... 5  1.  通用注解API、客户程序和实现模型 ................................................................................................................. 7  1.1. 简介 ........................................................................................................................................................................... 7  1.2. 实现的元数据 ........................................................................................................................................................... 7  1.2.1. 服务元数据 ............................................................................................................................................................ 8  1.2.2.@Reference ........................................................................................................................................................... 8  1.2.3. @Property ............................................................................................................................................................. 9  1.2.4. 实现作用域:@Scope、@Init、@Destroy ....................................................................................................... 9  1.3 接口元数据 .............................................................................................................................................................. 10  1.3.1. @Remotable ....................................................................................................................................................... 10  1.3.2. @Conversational ................................................................................................................................................ 11  1.4. 客户 API .................................................................................................................................................................. 11  1.4.1. SCA构件访问服务 .............................................................................................................................................. 11  1.4.2. 非 SCA构件的实现访问服务 ............................................................................................................................ 11  1.5. 错误处理 ................................................................................................................................................................. 12  1.6. 异步与会话编程 ..................................................................................................................................................... 12  1.6.1. @OneWay ........................................................................................................................................................... 12 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值