love fish大鹏一曰同风起,扶摇直上九万里

常用链接

统计

积分与排名

friends

link

最新评论

使用EJB3.O简化EJB开发(全中文)(转)

使用EJB3.O简化EJB开发    原著:Debu Panda

我们引入EJB来构造分布式的组件。它诞生之时是为了解决所有CORBA的问题和复杂性。经历过几次重要的版本更新和增加许多特性之后,EJB已经成为了J2EE的核心。在早期,很多开发人员沉迷于EJB甚至在没有任何意义的情况下在他们的工程中使用EJB。而当他们发现所使用的工程并没有质的变化后,谴责EJB成了一种趋势。

开发EJB从来没有变得简单甚至在早期的EJB版本规范中变得更加复杂。EJB由于其的复杂性和重量级特性而被比作一只大象。学多开发人员感觉EJB象一个油炸圈饼上多余的一层甜糖浆。在现在low carb和Atkins diet大行其道的今天,EJB专家委员会也没有选择余地的发布了体现low carb的EJB规范来简化EJB的开发。EJB3.0专家委员会在2004Javaone大会上发布了称之为EJB3.0第一个公开规范的轻量级模型的范例图。

第一眼看到EJB的新模型感觉很不错。在这篇文章中我们将讨论EJB3.0如何使用一个更小而精致的装配来吸引开发者的。在接下来的文章中我们将来讨论EJB3.0是怎样简化持久性模型的。

整理缺陷

在我们开始对EJB3.0带来的新特性进行讨论之前,让我们先分析一下现在EJB模型的复杂繁琐。

  • 现在的EJB模型需要建立许多组件接口和实现许多不必要的回滚方法。
  • 组件接口需要实现 EJBObject 或者 EJBLocalObject ,并且处理许多不必要的异常。
  • EJB的部署描述复杂而容易出错。
  • 基于EJB模型的容器持久化管理的开发和管理过于复杂。许多基础的特征未考虑到,比如使用数据库序列和EJBQL定义一个主键的标准方法就非常有限。
  • EJB组件不像是面向对象的,比如在使用继承和多态时就有太多限制。
  • 一个主要的EJB的缺点是你不能脱离EJB容器测试一个EJB模型且不能在容器内调试一个EJB,这对开发者无疑是一个可怕的事情。
如果你使用EJB你需要熟悉调用和查找EJB的复杂过程。显然,你仅仅要在程序中使用EJB但你却必须知道JNDI详细的细节。

简化开发者的观点

如果你使用现有版本的EJB你会懂得开发一个如HelloWorld的简单的EJB程序是多么困难。你至少需要两个接口,一个bean类和一个部署描述文件。大多数的开发者希望知道为什么我需要所有这些。IDEs(开发环境工具)象OracleJDeveloper, EclipseXDoclet简化了开发者的做这些普通的工作开发周期,可是在EJB在你部署到所选择的容器中之前,编译类和打包部署文件依然是开发人员的工作。

EJB3.0试图从以下方面简化复杂性:

·         不必定义接口和部署的描述文件,这些可以由容器使用metadata annotations生成。

·         使用常用的Java类作为EJB的类和常用的EJB业务接口。

元数据描述(Metadata Annotations)

EJB3.0非常倚重Metadata Annotations。Metadata Annotations已经成为JSR 175标准并且将是J2SE 5.0的一部分。Annotations是一种对象变成的属性,非常类似与XDoclet。可是不像XDoclet那样需要预先编译,Annotations由Java编译器在需要编译的时候编译。(依赖于@Retention的开始时间)。在开发人员的观点,Annotations就如同一个公有的并可以作为类,域,方法,参数,本地变量,构造,枚举和包一样使用的修改量。你可以在你的Java代码中附带特殊的属性使用Annotations来生成代码,自动编写文档代码,或者提供如在运行期间增强业务层安全或特殊业务逻辑的特殊服务。J2EE1.5(5.0)的目标是简化开发人员使用Annotations因此而可能产生一套的Annotations模板。Annotations使用@来标记,如下:

  @Author("Debu Panda")

  @Bean

  public class MySessionBean

EJB3.0为了简化开发因此使用Metadata Annotations来产生许多如接口一样的人为因素和使用Annotations来替代部署描述文件。

使用 POJOs 和 POJIs

在规范条件中,JavaBeans和接口经常分别的涉及到简单Java对象(POJOs)和简单Java接口(POJIs)。这些不必要的如Home接口的人为因素已经被去掉。

开发人员必须在javax.ejb包中实现一个EJB接口(会话bean,实体bean或消息驱动bean)或者选择在bean的实现类中使用Annotation。你可以使用无状态,状态,消息驱动或者实体去注释一个bean类。例如,如果你定义一个无状态EJB作为HelloWorld,你可以如下定义EJB:

