posts - 51, comments - 17, trackbacks - 0, articles - 9
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

引言

  期待已久的EJB3.0规范在最近发布了它的初稿。在本文中将对新的规范进行一个概要性的介绍,包括新增的元数据支持,EJBQL的修改,实体Bean模型访问bean上下文的新方法和运行时环境等等。作者还讨论了EJB在未来要作出的调整以及EJB3.0与其他开发规范之间的关系。

  开始

  无论如何由于EJB的复杂性使之在J2EE架构中的表现一直不是很好。EJB大概是J2EE架构中唯一一个没有兑现其能够简单开发并提高生产力的组建。 EJB3.0规范正尝试在这方面作出努力以减轻其开发的复杂性。EJB3.0减轻了开发人员进行底层开发的工作量,它取消或最小化了很多(以前这些是必须实现)回调方法的实现,并且降低了实体Bean及O/R映射模型的复杂性。

  在本文中,我首先会介绍EJB3.0中几个主要的改变。它对进一步深入了解EJB3.0是非常重要的。随后,我会从更高的层面来描述已经被提交到EJB3.0规范中的细节,并一个个的讲解新的规范中的改变:实体 Bean,O/R映射模型,实体关系模型和EJB QL(EJB查询语言)等等。

  背景

  EJB3.0中两个重要的变更分别是:使用了Java5中的程序注释工具和基于Hibernate的O/R映射模型。

  Java5中的元数据工具。

  Java5 (以前叫J2SE1.5或Tiger)中加入了一种新的程序注释工具。通过这个工具你可以自定义注释标记,通过这些自定义标记来注释字段、方法、类等等。这些注释并不会影响程序的语义,但是可以通过工具(编译时或运行时)来解释这些标记并产生附加的内容(比如部署描述文件),或者强制某些必须的运行时行为(比如EJB组件的状态特性)。注释的解析可以通过源文件的解析(比如编译器或这IDE工具)或者使用Java5中的APIs反射机制。注释只能被定义在源代码层。由于所有被提交到EJB3.0草案中的注释标记都有一个运行时的RetentionPolicy,因此会增加类文件占用的存储空间,但这却给容器制造商和工具制造商带来了方便。

  Hibernate

  目前Hibernate非常受欢迎,它是开发源代码的Java O/R映射框架,目的是把开发人员从繁琐的数据持久化编程中解脱出来。它也有一个标准的HQL(Hibernate 查询语言)语言,你可以在新的EJB QL中看到它的影子。Hibernate在处理如数据查询、更新、连接池、事务处理、实体关系处理等方面非常简单。

  概览

  在已经提交的EJB3.0规范中主要涉及两个方面的改变:

  1. 一套以注释为基础的EJB编程模型,再加上EJB2.1中定义的通过部署描述符和几个接口定义的应用程序行为。

  2. 新的实体Bean持久化模型,EJBQL也有许多重要的改变。

  还有一些有关上述的提议,比如:一个新的客户端编程模型,业务接口的使用以及实体Bean的生命周期。请注意EJB2.1编程模型(包括部署描述符和home/remote接口)仍然是有效的。新的简化模型并没有完全取代EJB2.1模型。

  EJB注释

  EJB 规范组织一个重要的目标是减轻原始代码的数量,并且他们为此给出了一个完美而简介的办法。在EJB3.0的里,任何类型的企业级Bean只是一个加了适当注释的简单Java对象(POJO)。注释可以用于定义bean的业务接口、O/R映射信息、资源引用信息,效果与在EJB2.1中定义部署描述符和接口是一样的。在EJB3.0中部署描述符不再是必须的了;home接口也没有了,你也不必实现业务接口(容器可以为你完成这些事情)。

  比如,你可以使用@Stateless注释标记类把Java类声明为一个无状态回话bean。对于有状态回话bean来说,@Remove注释可以用来标记一个特定的方法,通过这个注释来说明在调用这个方法之后bean的实例将被清除掉。

  为了减少描述组件的说明信息,规范组织还采纳了由异常进行配置(configuration-by-exception)的手段,意思是你可以为所有的注释提供一个明确的缺省值,这样多数常规信息就可以据此推断得出。

  新的持久化模型

  新的实体bean也是一个加了注释的简单Java对象(POJO)。一旦它被EntityManager访问它就成为了一个持久化对象,并且成为了持久化上下文(context)的一部分。一个持久化上下文与一个事务上下文是松耦合的;严格的讲,它隐含的与一个事务会话共存。

  实体关系也是通过注释来定义的,O/R映射也是,并提供几种不同的数据库规范操作,在EJB2.1中这些要通过开发人员自己的设计模式或者其它技术来完成的(比如,自增长主键策略)。

  深入研究

  现在是时候详细了解EJB3.0草案了。让我们开始探讨所有EJB中四种企业级bean,并看看他们在新的规范中是什么样子。

  无状态回话bean

  在EJB3.0规范中,写一个无状态回话bean(SLSB)只需要一个简单的Java文件并在类层加上@Stateless注释就可以了。这个bean可以扩展javax.ejb.SessionBean接口,但这些不是必须的。

  一个SLSB不再需要home接口,没有哪类EJB再需要它了。Bean类可以实现业务接口也可以不实现它。如果没有实现任何业务接口,业务接口会由任意 public的方法产生。如果只有几个业务方法会被暴露在业务接口中,这些方法可以使用@BusinessMethod注释。缺省情况下所有产生的接口都是local(本地)接口,你也可以使用@Remote注释来声明这个接口为remote(远程)接口。

  下面的几行代码就可以定义一个HelloWorldbean了。而在EJB2.1中同样的bean至少需要两个接口,一个实现类和几个空的实现方法,再加上部署描述符。

import javax.ejb.*;

/**
* A stateless session bean requesting that a remote business
* interface be generated for it.
*/
@Stateless
@Remote
public class HelloWorldBean {
public String sayHello() {
return "Hello World!!!";
}
}

  有状态回话bean

  除了几个SFSB的特别说明之外,有状态回话bean(SFSB)和SLSB一样精简:

  ·一个SFSB应该有一个方法来初始化自己(在EJB2.1中是通过ejbCreate()来实现的)。在EJB3.0的规范中建议这些初始化操作可以通过自定义方法完成,并把他们暴露在业务接口中。在使用这个bean之前由客户端来调用相应的初始化方法。目前规范组织就是否提供一个注释来标记某个方法用于初始化还存在争议。

  ·Bean的提供者可以用@Remove注释来标记任何SFSB的方法,以说明这个方法被调用之后bean的实例将被移除。同样,规范组织仍然在讨论是否要有一种机制来处理这种特殊的情况,即当这个方法出现异常的情况下bean的实例是否被移除。

  下面是对以上问题我个人的观点:

  ·是否应该有一个注释来标明一个方法进行初始化呢?我的观点是——应该有,这样容器就可以在调用其他方法之前至少调用一个方法来进行初始化。这不仅可以避免不必要的错误(由于没有调用初始化方法)而且可以使容器更明确的判断是否可以重用SFSB实例。我暂且把这个问题放一放,规范组织只考虑为一个方法提供一个注释来声明它是一个初始化方法。

  ·对于第二个问题我的观点也是肯定的。这有利于Bean的提供者合客户端程序对其进行控制。只有一个遗留的问题:那就是一旦调用这个方法失败,是否能移除这个bean 的实例?答案是不能,但是它将会在回话结束的时候被移除。
消息驱动Bean

  消息驱动Bean是唯一一种必须实现一个业务接口的Bean。这个接口指出bean支持的是哪一种消息系统。对于以JMS为基础的MDB来说,这个接口是 javax.jms.MessageListener。注意MDB业务接口不是一个真正意义上的业务接口,它只是一个消息接口。

  实体Bean

  ·实体Bean使用@Entity注释来标记,所有实体bean中的属性/字段不必使用@Transient注释来标记。实体bean的持久化字段可以通过JavaBean-style机制或者声明为public/protected字段来实现。

  ·实体bean可以使用助手类来描述其状态,但是这些类的实例并没有持久化唯一性(persistent identity)的特性(即,唯一标识这个bean的字段等),实际上这些助手类与他们的实体bean实例是紧密结合的;并且这些对象还是以非共享方式来访问实体对象的。

  实体关联

  EJB3.0同时支持Bean之间双向的合单向的关联,它们可以是一对一、一对多、多对一或者是多对多的关联。然而双向关联的两端还要分为自身端(owning side)和对方端(inverse side)不同的端。自身端负责向数据库通告关联的变更。对于多对多的关联自身端必须明确的声明。实际上对方端通过isInverse=true进行注释(由此自身端就不必说明了而是由另一段推断出)。看来上面的描述,规范组织还能说让EJB变的简单了吗?

  O/R映射

  EJB3.0 中的O/R映射模型也有了重要的改变,它从原来的abstract-persistence-schema-based变成了现在的Hibernate- inspired模式。尽管目前规范组织还在就此进行讨论但是一个明确的模型将会出现在下一个版本的草案中。

  举例来说,O/R映射模型将通过bean类中的注释来声明。而且此方法还会指出对应的具体表和字段。O/R映射模型提供了一套自有的SQL;而且除了提供一些基本的SQL外还支持某些高层开发的功能。比如,有一个通过@Column注释声明的字段columnDefinition,那么可以写这样的SQL: columnDefinition="BLOB NOT NULL"

  客户端程序模型

  一个EJB客户端可以通过 @Inject注释以一种“注入”的方式获得一个bean的业务接口引用。你也可以使用另一个注释 @javax.ejb.EJBContext.lookup()来完成上面的操作,但是规范中没有告诉我们一个普通的Java客户端怎样获得一个Bean 的实例,因为这个普通的Java客户端是运行在一个客户端容器中,它无法访问@javax.ejb.EJBContex对象。现在还有另外一种机制来完成上面的工作那就是使用一个超级上下文环境对象:@javax.ejb.Context()。但是规范中没有指出该如何在客户端中使用这个对象。

  EJB QL

  EJB QL可以通过@NamedQuery来注释。这个注释有两个成员属性分别是name和queryString.一旦定义了这些属性,就可以通过 EntityManager.createNamedQuery(name)来指向这个查询。你也可以创建一个标准的JDBC风格的查询并使用 EntityManager.createQuery(ejbqlString)或EntityManager.createNativeQuery (nativeSqlString)(这个方法用于执行一个本地查询)来执行查询。

  EJB QL有两个地方可以定义其参数。javax.ejb.Query接口提供了定义参数、指向查询、更新数据等等方法。下面是一个EJBQL指向查询的例子:

.. ..
@NamedQuery(
name="findAllCustomersWithName",
queryString="SELECT c FROM Customer c WHERE c.name LIKE :custName"
)
.. ..
@Inject public EntityManager em;
customers = em.createNamedQuery("findAllCustomersWithName")
.setParameter("custName", "Smith")
.listResults();

  下面列出了一些EJB QL的增强特性:

  ·支持批量更新和删除。

  ·直接支持内连接和外连接。FETCH JOIN运行你指出关联的实体,Order可以指定只查询某个字段。

  ·查询语句可以返回一个以上的结果值。实际上,你可以返回一个依赖的类比如下面这样:

SELECT new CustomerDetails(c.id, c.status, o.count)
FROM Customer c JOIN c.orders o
WHERE o.count > 100

  ·支持group by 和having。

  ·支持where子句的嵌套子查询。

  在提交的EJB3.0草案中,EJB QL与标准SQL非常的接近。实际上规范中甚至直接支持本地的SQL(就像我们上面提到的那样)。这一点对某些程序员来说也许有些不是很清楚,我们将在下面进行更详细的讲解。

  多样性

  方法许可(Method permissions)可以通过@MethodPermissions或@Unchecked注释来声明;同样的,事务属性也可以通过 @TransactionAttribute注释来声明。规范中仍然保留资源引用和资源环境引用。这些一样可以通过注释来声明,但是有一些细微的差别。比如,上下文(context)环境要通过注入工具控制。容器根据bean对外部环境引用自动初始化一个适当的已经声明的实例变量。比如,你可以象下面这样获得一个数据源(DataSource):

@Resource(name="myDataSource") //Type is inferred from variable
public DataSource customerDB;

  在上面的例子中如果你不指定引用资源的名称(name)那么其中的customerDB会被认为是默认值。当所有的引用属性都可得到时,@Injec注释就可以这样写:

@Inject public DataSource customerDB;

  容器负责在运行时初始化customerDB数据源实例。部署人员必须在此之前在容器中定义好这些资源属性。

  更好的消息是:那些以前必须检测的异常将一去不复返。你可以声明任意的应用程序异常,而不必在再抛出或捕获其他类似CreateException和 FinderException这样的异常。容器会抛出封装在javax.ejb.EJBException中的系统级异常或者只在必要时候抛出 IllegalArgumentException或IllegalStateException异常。
 EJB文件处理模式

  在我们结束本节之前,让我的快速的浏览一下容器提供商在EJB处理模式方面可能的变更。规范中对此并没有明确的表态,但我可以想到至少两种模式。

  ·一种办法是首先利用EJB文件生成类似于EJB2.1部署模式的文件(包括必要的接口和部署描述符)然后再用类似于EJB2.1的方式来部署这个EJB组件。当然,这样产生的部署描述符可能并不标准但是它可以解决同一个容器对EJB2.1和EJB3.0兼容的问题。

  ·另一种方法是一种类似于JSP托放的部署模式。你可以把一个EJB文件放到一个预先定义的目录下,然后容器会识别这个EJB并处理它,然后部署并使之可以使用。这种方法可以建立于上面那种方法之上,在支持反复部署时有很大的帮助。考虑到部署的简单性也是EJB3.0规范的目的之一,我真诚的希望在下一个草案出来时能够确定一个模式(至少能有一个非正式的)。

  你有什么想法

  EJB3.0规范的制定正在有序的进行,为了使 EJB的开发变得更加容易,EJB规范组织作出的努力是有目共睹的。就像他们说的那样,一切对会变得简单,但做到这一点并不容易。目前已经定义了50个注释标记(还有几个将在下一个草案中发布),每一个都有自己的缺省规则和其他的操作。当然,我真的不希望EJB3.0变成EJB2.1的一个翻版"EJB 3.0 = EJB 2.1 for dummies"(希望这个等式不要成立)。最后,我还是忍不住要提一些我自己的观点:

  ·首先,规范确实使反复部署变得容易了,并且有一个简单的模式来访问运行时环境。我还是觉得home接口应该放弃。

  ·在早期的EJB规范中,实体bean用于映射一个持久化存储。理论上(也许只是理论上)可能需要把实体bean映射到一个遗留的EIS (enterprise information system)系统中。出于将来扩展的考虑这样作是有好处的,并且可以使更多的业务数据模型采用实体bean。也因此其伴随的复杂性使得实体bean不被看好。在本次提交的草案中,一个实体bean只是一个数据库的映射。并且是基于非抽象持久化模式和简单的数据访问模式的更加简单开发。

  ·我对模型变更持保留态度,我认为在EJB中包含SQL脚本片断并不是个好注意。一些开发人员完全反对包含某些“SQL片段(SQLness)”(比如 @Table 和 @Column注释)。我的观点是这些SQLness是好的,据此我们可以清楚的知道我们到底要数据库作些什么。但是某些SQL段我看来并不是很好,比如 columnDefinition="BLOB NOT NULL",这使得EJB代码和SQL之间的耦合太过紧密了。

  ·尽管对于本地SQL的支持看似很诱人,其实在EJB代码中嵌入SQL是一个非常糟糕的主意。当然,有些办法可以避免在EJB中硬编码SQL,但是这应该在规范中说明,而不能是某些开发人员自己定义的模式。

  ·假设@Table注释只用于类。在运行时通过@Table注释的name属性定义的表名称将必须对应一个实际的数据库表。规范对此应该给予清楚的说明和一致的模式。

  ·规范还需要更清楚的说明客户端编程模型,尤其是普通java客户端。规范中所有的参考都假设或者隐含的使用EJB客户端。而且规范中对客户端的向后兼容方面也没有给出明确的说法。

  ·Transient注释应该重新命名以避免和已有的transient关键字发生冲突。事实上,在这一点上我们更乐于稍微的背离一下 configuration-by-exception原则并且定义一个@Persistent注释来明确的定义持久化字段。@Persistent注释可以仅仅是一个标记注释或者它可以有几个属性来关联O/R映射注释。

  与其他规范的关联

  目前可能影响到EJB3.0的JSR有JSR175(java语言元数据工具)和JSR181(Java Web服务元数据)

  JSR175已经初步完成并且不会和EJB3.0有太大的冲突;但是JSR181与EJB3.0有两个关联的地方:

  ·Web service接口:EJB规范将采用一种机制适应JSR181以便可以把一个bean实现为一个Web service并告诉Web service如何被客户端调用。

  ·JSR 181计划采用不同的机制来处理安全问题。在早期的规范中EJB建议使用一个一致的机制(MethodPermissions),但是JSR 181计划使用一个稍微不同的方式(SecurityRoles和SecurityIdentity注释)。同样的RunAs注释的定义也存在这些许差别。这一问题还在解决中最终会在J2EE层的规范中维持其一致性。

  在J2EE 1.5中的一些开发规范可能与EJB3.0有关联。除了上面说到的几个关联之外现在没有其他的开发规范与EJB3.0有冲突。

  结束语

  在使EJB的开发变得简单高效之前,我们还有很长一段路要走。规范组织在降低EJB的开发难度方面起了个好头。O/R映射模型的提议还处在早期阶段,规范组织正在完善它。我希望它不要太复杂也不要与SQL过分的耦合。让我们不要只是停留在期望、希望、思考和请求中:提出你的想法并把你的建议发送给规范组织 ejb3-feedback@sun.com。JCP并不是很民主的组织,但是你的建议一定是有价值的。

posted @ 2007-03-03 11:12 chenweicai 阅读(153) | 评论 (0)编辑 收藏

1、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别?

  答:规范内容包括Bean提供者,应用程序装配者,EJB容器,EJB配置工具,EJB服务提供者,系统管理员。这里面,EJB容器是EJB之所以能够运行的核心。EJB容器管理着EJB的创建,撤消,激活,去活,与数据库的连接等等重要的核心工作。JSP,Servlet,EJB,JNDI,JDBC,JMS.....

  2、EJB与JAVA BEAN的区别?

  答:Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地进程内COM组件,它是不能被跨进程访问的。Enterprise Java Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。

  2、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。

  答:EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技术实现。

  SessionBean在J2EE应用程序中被用来完成一些服务器端的业务操作,例如访问数据库、调用其他EJB组件。EntityBean被用来代表应用系统中用到的数据。

  对于客户机,SessionBean是一种非持久性对象,它实现某些在服务器上运行的业务逻辑。

  对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实现的实体。

  Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会有一个相对应的 Stateful Session Bean 的实体。Stateless Session Bean 虽然也是逻辑组件,但是他却不负责记录使用者状态,也就是说当使用者呼叫 Stateless Session Bean 的时候,EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method。换言之,很可能数个使用者在执行某个 Stateless Session Bean 的 methods 时,会是同一个 Bean 的 Instance 在执行。从内存方面来看, Stateful Session Bean 与 Stateless Session Bean 比较, Stateful Session Bean 会消耗 J2EE Server 较多的内存,然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。

  3、EJB与JAVA BEAN的区别?

  答:Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地进程内COM组件,它是不能被跨进程访问的。Enterprise Java Bean 相当于DCOM,即分布式组件。它是基于Java的远程方法调用(RMI)技术的,所以EJB可以被远程访问(跨进程、跨计算机)。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中,EJB客户从不直接访问真正的EJB组件,而是通过其容器访问。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。

  EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的?

  SessionBean:Stateless Session Bean 的生命周期是由容器决定的,当客户机发出请求要建立一个Bean的实例时,EJB容器不一定要创建一个新的Bean的实例供客户机调用,而是随便找一个现有的实例提供给客户机。当客户机第一次调用一个Stateful Session Bean 时,容器必须立即在服务器中创建一个新的Bean实例,并关联到客户机上,以后此客户机调用Stateful Session Bean 的方法时容器会把调用分派到与此客户机相关联的Bean实例。

  EntityBean:Entity Beans能存活相对较长的时间,并且状态是持续的。只要数据库中的数据存在,Entity beans就一直存活。而不是按照应用程序或者服务进程来说的。即使EJB容器崩溃了,Entity beans也是存活的。Entity Beans生命周期能够被容器或者 Beans自己管理。

  EJB通过以下技术管理实务:对象管理组织(OMG)的对象实务服务(OTS),Sun Microsystems的Transaction Service(JTS)、Java Transaction API(JTA),开发组(X/Open)的XA接口。

  4、EJB的角色和三个对象

  答:一个完整的基于EJB的分布式计算结构由六个角色组成,这六个角色可以由不同的开发商提供,每个角色所作的工作必须遵循Sun公司提供的EJB规范,以保证彼此之间的兼容性。这六个角色分别是EJB组件开发者(Enterprise Bean Provider) 、应用组合者(Application Assembler)、部署者(Deployer)、EJB 服务器提供者(EJB Server Provider)、EJB 容器提供者(EJB Container Provider)、系统管理员(System Administrator)

  三个对象是Remote(Local)接口、Home(LocalHome)接口,Bean类
5、EJB容器提供的服务

  答:主要提供声明周期管理、代码产生、持续性管理、安全、事务管理、锁和并发行管理等服务。

  6、EJB规范规定EJB中禁止的操作有哪些?

  答:1.不能操作线程和线程API(线程API指非线程对象的方法如notify,wait等),2.不能操作awt,3.不能实现服务器功能,4.不能对静态属生存取,5.不能使用IO操作直接存取文件系统,6.不能加载本地库.,7.不能将this作为变量和返回,8.不能循环调用。

  7、remote接口和home接口主要作用

  答:remote接口定义了业务方法,用于EJB客户端调用业务方法。

  home接口是EJB工厂用于创建和移除查找EJB实例

  8、bean 实例的生命周期

  答:对于Stateless Session Bean、Entity Bean、Message Driven Bean一般存在缓冲池管理,而对于Entity Bean和Statefull Session Bean存在Cache管理,通常包含创建实例,设置上下文、创建EJB Object(create)、业务方法调用、remove等过程,对于存在缓冲池管理的Bean,在create之后实例并不从内存清除,而是采用缓冲池调度机制不断重用实例,而对于存在Cache管理的Bean则通过激活和去激活机制保持Bean的状态并限制内存中实例数量。

  9、EJB的激活机制

  答:以Stateful Session Bean 为例:其Cache大小决定了内存中可以同时存在的Bean实例的数量,根据MRU或NRU算法,实例在激活和去激活状态之间迁移,激活机制是当客户端调用某个EJB实例业务方法时,如果对应EJB Object发现自己没有绑定对应的Bean实例则从其去激活Bean存储中(通过序列化机制存储实例)回复(激活)此实例。状态变迁前会调用对应的ejbActive和ejbPassivate方法。

  10、EJB的几种类型

  答:会话(Session)Bean ,实体(Entity)Bean 消息驱动的(Message Driven)Bean

  会话Bean又可分为有状态(Stateful)和无状态(Stateless)两种

  实体Bean可分为Bean管理的持续性(BMP)和容器管理的持续性(CMP)两种

  11、客服端调用EJB对象的几个基本步骤

  答:设置JNDI服务工厂以及JNDI服务地址系统属性,查找Home接口,从Home接口调用Create方法创建Remote接口,通过Remote接口调用其业务方法

posted @ 2007-03-03 10:37 chenweicai 阅读(154) | 评论 (0)编辑 收藏

JBoss,作为J2EE应用服务器,以其EJB容器卓越的性能、技术的潮流性、开发部署J2EE应用的方便性赢得了很多J2EE开发者的信赖。其中,免安装、基于JMX构架、热部署(Hot Deploy)、快速开发EJB应用等几项特征与其他商用服务器相比,显得有些得意忘形的样子。尽管其本身没有重大的缺陷,但毕竟是Open Source的开发模式,文档很少,因此要很好的掌握、精通开发基于JBoss的应用还是显得有些力不从心。
本文结合自己的开发经验,给出在JBoss 3.2.1下开发J2EE一些相关的注意事项和规则。其中,读者一定要知道JBoss 3.2.1作为JBoss的过渡产品(与JBoss 3.0.x、JBoss 4.x相比),自然有些东西和JBoss 3.0.x、JBoss 4.x有很大差别。但是,一般情况下,本文介绍的内容,大体上都适合JBoss各个版本。
下载完JBoss 3.2.1后,解压到一个没有空格的目录路径下面就可以运行JBoss,所以很方便,但前提是目标机器安装了Java 2 Standard Edition。一切就绪后,开始我们的旅程。
(假设JBoss 3.2.1安装在:C:\jboss-3.2.1_tomcat-4.1.24,本使用default配置)
一,    相关配置文件的设置
为开发J2EE应用,操作数据库成了必不可少的内容;调节日志输出的详细程度成了调试J2EE应用的关键;EJB应用的调优过程是J2EE应用的核心。等等,这些内容都是我们需要知道的。

(1)数据源的配置:

在JBoss 3.2.1中,配置数据源的步骤很简单,JBoss 3.2.1本身带了主流数据库的配置实例,于目录下:C:\jboss-3.2.1_tomcat-4.1.24\docs\examples\jca。具体使用那个配置文件取决于目标用户的数据库。如果是SQL Server 2000,则需要使用mssql-ds.xml文件(支持本地事务)或者mssql-xa-ds.xml文件(支持全局事务);如果是Oracle 9i数据库,则需要使用oracle-ds.xml文件或者oracle-xa-ds.xml文件。等等。这里以SQL Server 2000为例。
首先将mssql-ds.xml文件拷贝到目录:C:\jboss-3.2.1_tomcat-4.1.24\server\default\deploy下。然后打开文件,并作如下修改:
<datasources>
    <local-tx-datasource>
        <jndi-name>VSSDB</jndi-name>
        <connection-url>jdbc:microsoft:sqlserver://125.16.45.158:1433;DatabaseName=DDD
</connection-url>
        <driver-class>com.microsoft.jdbc.sqlserver.SQLServerDriver</driver-class>
        <user-name>sa</user-name>
        <password>sa</password>
        <min-pool-size>50</min-pool-size>
        <max-pool-size>200</max-pool-size>
    </local-tx-datasource>
</datasources>
如果目标J2EE应用只需要本地事务,则上述过程已经完成了Datasource的配置,同时这个配置将用于JDBC以及EJB通过JNDI使用。如果要实现EJB使用Datasource,则还需要修改位于目录:C:\jboss-3.2.1_tomcat-4.1.24\server\default\conf下的standardjbosscmp-jdbc.xml文件。比如,
<jbosscmp-jdbc>

   <defaults>
      <datasource>java:/VSSDB1</datasource>
      <datasource-mapping>MS SQLSERVER2000</datasource-mapping>

      <create-table>true</create-table>
      <remove-table>false</remove-table>
      <read-only>false</read-only>
      <time-out>300</time-out>
      <pk-constraint>true</pk-constraint>
      <fk-constraint>false</fk-constraint>
。。。。。。。。
其中,<datasource>java:/VSSDB</datasource>中的VSSDB就是mssql-ds.xml配置的数据源;而“java:/”前缀表明该命名空间只是对JBoss本身可见,即运行于JBoss外的应用是不能够使用这里定义的数据源,这一点希望读者注意。
其次,<datasource-mapping>MS SQLSERVER2000</datasource-mapping>中的MS SQLSERVER2000可以在该文件的其他地方找到。(如果是其他数据库,情况都是类似的,希望读者加以思考!)

(2)日志的输出详细程度配置:
    
由于JBoss 3.2.1开发采用了Log4j管理其日志信息(严格地讲,它扩展了Log4j),因此了解Log4j的机理,有助于理解JBoss 3.2.1管理日志的方式。
JBoss 3.2.1采用JMX架构的同时,且以.xml文件类型为配置文件,因此可以找到位于目录:C:\jboss-3.2.1_tomcat-4.1.24\server\default\conf下的log4j.xml文件。比如,其中一段配置示例如下:
      <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out"/>
    <param name="Threshold" value="INFO"/>

    <layout class="org.apache.log4j.PatternLayout">
      <!-- The default pattern: Date Priority [Category] Message\n -->
      <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
    </layout>
  </appender>
比如,为了调节JBoss 3.2.1控制台日志输出的详细程度(调整为DEBUG级别),我们需要修改value=”INFO”,将INFO改为DEBUG。
如果目标读者在开发Entity Beans,可以调节位于与log4j.xml文件同一目录下的standardjboss.xml文件(该文件主要是提供修改EJB相关的调试、运行、调优、部署参数)。如果目标读者Entity Beans采用的<container-name>为Standard CMP 2.x EntityBean,则将其中的<call-logging>属性的取值改为true。
<container-configuration>
        <container-name>Standard CMP 2.x EntityBean</container-name>
        <call-logging>false</call-logging>
<invoker-proxy-binding-name>entity-rmi-invoker</invoker-proxy-binding-name>
        <sync-on-commit-only>false</sync-on-commit-only>
。。。。。。。。。
完成上述两步后,读者在调试Entity Beans时通过控制台,可以看到Entity Beans发出的JDBC调用细节。

(3)Tomcat容器相关参数的配置:

如果目标读者使用JBoss 3.2.1与Tomcat 4.1.24的集成版本,则可以通过调节分别位于目录:C:\jboss-3.2.1_tomcat-4.1.24\server\default\deploy\jbossweb-tomcat.sar下的web.xml和目录:C:\jboss-3.2.1_tomcat-4.1.24\server\default\deploy\jbossweb-tomcat.sar\META-INF下的jboss-service.xml文件来达到目标读者特定需求。
比如,如果想将HTTP服务端口改为80,则可以修改jboss-service.xml文件;如果想使目标J2EE应用处理更多的文件类型,可以修改web.xml文件。

(4)相关类库的放置:

如果您的应用涉及到第三方类库,比如JDBC Driver,则可以将这些JDBC Driver存放到目录下:C:\jboss-3.2.1_tomcat-4.1.24\server\default\lib。注意,不是目录:C:\jboss-3.2.1_tomcat-4.1.24\lib下。
如果是与目标J2EE应用相关,则可以存放到目标.war(或者.ear)里面,或者xxx.war目录中的WEB-INFO\lib下。无论那种情形,都需要遵循J2EE规范。

当然,JBoss 3.2.1的配置文件有很多,比如提供邮件服务的mail-service.xml文件,等等。在这里只是给读者一些信息,如果您有相关问题,都可以试着本文介绍的一些内容解决您的问题。谢谢。

二,开发EJB应用
如果开发EJB应用,建议采用JBoss作为开发服务器,因为开发、调试、部署速度快。如果采用其他商用服务器,由于实现机理的不同,其编译的速度很慢。
如果采用Entity Beans技术,则您需要知道这么几点。第一,您目标系统的数据源有多少个操作入口,即是否存在Entity Beans之外的方式来操作数据库。如果有,则需要调节相应<container-name>的<commit-option>提交策略以及<locking-policy>策略。
比如,JBoss 3.2.1采用的<commit-option>方式有4种:A、B、C、D。当然,如果除了Entity Beans访问数据库外,别无它出,采用A是很理智的。如果有,则需要取决于具体的情况使用<commit-option>方式。同时,<commit-option>方式的选择与<locking-policy>策略有关系。
能够采用<read-only>的Entity Beans或Entity Beans Methods,则尽量采用,这样会减少或消除死锁发生的可能性。
尽量采用1:n的关系来操作n方的数据表结构,这样能够提高EJB Container的效率。

待续。。。。。。

posted @ 2007-03-01 10:47 chenweicai 阅读(170) | 评论 (0)编辑 收藏

  bin                   启动和关闭JBoss的脚本
  client                客户端与JBoss通信所需的的Java库(JARs)
  docs                  配置的样本文件(数据库配置等)
  doc/dtd               在JBoss中使用的各种XML文件的DTD。
  lib                   一些JAR,JBoss启动时加载,且被所有JBoss配置共享。(不要把你的库放在这里)
  server                各种JBoss配置。每个配置必须放在不同的子目录。子目录的名字表示配置的名字。JBoss包含3个默认的配置:minimial,default和all。
  server/all            JBoss的完全配置,启动所有服务,包括集群和IIOP
  server/default        JBoss的默认配置。在没有在JBoss命令航中指定配置名称时使用。
  server/default/conf   JBoss的配置文件。
  server/default/data   JBoss的数据库文件。比如,嵌入的数据库,或者JBossMQ。
  server/default/deploy JBoss的热部署目录。放到这里的任何文件或目录会被JBoss自动部署EJB、WAR、EAR,甚至服务。
  server/default/lib    一些JAR,JBoss在启动特定配置时加载他们。 (all和minimial配置也包含这个和下面两个目录。)
  server/default/log    JBoss的日志文件。
  server/default/tmp    JBoss的临时文件。

启动时可用-c参数指定要启动的配置:run.bat -c config-name

posted @ 2007-02-28 12:49 chenweicai 阅读(214) | 评论 (0)编辑 收藏

     摘要: JBoss3.0 下配置和部署 EJB 简介 1.JBoss简介 JBoss 是一个运行 EJB 的 J2EE 应用服务器。它是开放源代码...  阅读全文

posted @ 2007-02-28 10:59 chenweicai 阅读(408) | 评论 (0)编辑 收藏

三个基本class
EJB最少也需要三个class, remote interface, home interface, and bean implementation(bean行为).

1. remote interface 用来揭示EJB对外的一些方法.在这个例子中,the remote interface 就是org.jboss.docs.interest.Interest.

ackage org.jboss.docs.interest;

import javax.ejb.EJBObject;
import java.rmi.RemoteException;

/**
This interface defines the `Remote' interface for the `Interest' EJB. Its
single method is the only method exposed to the outside world. The class
InterestBean implements the method.
*/
public interface Interest extends EJBObject
{
  public double calculateCompoundInterest(double principle,
      double rate, double periods) throws RemoteException;
}

 

2.home interface 是用来规定怎样创建一个实现remote interface的bean. 在本例中home interface 是 org.jboss.docs.InterestHome.

package org.jboss.docs.interest;

import java.io.Serializable;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;

/**
This interface defines the `home' interface for the `Interest' EJB.
*/
public interface InterestHome extends EJBHome
{
/**
Creates an instance of the `InterestBean' class on the server, and returns a
remote reference to an Interest interface on the client.
*/
  Interest create() throws RemoteException, CreateException;
}


3.bean implementation 是提供方法的实现,这些方法在上述两种interface中都有规定了,在本例中是两个方法: calculateCompoundInterest和create().

这个bean implementation 是 org.jboss.docs.interest.InterestBean.

package org.jboss.docs.interest;

import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

/**
This class contains the implementation for the `calculateCompoundInterest'
method exposed by this Bean. It includes empty method bodies for the methods
prescribe by the SessionBean interface; these don't need to do anything in this
simple example.
*/
public class InterestBean implements SessionBean
{
  
  public double calculateCompoundInterest(double principle,
    double rate, double periods)
  {
    System.out.println("Someone called `calculateCompoundInterest!'");
    return principle * Math.pow(1+rate, periods) - principle;
  }

  /** Empty method body
  */
  public void ejbCreate()
  {}

  /** Every ejbCreate() method ALWAYS needs a corresponding
  ejbPostCreate() method with exactly the same parameter types.
  */
  public void ejbPostCreate()
  {}

   /** Empty method body
  */
  public void ejbRemove()
  {}
  /** Empty method body
  */
  public void ejbActivate()
  {}

  /** Empty method body
  */
  public void ejbPassivate()
  {}
  /** Empty method body
  */
  public void setSessionContext(SessionContext sc)
  {}
}


 

这些classes必须打包进一个JAR文件中,JAR文件中包含了目录结构和包的层次.在本例中,这些classes是在包org.jboss.docs.interest, 这样他们需要在目录org/jboss/docs/interest/ 下.

部署发布描述器ejb-jar.xml和jboss.xml
在JAR文档创建之前,还需要一个叫META-INF的目录,这是存放部署发布描述器的(一般叫ejb-jar.xml).大部分商用EJB Server提供图形化工具来编辑这个 描述器.在JBoss中需要手工:

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar>
  <description>JBoss Interest Sample Application</description>
  <display-name>Interest EJB</display-name>
  <enterprise-beans>
  <session>
    <ejb-name>Interest</ejb-name>

      <!-- home interface -->
      <home>org.jboss.docs.interest.InterestHome</home>

      <!-- remote interface -->
      <remote>org.jboss.docs.interest.Interest</remote>

      <!-- bean implementation -->
      <ejb-class>org.jboss.docs.interest.InterestBean</ejb-class>

      <!--bean 的类型 这里是Stateless -->
      <session-type>Stateless</session-type>
      <transaction-type>Bean</transaction-type>
  </session>
  </enterprise-beans>
</ejb-jar>

在本例中,一个包中只有一个EJB 这样就不用描述多个EJB之间是怎样交互的.

尽管对于所有的EJB服务器,ejb-jar.xml部署描述器的格式是一样的(更多精确的定义可以从sun得到DTD).它并没有规定所有的必须的信息,比如如何将EJB-NAME和JNDI naming service联系起来.

缺省情况下,JNDI name将使用在ejb-jar.xml中<ejb-name>XXX</ejb-name>中的XXX来使用EJB的home interface.

但是如果有多个EJB,在ejb-jar.xml中,在<ejb-name>XXX</ejb-name>中XXX就不能用同一个名字了,一般格式是"[application name]/[bean name]".

那么如果再按照缺省情况,JNDI name就可能找不到你的应用程序的入口了,因此我们要特别规定一下.这就需要在jboss.xml中规定:

<?xml version="1.0" encoding="UTF-8"?>
<jboss>
  <enterprise-beans>
    <session>
      <ejb-name>Interest</ejb-name>
      <jndi-name>interest/Interest</jndi-name>
    </session>
  </enterprise-beans>
</jboss>

这样,你所有叫Interest文件都被梆定到JNDI name:interest/Interest下面

jndi.properties
虽然有了上面你的应用程序和JNDI name的梆定,但是一旦部署发布到JBoss服务器上,你还需要一个jndi.properties文件,以告诉调用你程序的客户端请求到哪里去初始化JNDI naming service.

 

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

 

在本例中,客户端请求将寻找Interest 这个bean, 然后得到这个bean的home interface. home interface是用来得到这个bean的remote interface.最后,客户端请求将通过remote interface来使用由EJB提供的功能.

posted @ 2007-02-27 22:51 chenweicai 阅读(383) | 评论 (0)编辑 收藏

  JBoss是一个开放源码的EJB服务器,它与其它服务器整合后可以提供一个完整的J2EE平台。本文介绍如何在Linux环境下安装和配置JBoss,以及如何在JBoss平台上实现EJB的开发和部署。

作为J2EE架构中最重要的构件,EJB是实现服务器端分布式计算的核心。EBJ服务器是EJB的容器,它控制着EJB的运行,并为其提供事务处理、数据库访问、安全控制等一系列系统级的服务

EJB服务器是J2EE应用服务器的一个重要组成部分。Sun公司的J2EE SDK、IBM公司的WebSphere,以及BEA公司的WebLogic等J2EE实现都内嵌了EJB服务器。虽然JBoss目前还不是一个完整的J2EE应用服务器,但它却是一个完整的EJB服务器,在与Tomcat、Jetty等Web服务器整合后,能够提供一个完整的J2EE平台。

JBoss最大的优点在于它是源代码开放的自由软件,并完全遵循J2EE规范。由于JBoss强大的功能和优异的性能,以及与Linux等GNU项目的结合,目前已经成为J2EE服务器端企业级应用的一股强大力量。

安装JBoss


JBoss的安装和配置相对比较简单。首先到http://www.jboss.org上下载JBoss软件包。目前JBoss的最高版本为3.0,建议下载相对稳定的JBoss2.4.4和Tomcat3.2.3集成的二进制软件包,这样就避免了单个软件包下载后JBoss和Tomcat之间的配置问题。

下载的软件包解压缩到/usr目录后,将生成/usr/JBoss-2.4.4_Tomcat-3.2.3这目录。为方便今后的使用,把该目录更名为/usr/jb_tom。在/usr/jb_tom目录下可以找到/usr/jb_tom/jboss和/usr/jb_tom/tomcat两个子目录,它们分别为JBoss和Tomcat的根目录。

在正式启动JBoss之前,应该先安装好JDK(建议安装JDK 1.3以上的版本),并将环境变量ClassPath设置好。位于/usr/jb_tom/jboss/bin目录下的run_withtomcat.sh文件是JBoss和Tomcat的启动脚本,按照JBoss和Tomcat的默认配置,运行该脚本后将分别在8080和8083端口启动JBoss和Tomcat的HTTP服务。如果一切正常,此时在浏览器中输入http://localhost:8080将出现Tomcat的首页,而输入http://localhost:8080则出现无错误的空白页面。


创建EJB


下面以一个简单的无状态会话Bean为例,讲述如何为JBoss平台编写EJB。按照EJB规范,一个EJB中至少应该包含如下三个类的实现:

◆远程接口

远程接口暴露了整个EJB对外界的接口,在本例中远程接口封装在greet.Greet类中。

◆本地接口

本地接口描述了创建、管理和销毁EJB时的行为,在本例中本地接口封装在greet.GreetHome类中。

◆Bean类

Bean类实现了远程接口中定义的所有方法,在本例中Bean类封装在greet.GreatBean类中。

EJB在发布时是以一个JAR包的形式提供的。EJB服务器要求该JAR包中必须包含所有的类文件和相应的部署文件,并且要按照EJB开发时的目录结构进行组织。在我们的例子中,所有的类文件都位于greet目录下,部署文件则位于META-INF目录下,相应的目录结构为:

greet
  +-- Greet.java
  +-- GreetHome.java
  +-- GreetBean.java
META-INF
  +-- ejb-jar.xml
  +-- jboss.xml


1.定义远程接口

EJB向外界暴露的接口都在远程接口中进行定义,本例中的EJB只向外界提供了一个接口为calculateMagic,相应的源文件为Greet.java,代码如下:

package greet;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
/**
 * 这个接口为‘Greet’定义了远程接口
public interface Greet extends EJBObject 
{
    public double calculateMagic(double seed) throws RemoteException;
}


2.定义本地接口

EJB的本地接口对创建、管理和销毁EJB的行为进行了描述,本地接口至少应该提供create()方法,以便对EJB创建时的行为进行相应的描述。例子中本地接口对应的源文件为GreetHome.java,代码如下:

package greet;
import java.io.Serializable;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface GreetHome extends EJBHome 
{
 Greet create() throws RemoteException, CreateException;
}


3. 实现Bean类

EJB真正完成的工作是在Bean类中实现的,Bean类必须为远程接口中定义的所有方法提供相应的实现。本例中的Bean类对应的源文件为GreetBean.java:

package greet;
import java.rmi.RemoteException; 
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
public class GreetBean implements SessionBean 
{
 public double calculateMagic(double seed) {
  System.out.println ("Someone called `calculateMagic!'");
return seed * Math.random();
 }
 public GreetBean() {}
public void ejbCreate() {
 System.out.println("Create Greet EJB.");
}
public void ejbRemove() {
 System.out.println("Remove Greet EJB.");
}
public void ejbActivate() {
 System.out.println("Activate Greet EJB");
}
 public void ejbPassivate() {
  System.out.println("Passivate Greet EJB");
 }
/**
* Set context for `Greet' EJB
*/
 public void setSessionContext(SessionContext sc) {
  System.out.println("Set context for Greet EJB");
 }
}


在给出EJB的接口定义并提供了Bean类的具体实现后,用下面的命令对这些.java文件进行编译,生成相应的.class文件:

javac *.java -classpath \
/usr/jb_tom/jboss/lib/ext/jboss-j2ee.jar:.


 

部署描述符



根据EJB规范,要想将EJB成功地部署到EJB服务器上,必须为EJB服务器提供相应的部署描述符。部署描述符对所要部署的EJB进行了说明,包括该EJB的远程描述符、本地描述符和Bean类等信息。由于EJB服务器只有在获得这些基本信息后才能正确完成EJB的部署,因此编写EJB描述符是开发EJB时必不可少的一个环节。

对于不同的EJB服务器来说,部署同一EJB时所需的部署描述符可能并不相同。在JBoss平台上,任何将要被部署的EJB都必须提供ejb-jar.xml和jboss.xml两个文件,这两个文件均位于JAR包中的META-INF目录下,用于对将要部署的EJB进行简要的说明。

ejb-jar.xml

ejb-jar.xml是EJB规范定义的标准部署描述符,在任何EJB服务器上部署EJB时都需要用到该部署描述符。本例中用到的ejb-jar.xml代码如下所示:

<?xml version="1.0" encoding="Cp1252"?>
<ejb-jar>
<description>jBoss test application </description>
<display-name>Test</display-name>
<enterprise-beans>
<session>
<ejb-name>GreetEJB</ejb-name>
<home>greet.GreetHome</home>
<remote>greet.Greet</remote>
<ejb-class>greet.GreetBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>


jboss.xml

虽然ejb-jar.xml对所有的EJB服务器都是通用的,但它并没有为EJB服务器提供将要被部署的EJB的全部信息。为了能够对EJB的部署进行更灵活的控制,大部分EJB服务器都要求EJB开发者同时提供另外一个文件来对将要部署的EJB进行描述,在JBoss中该文件为jboss.xml,它也位于JAR包中的META-INF目录中。jboss.xml中可以对EJB对应的JNDI名字以及相应的持久性进行说明,在本例中用到的jboss.xml如下所示:

<?xml version="1.0" encoding="ISO-8859-1"?>
<jboss>
<enterprise-beans>
<session>
<ejb-name>GreetEJB</ejb-name>
<jndi-name>GreetingEJB</jndi-name>
</session>
<secure>false</secure>
</enterprise-beans>
<resource-managers/>
</jboss>


部署EJB



开发EJB的最后一步是将其中所有的类文件和相应的部署描述符压缩成JAR包,然后部署到EJB服务器上。在本例中,JAR包的生成可以通过下面这条命令来实现:

jar cf greetejb.jar greet/*.class META-INF/*.xml


该命令将greet目录下的.class文件和META-INF目录下的.xml文件压缩成greetejb.jar文件。如果想知道生成的JAR包是否正确地包含了所有的文件,可以用命令:

jar cvf greetejb.jar


来查看greetejb.jar中包含的文件。如果得到如下的类似信息,则说明所需的文件都已经被正确地包含在该压缩包中了,信息如下:

0 Sun May 24 15:32:10 CST 2002 META-INF/
68 Sun May 24 15:32:10 CST 2002 META-INF/MANIFEST.MF
1007 Sun May 24 14:35:46 CST 2002 greet/GreetBean.class
209 Sun May 24 14:35:46 CST 2002 greet/Greet.class
251 Sun May 24 14:35:46 CST 2002 greet/GreetHome.class
493 Sun May 24 08:40:00 CST 2002 META-INF/ejb-jar.xml
303 Sun May 24 08:43:22 CST 2002 META-INF/jboss.xml


生成的JAR包在JBoss上的部署相当简单,只需要将该文件复制到JBoss的deploy目录下就可以了,命令如下:

cp greetejb.jar /usr/jb_tom/jboss/deploy/


JBoss支持热部署,deploy目录下所有文件的改变都会被JBoss自动检测到,并根据检测结果对相应的EJB进行
[INFO,ContainerFactory] Deploying GreetEJB
[INFO,GreetEJB] Initializing
[INFO,GreetEJB] Initialized
[INFO,GreetEJB] Starting
[INFO,GreetEJB] Started


至此,EJB在JBoss平台上的部署就全部完成了,如果想知道该EJB能否正常地工作,则需要为其编写专门的客户端程序进行测试。

测试EJB



EJB存在的价值在于为其客户提供相应的服务,EJB客户包含的范围相当广泛,可以是另外的EJB、普通的JavaBean、JSP页面、Applet或者标准的Java应用程序。GreetClient.java是已经部署好的EJB的客户程序,其完整的源码如下所示:

import javax.naming.*;
import java.util.Hashtable;
import javax.rmi.PortableRemoteObject; 
import greet.*;
class GreetClient
{
 public static void main(String[] args) {
  System.setProperty("java.naming.factory.initial", 
"org.jnp.interfaces.Naming ContextFactory");
  System.setProperty("java.naming.provider.url", 
"localhost:1099");
try {
   // Get a naming context
   InitialContext jndiContext = new InitialContext();
  System.out.println("Got context");
 Object ref  = jndiContext.lookup("GreetingEJB");
  System.out.println("Got reference");
 GreetHome home = (GreetHome) 
   PortableRemoteObject.narrow (ref, GreetHome.class);
   Greet greet = home.create();
   System.out.print("The magic number from server is ");
System.out.println(greet.calculateMagic(123.456));
  } catch(Exception e) {
   System.out.println(e.toString());
  }
 }
}


用下面的命令对EJB客户端程序进行编译:

javac GreetClient.java \
-classpath /usr/jb_tom/jboss/lib/ext/jboss-j2ee.jar:.


如果一切正常,就可以运行客户端程序来对EJB进行测试了,命令如下:

java -cp \ 
$CLASSPATH:/usr/jb_tom/jboss/client/jboss-client.jar:. \
GreetClient


小结



本文以一个无状态的会话Bean为例,讲述了在JBoss平台上开发和部署EJB的全过程,对JBoss的安装、EJB的创建、EJB的部署及EJB的测试做了简要介绍。作为一个开放源码的EJB服务器,JBoss已经开始被越来越多的企业所接受,基于JBoss的成功案例屡见不鲜。有关JBoss的更多信息,请访问JBoss的网站http://www.jboss.org。

posted @ 2007-02-27 22:11 chenweicai 阅读(240) | 评论 (0)编辑 收藏

jdk是java develop kit -- java开发包
j2sdk是java 2 software develop kit -- java2软件开发包

实际上jdk和j2sdk是基本同样的。
j2sdk呢有几个版本对应于java2的几个版本,其中j2ee需要用到开发工具就是J2eesdk了,只不过大部分应用服务器(weblogic jboss等)都内置了j2eesdk。

当然了,j2sdk标准版是基础,所以要安装先;j2eesdk因为是企业应用嘛,所以是注册后才能下载

至于jre是java runtime envionment -- java运行环境,jdk中包括了它,但是对于不需要开发只是运行的用户是可以只单独安装jre的,所以sun提供了jre的下载。



JDK和J2SDk:

J2SDk包含了Java Development kit(JDK)、Java Runtime Environment(JRE)和Java Plug-in。原先sun的JAVA软件开发工具包是JDK,现在就称为J2SDk了。 

JRE和plug-in:JRE包含了java plug-in。 

sun的java网站上就单独提供J2SDK和JRE各种版本的下载,J2SDk是提供给开发JAVA程序所 
用,应用程序用户是不需要开发工具的。而JRE顾名思义是JAVA程序要运行所需要的环境 
,所谓跨平台就是要各种平台都有一个中间代理,那就是JRE。一般采用JAVA技术开发出 
的软件都得带这个,所以sun就单独提供了JRE安装文件,以供JAVA应用程序发布时所用。 

Swing和JFC(Java Foundation Class)JFC是早期Sun对JDK的功能扩展,不是Java的公共 
规范,Swing是其中的一项用户界面扩展技术。最新的JAVA2技术则包含了JFC技术,不需 
要再扩展了。说白了,其实就是Sun将JFC纳入了JAVA核心类库。原先要用到JFC技术,用 
户必须在原有的JRE前提下再添加JFC,现在少了一步,只需JRE了。

J2ME——Java 2 Micro Edition
J2SE——Java 2 Standard Edition
J2EE——Java 2 Enterprise Edition
如需要进行开发,必须安装J2SE,因为javac、jdb等工具由提供。

posted @ 2007-02-27 18:39 chenweicai 阅读(315) | 评论 (0)编辑 收藏

Java

Description

Executes a Java class within the running (Ant) VM or forks another VM if specified.

If odd things go wrong when you run this task, set fork="true" to use a new JVM.

As of Ant 1.6.3, you can interact with a forked VM, as well as sending input to it via the input and inputstring attributes.

Parameters

Attribute Description Required
classname the Java class to execute. Either jar or classname
jar the location of the jar file to execute (must have a Main-Class entry in the manifest). Fork must be set to true if this option is selected. See notes below for more details. Either jar or classname
args the arguments for the class that is executed. deprecated, use nested <arg> elements instead. No
classpath the classpath to use. No
classpathref the classpath to use, given as referenceto a PATH defined elsewhere. No
fork if enabled triggers the class execution in another VM (disabled by default) No
spawn if enabled allows to start a process which will outlive ant.
Requires fork=true, and not compatible with timeout, input, output, error, result attributes.
(disabled by default)
No
jvm the command used to invoke the Java Virtual Machine, default is 'java'. The command is resolved by java.lang.Runtime.exec(). Ignored if fork is disabled. No
jvmargs the arguments to pass to the forked VM (ignored if fork is disabled). deprecated, use nested <jvmarg> elements instead. No
maxmemory Max amount of memory to allocate to the forked VM (ignored if fork is disabled) No
failonerror Stop the buildprocess if the command exits with a returncode other than 0. Default is "false" (see note) No
resultproperty The name of a property in which the return code of the command should be stored. Only of interest if failonerror=false and if fork=true. No
dir The directory to invoke the VM in. (ignored if fork is disabled) No
output Name of a file to which to write the output. If the error stream is not also redirected to a file or property, it will appear in this output. No
error The file to which the standard error of the command should be redirected. No
logError This attribute is used when you wish to see error output in Ant's log and you are redirecting output to a file/property. The error output will not be included in the output file/property. If you redirect error with the "error" or "errorProperty" attributes, this will have no effect. No
append Whether output and error files should be appended to or overwritten. Defaults to false. No
outputproperty The name of a property in which the output of the command should be stored. Unless the error stream is redirected to a separate file or stream, this property will include the error output. No
errorproperty The name of a property in which the standard error of the command should be stored. No
input A file from which the executed command's standard input is taken. This attribute is mutually exclusive with the inputstring attribute No; default is to take standard input from console (unless spawn="true")
inputstring A string which serves as the input stream for the executed command. This attribute is mutually exclusive with the input attribute. No; default is to take standard input from console (unless spawn="true")
newenvironment Do not propagate old environment when new environment variables are specified. Default is "false" (ignored if fork is disabled). No
timeout Stop the command if it doesn't finish within the specified time (given in milliseconds). It is highly recommended to use this feature only if fork is enabled. No
clonevm If set to true true, then all system properties and the bootclasspath of the forked Java Virtual Machine will be the same as those of the Java VM running Ant. Default is "false" (ignored if fork is disabled). since Ant 1.7 No

Parameters specified as nested elements

arg and jvmarg

Use nested <arg> and <jvmarg> elements to specify arguments for the Java class and the forked VM respectively. See Command line arguments.

sysproperty

Use nested <sysproperty> elements to specify system properties required by the class. These properties will be made available to the VM during the execution of the class (either ANT's VM or the forked VM). The attributes for this element are the same as for environment variables.

syspropertyset

You can specify a set of properties to be used as system properties with syspropertysets.

since Ant 1.6.

classpath

Java's classpath attribute is a PATH like structureand can also be set via a nested classpath element.

bootclasspath

The location of bootstrap class files can be specified using this PATH like structure- will be ignored if fork is not true or the target VM doesn't support it (i.e. Java 1.1).

since Ant 1.6.

env

It is possible to specify environment variables to pass to the forked VM via nested env elements. See the description in the section about exec

Settings will be ignored if fork is disabled.

permissions

Security permissions can be revoked and granted during the execution of the class via a nested permissions element. For more information please see permissions

When the permission RuntimePermission exitVM has not been granted (or has been revoked) the System.exit() call will be intercepted and treated like indicated in failonerror.

Note:
If you do not specify permissions, a set of default permissions will be added to your Java invocation to make sure that the ant run will continue or terminated as indicated by failonerror. All permissions not granted per default will be checked by whatever security manager was already in place. exitVM will be disallowed.

Settings will be ignored if fork is enabled.

since Ant 1.6.

assertions

You can control enablement of Java 1.4 assertions with an <assertions>subelement.

Assertion statements are currently ignored in non-forked mode.

since Ant 1.6.

redirector

Since Ant 1.6.2

A nested I/O Redirectorcan be specified. In general, the attributes of the redirector behave as the corresponding attributes available at the task level. The most notable peculiarity stems from the retention of the <java> attributes for backwards compatibility. Any file mapping is done using a null sourcefile; therefore not all Mappertypes will return results. When no results are returned, redirection specifications will fall back to the task level attributes. In practice this means that defaults can be specified for input, output, and error output files.

Errors and return codes

By default the return code of a <java> is ignored. Alternatively, you can set resultproperty to the name of a property and have it assigned to the result code (barring immutability, of course). When you set failonerror="true", the only possible value for resultproperty is 0. Any non-zero response is treated as an error and would mean the build exits.

Similarly, if failonerror="false" and fork="false" , then <java>must return 0 otherwise the build will exit, as the class was run by the build JVM.

JAR file execution

The parameter of the jar attribute is of type File; that is, the parameter is resolved to an absolute file relative to the base directory of the project, not the directory in which the Java task is run. If you need to locate a JAR file relative to the directory the task will be run in, you need to explicitly create the full path to the JAR file.

When using the jar attribute, all classpath settings are ignored according to Sun's specification.

Examples

				       <java classname="test.Main">
         <arg value="-h"/>
         <classpath>
           <pathelement location="dist/test.jar"/>
           <pathelement path="${java.class.path}"/>
         </classpath>
       </java>

		
Run a class in this JVM with a new jar on the classpath
				       <java jar="dist/test.jar"
           fork="true"
           failonerror="true"
           maxmemory="128m"
           >
         <arg value="-h"/>
         <classpath>
           <pathelement location="dist/test.jar"/>
           <pathelement path="${java.class.path}"/>
         </classpath>
       </java>

		
Run the JAR test.jar in this project's dist/lib directory. using the manifest supplied entry point, forking (as required), and with a maximum memory of 128MB. Any non zero return code breaks the build.
				       <java
           dir="${exec.dir}"
           jar="${exec.dir}/dist/test.jar"
           fork="true"
           failonerror="true"
           maxmemory="128m"
           >
         <arg value="-h"/>
         <classpath>
           <pathelement location="dist/test.jar"/>
           <pathelement path="${java.class.path}"/>
         </classpath>
       </java>

		
Run the JAR dist/test.jar relative to the directory ${exec.dir}, this being the same directory into which the JVM is to start up.
				  <java classname="test.Main"/>
		
Runs a given class with the current classpath.
				  <java classname="test.Main"
        fork="yes" >
    <sysproperty key="DEBUG" value="true"/>
    <arg value="-h"/>
    <jvmarg value="-Xrunhprof:cpu=samples,file=log.txt,depth=3"/>
  </java>

		
Add system properties and JVM-properties to the JVM as in java ="-Xrunhprof:cpu=samples,file=log.txt,depth=3 -DDEBUG=true test.Main
				  <java classname="ShowJavaVersion" classpath="."
        jvm="path-to-java14-home/bin/java" fork="true"
        taskname="java1.4" >

		
Use a given Java implementation (another the one Ant is currently using) to run the class. For documentation in the log taskname is used to change the [java] log-prefix to [java1.4].

Note: you can not specify the (highly deprecated) MSJVM, "jview.exe" as the JVM, as it takes different parameters for other JVMs, That JVM can be started from <exec> if required.

posted @ 2007-01-31 20:12 chenweicai 阅读(1295) | 评论 (0)编辑 收藏

package proxy;
/**
 *
 * @author chen
 *
 */
public interface Subject {
 abstract public void request();
 abstract public void request2();
}


package proxy;

/**
 *
 * @author chen
 *
 */
public class RealSubject implements Subject {
 
 public RealSubject(){
 }

 public void request() {
  // TODO Auto-generated method stub
  System.out.println("From real subject.request().");
 }
 
 public void request2() {
  // TODO Auto-generated method stub
  System.out.println("From real subject.request2()");
 }
}

package proxy;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 *
 * @author chenweicai
 *
 */
public class DynamicSubject implements InvocationHandler {
 
 private Object sub;
 
 public DynamicSubject(){
 }
 
 public DynamicSubject(Object obj){
  this.sub = obj;
 }

 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  // TODO Auto-generated method stub
     System.out.println("before calling " + method);
     method.invoke(sub,args);
     System.out.println("after calling " + method);
  return null;
 }

}


package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;

/**
 *
 * @author chen
 *
 */
public class Client {
 static public void main(String[] args)
        throws Throwable{
    RealSubject rs = new RealSubject();  //在这里指定被代理类
    InvocationHandler ds = new DynamicSubject(rs);  //初始化代理类
    Class cls = rs.getClass();
  
    //以下是分解步骤
    /*Class c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces()) ;
    Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class});
    Subject subject =(Subject) ct.newInstance(new Object[]{ds});*/
  
    //以下是一次性生成
    Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(),
    cls.getInterfaces(),ds );

    subject.request2();
   }
}

posted @ 2007-01-05 20:47 chenweicai 阅读(390) | 评论 (1)编辑 收藏

仅列出标题
共6页: 上一页 1 2 3 4 5 6 下一页