近六个月来,有关Web services生命周期,安全,协作,事务方面的许多标准纷纷出现。JSR已经开始用一种标准的方式来定义Web services的各个方面如何从J2EE应用服务器中得到支持。
JSR 109专门讨论本地客户端如何访问Web services,服务器生命周期和Web services的部署。JSR 104,105和106联合在一起来描速web服务安全,包括信任服务的API,数字签名和加密。JSR 156 和157定义支持Web services的事务和合作的基础,包括支持2PC (JTA) 和商业事务。本文将介绍JSR 109 的内容并考察它对Web services在J2EE环境中实现的影响。
JSR 109: Web'http://jcp.org/en/jsr/detail?id=109"Web Services 在J2EE上的实现。当前规格说明书状态:版本0.3(正式发布版本 1.0) 15-April-2002
JSR 109介绍
在过去的这些年里,J2EE成为提供web服务的主流标准。同时也出现了许多把应用端功能移植至web前端之后的标准, 其中Web services是最新的。J2EE一开始使用的是servlets,jsp和无状态会话企业Java
bean, 然后EJB规范发生了调整开始支持有状态的企业java bean, 在后来是实体bean, 最后开始支持基于消息的java bean。
毫无疑问J2EE将会继续的发展和进步。JSR 109是最新的描述扩展J2EE的规格文档之一。JSR 109 定义了J2EE应用服务器应该如何以一种标准的方式提供对Web services的部署,治理和访问的本地支持。 明确的说,JSR 109覆盖以下重要的领域:
客户端的编程模式――J2EE如何把Web services作为传统的远程对象来访问服务器端的编程模式――怎样用servlets和无状态会话EJB来实现Web services并使Web services具有和他们一样的生存周期Web services部署和部署描述器――如何在应用服务器上部署Web services
在这篇文章里,我们要考察JSR 109的许多领域来理解每个领域到底带来了什么样的好处。但是在读这篇文章的时候,你要记住规格说明文档是描述解决问题的结论。我们在研究一种技术的时候经常只是注重它能做什么而忘记它要解决的问题是什么。在我们读这篇规格说明文档的时候,我们要一直问自己“它究竟要解决什么问题?”规格说明文档描述解决问题的结论,它描述的范围不应该宽于也不应该窄于问题的范围。
首先,JSR 109 尝试定义一种实现Web services的编程模式,在这种模式下无论Web services是如何实现的,对调用端来说看起来都是一样的。因为Webservices同时被其他很多的规范所控制和定义,JSR 109不可以要求Web services在实现和部署范围以外有任何的改变。我们来简单的看看部署和部署模式。
JSR 109 尝试定义一种模拟其它J2EE编程模式的客户端编程模式;熟悉“传统”远程方法调用的开发人员会很轻易的理解JSR 109。所谓的“传统”,我们指JSR109定义了一种和其他J2EE应用一致的客户端编程模式,使用JNDI等方式来获取远程接口然后调用引用的对象。
注重:一些支持Web services的公司,比如说Sun 和 BEA,他们表示对JSR109持有保留意见。需要查看完全的描述,参考http://jcp.org/en/jsr/results?j=109&t=1&c=1"投票内容。
客户端编程模型
JSR 109客户端编程模式的目的是清楚的定义java应用如何能够像访问EJB那样访问Web service。这个问题只是许多复杂情形中的一种。其它的JSR定义和应用服务器不在一起的Webservices的访问;然而,这种方式给客户端应用带来了一定的编程复杂度。在部署Web service的应用服务器内部访问Web service我们定义为直接访问。JSR
109的客户端编程模式定义了一种简单易懂的访问本地部署的Web service的方式。
三种模式
JSR 109定义了三种客户端编程模式――用户治理端口访问模式,容器治理端口访问模式,动态端口访问模式。我们将侧重于用户治理访问模式,这种模式基于原来的WSDL为Webservice定义了一个接口。使用用户治理访问模式的时候,应用系统需要为一个特定的接口提供一个端口。容器治理端口访问模式和用户自治理模式类似,但是容器直接治理对实例的调用,而用户只是申请一个普通的可以访问不同接口的端口。
端口在了解Web service之前,我们必需先理解端口的概念。一个端口是Web service的一个实例。一个客户应用访问Web service必需通过服务接口访问服务,这时应用服务器可能启动一个已经存在的实例或者创建一个新实例来实现这个请求。熟悉EJB编程模式的读者会发现JSR109的客户端编程模式非常熟悉。
动态端口访问模式不需要事先了解WSDL的定义,调用会在端口不工作的时候发生。虽然明显看来动态端口访问模式更加强壮,但是在现实应用中动态端口访问模式并没有多大用处。在将来――当动态编程变得更加普遍的时候――这种方式也许会是非常有用的。本文的余下篇章中,我们将使用更加传统的容器治理端口访问模式,在这种模式里用户事先知道Webservice接口的定义。我们待会再解析用户治理端口访问模式和容器治理端口访问模式。
第一步:首先我们得到一个在任何JNDI客户系统中都要用到的InitialContext。(对JNDI的描速已经超出了本文的范围,有爱好的读者可以直接访问JNDI培训)当我们考察Webservices部署的时候,我们将了解访问Web service实际名称的细节;直到这个时候,我们才需要使用Web services的名称。当然,应用服务器应当保证实际的Web services已经被绑定到JNDI树上了。
例1.用户治理端口访问模式
00 InitialContent ic = new InitialContext();
01 SomeSpecificServiceInterface srv = (SomeSpecificServiceInterface)ic.lookup (java:comp/env/service/SomeSpecificServiceInterface);
02 ServiceInstance si = (SomeSpecificService)srv.getServiceInstancePort();
让我们来逐行研究这个程序片断,行00是传统的JNDI查找。行01,我们得到接口ServiceInterface的一个特定实例。所有的服务都需要实现Services接口,这个接口定义了访问服务的一些公用方法,例如返回特定实例。假如你熟悉EJB规范,你将发现Services接口和EJB本地接口有类似之处。行02,我们得到了定义了实际使用的方法的远程对象的一个实例。
当Web service的定义在开发的时候已经完全已知的情况下我们一般使用用户治理端口访问模式。假如因为某种原因应用服务器不能返回支持行01 cast操作的实例,异常将会被抛出。
例2.容器治理端口访问模式
00 InitialContent ic = new InitialContext();
01 Service srv = (Service)ic.lookup
(java:comp/env/service/SomeSpecificServiceInterface);
02 ServiceInstance si = (SomeSpecificService)srv.getPort();
例2和例1仅有很小的差别。在01我们只需要对象的一个公用接口。没有指定返回的接口名称,所以容器可以自由的返回任意的匹配被请求的JNDI名称的实例。行02也有一些差别:我们使用一个普通的getPort()调用方法而不是像我们在例1中使用的那种特定名称的getportPort调用方法。
规格说明书中声明当用户仅仅访问对象的服务定义时可以使用容器治理端口访问。行02假定客户端知道服务可能不支持的一个特定接口。假如容器不知道所需求的cast操作,异常将被抛出。更可能的是,客户端在build的时候没有一个完全的WSDL定义,因此他们不能用thegetPort()方法,但是他们会指定合适的实例类型――这种方式看起来更可行。
服务器编程模型
服务器编程模式可能是JSR109最重要的部分。理解Web service在不同的生命周期的工作方式将帮助Web service开发人员创建在不同条件下都可以按预定方式工作的Web
service。EJB规格说明书定义了不同类型EJB的生命周期。JSR 109更进了一步,它扩展了EJB模式,定义了Web services如何在Webservices容器里工作。JSR 109 关于服务器编程的定义是一个解决行为一致性的尝试。
快速背景贴士Web 应用和EJB 一般在“容器”内执行。容器提供EJB或者Web 应用运行时需要需要的所有服务。事务,JNDI,JDBC,所有类似的服务都由容可提供。一般来说,一个应用服务器里有两种容器――Web 应用容器和EJB容器。它们都提供相似的服务,比如生命周期治理,但也会有微小的差异,这个要看提供的是何种服务。Web应用容器知道如何加载servlets;EJB容器知道如何加载EJB。
在我们了解JSR 109规范内容之前,让我们先了解我们需要什么来支持Web services顺应J2EE的工作方式。首先,Web service的实现应该对客户透明。Webservice在应用服务器内实现这个事实不应该改变客户端对服务行为的熟悉。况且我们需要在很多的应用服务器里使用Web service。因此,编程模式应该是轻便强壮的,不仅支持现在的实现也要支持将来的实现。
另一点比较重要的是和现存J2EE服务的无缝整合,例如 JDBC。我们希望我们的Web services能够方便的利用J2EE现存的优势而不危及到服务自身的完整性。
有了这些目标,JSR 109定义了对Web services两个领域的支持:无状态会话bean和servlets。JSR 109一个让人失望的地方是它在没有解释的情况下忽略了消息驱动bean的定义。消息bean支持可扩展的同步消息,这是Webservices的一个重要部分。由于消息bean的行为可以被无状态bean和servlets所模拟,所以我们需要编写额外的代码。
在Web services里端口的定义十分重要,JSR 109 定义了在J2EE应用服务器里如何将端口和服务进行映射。Web service的端口在概念上类似于JVM里的实例。
WSDL: Web service的接口定义,WSDL并不是Web service的一部分,