@Remote

  @Stateless public class HelloWorldBean {

 public String sayHello(String s)

  { System.out.println("Hello: "+s; }

  }

EJB的接口无论远程的还是本地的都不必再实现EJBObjectEJBLocalObject。你要么为EJB提供业务接口并且实现bean类中的接口,要么需要在部署的时候生成这些接口。虽然会话bean和消息驱动bean的接口是必须的,但是实体bean的接口是可选的。如果你没有为你的会话bean实现一个接口,那么它会自动为你生成一个。所生成的接口是本地的还是远程的取决于你在bean类中的Annotations。如果你仔细看看上面的代码范例,@Remote很明显是用来为你的HelloWorld生成一个远程接口。如果需要,你可以在你的EJB中同时生成远程和本地接口。

在上面的例子中,很明显开发人员不必再做那些如定义接口和实现回滚方法等这些普通的工作。

生成接口的名字来源于bean实现类的名字。生成接口对开发人员来说非常有用。但是我并没有看到任何如Oracle 的JDeveloper的这些IDE立即实现这种生成接口功能。

规范中没有明确EJB查找时客户端的需求是什么,也没有明确我们如何保持这些EJB需要调用的接口。基于以下几个情况下的原因我将不推荐使用生成接口:

·         生成接口的名字来源于bean的名字

·         如果你不愿意在EJB中暴露出一些方法而生成接口将默认暴露出所有的方法。

·         你需要在客户端使用接口来调用EJB.

去掉回滚方法的需求。

EJB2.1和更早版本需要实现很多即使对于每个EJB你不需要的一些生命周期的方法,如ejbPassivate, ejbActivate, ejbLoad, ejbStore等等。例如,在无状态会话bean中不需要ejbPassivate但是你还是得实现它的方法。现在EJB3.0中类似的常用Java类实现这些生命周期的方法都变成为可选择的。如果你在EJB中实现任何回滚容器都会调用这些方法。

唯一的异常是在你可以使用Removeannotations时一个状态会话bean的业务方法的ejbRemove方法是状态会话bean。如果你使用这个annotations它将在完成annotations方法后(无论正常或非正常)提示容器移除状态会话bean实例。例如,你可以指定以下的方式去在checkOut方法执行后移除一个状态会话bean实例。

@Stateful public class Cart {

...

...

@Remove public void checkOut() {

...

}

}

Annotations与部署描述的比较

在前面我们讨论到EJB中不再需要部署描述而由annotations代替。每个部署描述的属性都将被选择一个默认值,而开发人员在直到他们想改变这些属性的默认值之前不必为这些属性指定值。这些也能用来为bean的类自身指定使用的annotations。EJB3.0规范为开发人员使用bean类型,接口类型,资源引用,事务属性,安全等等定义了一组metadata annotations。例如,如果我们可以如下为一个特殊的EJB定义使用资源引用:

@Resource(name="jdbc/OracleDS", resourceType="javax.sql.DataSource")

J2EE的提供商如Oracle, BEA, IBM将增加属性annotations在他们指定的部署描述中,开发人员将可以使用这些annotations去避免使用部署描述。这看起来对开发人员十分具有吸引力,特别对XML描述是已经感到厌恶的开发人员,他们早就恨透并想脱离老的那种描述方式,但依然有一些问题使得我们在正式使用annotations时需要谨慎对待。

  • 它违背了我们轻便应用程序的目标,因为如果一个EJB如果使用一个提供商指定的部署描述,在重新编译或打包EJB的时候它必须多次改变。
  • 部署描述对EJB模板提供了全局观点使得组装和部署的时候不必考虑单独的EJB,他们将每个部署需求拧在一起,并且在部署完成之前描述是无效或者不可自动生成的。这对部署员来说是个可怕的事情。
  • 部署描述在EJB模板中被相关工具用来定义EJBs,当你试图整合一个和另一个容器的时候非常有用。EJB3.0规格同样主张在部署描述中使用重载annotations的方式。可是在规范里并没有提到重载annotations的细节。

无疑摆脱部署描述将使得新的开发者开发更加容易,但是如果使用不当这也将造成管理上的可怕问题。

简化持久化容器管理

CMP实体bean将成为EJB3.0使得开发人员强制使用的一个主要的检查方式。持久化框架象如OracleAS TopLink, 开源的Hibernate已经成为不像实体bean本质上的复杂和重量级的开发J2EE持久化框架应用的被大家喜爱的方式。 EJB3.0采纳了如TopLinkHibernate轻量级的持久化模式来简化容器持久化管理,这些听起来更让开发人员们欣喜。让我们简单的浏览一下实体bean的计划,我们将在另外的文章中讨论持久化改进的细节。

实体bean作为POJOs已经改头换面,实体bean将不在需要组件接口。实体bean现在看起来是支持继承和多态的纯粹的对象。

下面的是关于实体bean源代码

@Entity public class Employee{

  private Long empNo;

  private String empName;

  private Address address;

  private Hashmap projects = new Hashmap();

  private Double salary;

  @Id(generate=SEQUENCE) public Long getEmpNo() {

  return empNo;

  }

  protected void setEmpNo(Long empNo) {

  this.empNo = empNo;

  }

  public String getEmpName() {

  return EmpName;

  }

  public void setEmpName(String EmpName){

  this.EmpName = EmpName;

  }

  @Dependent public Address getAddress() {

  return address;

  }

  public void setAddress(Address address) {

  this.address = address;

  }

  public Set getProjects() {

  return projects;

  }

  public void setProjects(Set projects) {

  this.projects = projects;

  }

  public Double getSalary() {

  return salary;

  }

  public void setSalary(Double salary) {

  this.salary = salary;

  }

  ....

  }

如果你仔细看这些代码,你可以发现在现在的实体beanbean类是一个具体的类而不再是一个抽象类。

EJB QL和实体beanSQL查询做了多项改进。类似于Hibernate的新的实体管理API和简化版的TopLink的会话API被建议用来处理实体bean的操作,也就是实体bean的创建,释放,查找。

我们将在深入的文章中进一步对建议CMP实体bean的细节做更多的验证。

简化EJB客户端

即使应用中EJB是序列化的,使用EJB也就是寻找和调用也是非常复杂的。J2EE 1.4 EJB 3.0规范致力于简化EJB客户端。

如果目前你希望使用EJB你必须在部署描述中定义EJB引用或者EJB本地引用,寻找到EJB然后调用。如果我们希望调用HelloWorld EJB,你可以按照下面的简单方法调用EJB使用已存在的实现。

如下在部署描述中找到EJB指示的定义

<ejb-ref>

  <ejb-ref-name>HelloWorldEJB</ejb-ref-name>

  <ejb-ref-type>Session</ejb-ref-type>

  <home>hello.HelloWorldHome</home>

  <remote> hello.HelloWorld</remote>

  </ejb-ref>

然后按照如下方法寻找EJB.你需要明确处理EJB查找和建立一个bean实例时的异常。

try

  {

    Context context = new InitialContext();

               HelloWorldHome helloHome =

                 (HelloWorld)PortableRemoteObject.narrow(context.lookup

     ("java:comp/env/ejb/HelloWorldEJB"), HelloWorldHome.class);

               HelloWorld hello = helloHome.create();

                 ....

   }

    catch(RemoteException e)

               {

                 System.err.println("System/communication error: " + e.getMessage());

               }

               catch(NamingException e)

               {

                 System.err.println("Communication error: " + e.getMessage());

               }

               catch(CreateException e)

               {

                 System.err.println("Error creating EJB instance: " + e.getMessage());

               }

如一个环境变量的变化一样,EJB3.0建议使用安放injection的方法查找和调用EJB.

下面我们使用安放injection的方法在另一个EJB查找HelloWorldEJB

@Inject private void setSessionContext(SessionContext ctx)

  {

  this.ctx = ctx

  }

  ...

  myHello = (HelloWorld)ctx.lookup("java:comp/env/ejb/HelloWorldEJB");

如果你仔细查看上面的代码,它依赖的injection使用@Injectset来的指定对SessionContext方法的annotationsinjection 方法将可以在业务方法被EJB调用前被容器调用来设定EJBContext

另一个injected HelloWorld会话bean的直接的范例可以简化为使用

@EJB public HelloWorld myHello,这将使得myHelloHelloWorld bean的实例injected

你可以使用依赖的injection来查询任何类型的环境和资源参考如DataSource, JMS, Mail, Web Service等等。

容器外部测试可行性

一个现在EJB开发者所关注的不仅仅是EJB开发的复杂,也包括了测试的可怕之处。开发和测试EJB必须需要一个EJB容器并且开发人员必须熟悉最终部署平台才可以执行测试。这对于许多只在一个主要平台开发的企业开发人员来说不是主要问题,但是对于支持多个开发商平台并且要在维护的多个环境中测试EJBISV们来说是个大问题。EJB3.0规范承诺将提供在容器外测试的功能,但是这点在这次的规范中遗漏掉了。

结论

虽然还有很多关于打包,装配和重要的API细节没有在这个规范中提及,但是诸多的建议使得EJB3.0规范让企业级Java开发人员看起来是恨有前途的。通过这些无疑是从开发人员到服务供应商都将帮助减少开发的复杂性。下面就要看服务提供商们怎么实现,并使得EJB3.0成为企业级应用一个引人瞩目的选择。

Author Bio 作者自述

Debu PandaOracle应用服务开发小组的主要管理者,他的在EJB容器和事务管理上取得过很多成就。他已经有13年的IT产业的经验并在多家杂志和技术出版社刊登过很多著作。

 

翻译问题:

由于部分英文名词未敢枉自翻译,所以留英文原词在文中

Cleaning up the Dirty Laundry       整理缺陷

low carb

Atkins diet

metadata annotations                    元数据描述

Simplifying Client View for EJBs   简化EJB客户端

dependency injection                    依赖型injection

setter injection                             安放injection

ISV Independent software vendor 独立软件供应商

posted on 2006-06-30 11:49 liaojiyong 阅读(494) 评论(0)  编辑  收藏 所属分类: EJB


只有注册用户登录后才能发表评论。


网站导航: