爪哇一角

共同探讨STRUTS#HIBERNATE#SPRING#EJB等技术
posts - 3, comments - 6, trackbacks - 0, articles - 99
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Xdoclet 生成 SessionBean EntityBean 代码

xDoclet 简介

              使用 XDoclet ,你能够在 J2EE 环境下更加高效地工作,你所看到的 Bean 以及 Bean 之间的关系将更加简单,许多繁杂的事情将远离你的 EJB 开发过程。

       XDoclet Rickard Oberg 创建的 EJBDoclet 工具发展而来,它的设想很简单:避免为每个 EJB 提供多个文件,而是从单一 Bean 类文件中提供组件需要的所有信息。那么,这是如何实现的呢? Java 没有 .NET 吹嘘的“属性”,但 Java Javadoc 标记。我们可以把一个特殊的 @ 标记放入 Javadoc 注释,然后让一个 Doclet 工具处理这些标记。由工具为指定的 Bean 生成合适的 XML 描述器文件和接口文件。 XDoclet 建立在 EJBDoclet 思想的基础上,但适用范围不再局限于 EJB 。现在,我们已经可以用 XDoclet 生成 Web 服务、 Web 应用描述器,甚至还可以对它进行扩展,满足自己的特殊需要。

 

@ 标记有一个标准的格式,包含一个“名称空间”以及一个属于该名称空间的“标记名称”。标记的属性以“名字 = 值”的形式在标记中指定。下面是一个例子:

 

/**

* @namespace:tag name="value" name2="value2" ...

*/

 

当前可用的名称空间包括:

ejb 标准的 EJB 信息(非厂商私有的信息)

jboss 面向 JBoss 应用服务器的信息。

weblogic 面向 BEA Weblogic 应用服务器的信息。

webSphere 面向 IBM WebSphere 应用服务器的信息。

orion 面向 Orion 应用服务器( Oracle )的信息。

castor Castor 框架生成映射信息。

mvcsoft MVCSoft EJB 2.0 持久化管理器生成文件。

soap 生成 SOAP 描述器。

struts 生成 struts-config.xml

web Web 应用生成 web.xml 配置文件。

jsp 生成标记库扩展描述器信息。

从上面的清单可以看出,除了 EJB 之外, XDoclet 还提供了许多其它方面的支持(因此它的名字也从 EJBDoclet 变成了 XDcolet )。

myEclipse 中的配置

       以下本文使用 eclipse 结合 myeclipse 插件,进行 ejb 的开发和演示。安装好 eclipse myeclipse 以后,就可以新建项目进行 ejb project 的开发。

1.       新建立 EJB Project

输入工程名称: myEJB ,注意, src 是默认的源码输出文件夹,因为在 myeclipse 中很多 xdoclet 配置文件的输出文件目标路径默认值都是该文件夹,所以建议大家不要修改这个默认值。

新建立项目后,由于目前没有 ejb-jar.xml 的配置文件,所以会有一个 warning 信息:

这个警告信息会在 xdoclet 运行生成 ejb-jar.xml 文件后消失。

2.       鼠标右键选择新建的 myejb 项目,弹出窗口中选择 properties

进入到 myeclipse-xdoclet ,准备进行项目的 xdoclet 配置

增加一个标准的配置,然后选择 ejb 的标准配置

这个操作将生成 ejb 代码的选项都进行默认的配置,不依赖于任何的应用程序服务器

不过我这个演示是用的 jboss 的服务器,所以还需要增加 jboss 的选项,右键点上图中的 ejbdoclet 的根节点,选择 add 来增加 ejb 的生成项目,在出现的选择列表中,选择 jboss

然后配置新增加的 jboss 的选项,一般来说,有如下 4 项需要填写,见下图标记部分:

其中,

version 表明你用的 jboss 的版本,我用的是 jboss-4.0.3 ,但是只需要标记 4.0 即可 , 如果你使用的是 3.2.* 的版本,那就填写成为 3.2

第二个是你在 jboss 中配置的 datasource 的名称

第三个是你用到的数据源映射名称,这个名称是不能够任意填写,必须按照 jboss 配置文件中填写,配置文件在 C:\jboss-4.0.3\server\default\conf\standardjbosscmp-jdbc.xml (我的 jboss 安装目录)我测试用的是 mysql ,所以填写 mySQL 。如果是 oracle9i 的数据库,则为 Oracle9i ,更加详细的信息,察看 standardjbosscmp-jdbc.xml 文件

最后一个是生成 jboss.xml jbosscmp-jdbc.xml 的目标文件夹,一般生成到 src/META-INF 文件夹。

到这里, xdoclet 的配置完成,下面将创建 EntityBean 的类并根据定义的 tag 来生成代码。

生成 EntityBean 代码

首先创建一个 entitybean ,名称为 User ,如下图所示,需要注意,包名必须最后是 .ejb 结尾,否则 xdoclet 不认

创建完成后,检查生成的代码, User.java, 会发现在类的上方,会出现如下的 tag

* @ejb.bean name="User"

 *           display-name="Name for User"

 *           description="Description for User"

 *           jndi-name="ejb/User"

 *           type="CMP"

 *           cmp-version="2.x"

 *           view-type="both"

这些是默认生成的 tag ,不能完全的符合我们的要求,我们修改成为如下,红色为增加的部分:

* @ejb.bean name = "User"

*                   type = "CMP"

*                   cmp-version = "2.x"

*                   display-name = "User"

*                   description = "User"

*                   view-type = "both"

*                   jndi-name = "ejb/UserHome"

*                   local-jndi-name = "ejb/UserLocalHome"

*                   primkey-field = "userId"

* @ejb.persistence table-name = "systemuser"

* @jboss.persistence table-name = "systemuser"

* @ejb:util

* generate="physical"

然后,需要为 user entity 增加它的几个相关的方法

在相关的地方修改这个抽象的类,修改后,红色为增加的部分:

public abstract class User implements EntityBean {

 

       /** The entity context */

       private EntityContext context;

 

       /**

       * @ejb.interface-method view-type = "both"

       * @ejb.persistence column-name = "userId"

       * @ejb.pk-field

       *

       * @return

       */

       public abstract String getUserId();

       /**

       * @ejb.interface-method view-type = "both"

       *

       * @param userId

       */

       public abstract void setUserId(String userId);

       /**

       * @ejb.interface-method view-type = "both"

       * @ejb.persistence column-name = "userName"

       *

       * @return

       */

       public abstract String getUserName();

       /**

       * @ejb.interface-method view-type = "both"

       *

       * @param userName

       */

       public abstract void setUserName(String userName);

       /**

       * @ejb.interface-method view-type = "both"

       * @ejb.persistence column-name = "Password"

       *

       * @return

       */

       public abstract String getPassword();

       /**

       * @ejb.interface-method view-type = "both"

       *

       * @param password

       */

       public abstract void setPassword(String Password);

好了, entitybean 修改成为这样以后就可以生成相关的接口和实现类了

如果运行正常,在控制台窗口中会出现如下提示:

Buildfile: F:\workspace\MyEJB\.xdoclet-build.tmp.xml

N65540:

[ejbdoclet] (XDocletMain.start                   47  ) Running <remoteinterface/>

[ejbdoclet] Generating Remote interface for 'com.mycom.myejb.entity.ejb.User'.

[ejbdoclet] (XDocletMain.start                   47  ) Running <localinterface/>

[ejbdoclet] Generating Local interface for 'com.mycom.myejb.entity.ejb.User'.

[ejbdoclet] (XDocletMain.start                   47  ) Running <homeinterface/>

[ejbdoclet] Generating Home interface for 'com.mycom.myejb.entity.ejb.User'.

[ejbdoclet] (XDocletMain.start                   47  ) Running <localhomeinterface/>

[ejbdoclet] Generating Local Home interface for 'com.mycom.myejb.entity.ejb.User'.

[ejbdoclet] (XDocletMain.start                   47  ) Running <dataobject/>

[ejbdoclet] Generating Data Object class for 'com.mycom.myejb.entity.ejb.User'.

[ejbdoclet] (XDocletMain.start                   47  ) Running <valueobject/>

[ejbdoclet] (XDocletMain.start                   47  ) Running <entitypk/>

[ejbdoclet] (XDocletMain.start                   47  ) Running <entitycmp/>

[ejbdoclet] Generating CMP class for 'com.mycom.myejb.entity.ejb.User'.

[ejbdoclet] (XDocletMain.start                   47  ) Running <entitybmp/>

[ejbdoclet] (XDocletMain.start                   47  ) Running <session/>

[ejbdoclet] (XDocletMain.start                   47  ) Running <dao/>

[ejbdoclet] (XDocletMain.start                   47  ) Running <utilobject/>

[ejbdoclet] Generating Util class for 'com.mycom.myejb.entity.ejb.User'.

[ejbdoclet] (XDocletMain.start                   47  ) Running <deploymentdescriptor/>

[ejbdoclet] Generating EJB deployment descriptor (ejb-jar.xml).

[ejbdoclet] (XDocletMain.start                   47  ) Running <jboss/>

[ejbdoclet] Generating jboss.xml.

[ejbdoclet] Generating jbosscmp-jdbc.xml.

_xdoclet_generation_:

BUILD SUCCESSFUL

Total time: 8 seconds

如果你在运行中,出现了

N65540:

 

BUILD FAILED

java.lang.UnsupportedClassVersionError: xjavadoc/ant/XJavadocTask (Unsupported major.minor version 49.0)

 

的异常,建议你更换以下 eclipse jre 环境。例如当我用 jdk1.4.2 的时候就出现上述异常,更换为 jdk1.5 后即正常运行。

生成 SessionBean 代码

 

 

 

修改生成的类为抽象的类

public abstract class UserManager implements SessionBean {

…………….

 

修改 UserManager xdoclet 标签为:

* @ejb.bean name="UserManager"

 *           display-name="Name for UserManager"

 *           description="Description for UserManager"

 *           jndi-name="ejb/UserManagerHome"

 *           type="Stateless"

 *           view-type="both"

 

下面将增加一个 login 的方法,将 UserManager.java 移动到最下方,你会发现 xdoclet 已经给你创建了一个现有的方法:

       /**

        * An example business method

        *

        * @ejb.interface-method view-type = "both"

        *

        * @throws EJBException Thrown if method fails due to system-level error.

        */

       public void replaceWithRealBusinessMethod() throws EJBException {

              // rename and start putting your business logic here

       }

根据你自己的需要修改这个方法,或者增加新的方法,不过一定要保留它的 ejb 的标签

例如增加一个方法 :

       /**

        * @ejb.interface-method view-type = "both"

        *

        * @param username

        * @param password

        * @return

        * @throws EJBException

        */

       public boolean login(String username,String password) throws EJBException {

              boolean loginresult = false;

              if(username.equals("gary") && password.equals("gzllm")){

                     System.out.println(" 用户名与密码匹配 , 允许登录系统 ");

                     loginresult = true;

              }else{

                     System.out.println(" 用户名与密码不匹配 , 不登录失败 ");

                     loginresult = false;

              }

              return loginresult;

       }

然后再次运行 xdoclet

运行成功后会生成如下图所示结构的代码:

这个时候就生成了最常用的 SessionBean 的代码。

 

部署 EJB 程序

1、  部署 ejb 代码,首先需要设置你的应用程序服务器,以下我配置了一个 jboss 的应用程序服务器。在 eclipse windows 菜单下选择 preferences ,选择 myeclipse 选项,选择你需要使用的服务器,并配置相关的路径,如下图所示:

2、  Jboss 下面的进一步的选项中能够选择运行的模式,可以选择 debug 模式和 run 模式,建议现在选择 debug 模式

3、  JDK 选用你正在使用的 jdk ,点 ok 配置结束

4、  由于发布的 jboss ejb 程序需要用到 mySQL 数据库,所以还需要配置一下 JBoss ,首先拷贝 mysql 的数据库配置文件,从 C:\jboss-4.0.3\docs\examples\jca\mysql-ds.xml 拷贝到需要发布的服务器中,修改配置文件数据库连接部分为:
    <jndi-name>MyEJB</jndi-name>

    <connection-url>jdbc:mysql://192.168.2.26:3306/MyEJB</connection-url>

    <driver-class>com.mysql.jdbc.Driver</driver-class>

    <user-name>root</user-name>

    <password>root</password>

    <connection-url>jdbc:mysql://192.168.2.26:3306/MyEJB</connection-url>
然后启动你自己的 mysql 的数据库,并创建 MyEJB 数据库以及相关的 User 表。

另外,还需要将用到的数据库连接驱动程序 mysql-connector-java-3.1.10-bin.jar (我用的 mysql jdbc 驱动程序是 mysql-connector-java-3.1.10 )拷贝到应用程序服务器的 lib 目录中,我的目录是 C:\jboss-4.0.3\server\default\lib ,否则在启动 jboss 的时候会报异常:

16:48:25,078 WARN  [JBossManagedConnectionPool] Throwable while attempting to get a new connection: null

org.jboss.resource.JBossResourceException: Could not create connection;

- nested throwable: (org.jboss.resource.JBossResourceException: Failed to register driver for: com.mysql.jdbc.Driver;

- nested throwable: (java.lang.ClassNotFoundException:

No ClassLoaders found for: com.mysql.jdbc.Driver))

5、  eclipse 的工具栏中找到如图所示的一个按钮

6、  增加一个配置

7、  选择刚才配置的 jboss 服务器

8、  选择完成。

9、  部署完成

10、              运行 ejb ,点击部署旁边的一个按钮:

11、              Jboss 启动过程中,可以看到,刚才写的 ejb 部分已经发布成功。
在控制台的启动 log 中,你可以看到类似以下语句:
17:00:16,453 INFO  [ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:name=MyEJB,service=DataSourceBinding' to JNDI name 'java:MyEJB'

17:00:17,312 INFO  [EjbModule] Deploying User

17:00:17,812 INFO  [EjbModule] Deploying UserManager

17:00:18,250 INFO  [BaseLocalProxyFactory] Bound EJB LocalHome 'User' to jndi 'ejb/UserLocalHome'

17:00:18,328 INFO  [ProxyFactory] Bound EJB Home 'User' to jndi 'ejb/UserHome'

17:00:22,796 INFO  [BaseLocalProxyFactory] Bound EJB LocalHome 'UserManager' to jndi 'UserManagerLocal'

17:00:22,812 INFO  [ProxyFactory] Bound EJB Home 'UserManager' to jndi 'ejb/UserManagerHome'

17:00:22,828 INFO  [EJBDeployer] Deployed: file:/C:/jboss-4.0.3/server/default/deploy/MyEJB.jar/

说明 entitybean sessionbean 部署运行成功。

JBoss 的管理界面中,也可以找到如下的关于 myejb.jar 的部署说明:

 

测试 EJB 程序

1、  新建一个 java project project name MyEJBTest



在项目的 libraries 中,将 J2EE 的包添加到项目中,另外还需要增加一个变量,如下图所示:

然后将新增加的变量也增加到你的项目 libories 中:

2、  在项目的构建路径中增加对 MyEJB 项目的引用:


3、  新建一个类 Test


4、  编辑生成的 Test 的类,修改后的代码如下所示:
package com.mycompany.myejb.test;

 

import java.rmi.RemoteException;

import java.util.Properties;

 

import javax.ejb.CreateException;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.rmi.PortableRemoteObject;

 

import com.mycom.myejb.session.interfaces.UserManager;

import com.mycom.myejb.session.interfaces.UserManagerHome;

 

public class Test {

       Properties properties;

      

       public Test() {

              properties = new Properties();

              properties.put("java.naming.factory.initial",

              "org.jnp.interfaces.NamingContextFactory");

              properties.put("java.naming.factory.url.pkgs",

              "org.jboss.naming:org.jnp.interfaces");

              properties.put("java.naming.provider.url", "jnp://localhost:1099");

              properties.put("jnp.disableDiscovery", "true");

       }

      

       /**

        * @param args

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

              Test t = new Test();

              System.out.println(" 登录测试结果 :" + t.testLogin("gary", "gzllm"));

              System.out.println(" 登录测试结果 :" + t.testLogin("errorUser", "gzllm"));

       }

      

       public boolean testLogin(String username, String password) {

              boolean loginresult = false;

              Context ctx;

              try {

                     ctx = new InitialContext(properties);

                     Object object = ctx.lookup(UserManagerHome.JNDI_NAME);

                     UserManagerHome userManagerHome = (UserManagerHome) PortableRemoteObject

                     .narrow(object, UserManagerHome.class);

                     UserManager userManager = userManagerHome.create();

                     loginresult = userManager.login(username, password);

              } catch (NamingException e) {

                     e.printStackTrace();

              } catch (RemoteException e) {

                     e.printStackTrace();

              } catch (CreateException e) {

                     e.printStackTrace();

              }

              return loginresult;

       }

      

}

5、  如上的测试程序测试部署成功的 myejb.jar 中的 login 的方法,如果输入的用户名与密码为 gary/gzllm 则返回 true ,否则其他的就返回 false ,运行生成的 Test ,可以看到如下输出结果:


整个程序测试成功。

总结与补充

1.       由于 EJB 的一个最基本的设计模式 Session Façade ,我并没有在测试程序中直接调用 User 这个 entitybean ,甚至为了简便,甚至生成了这个类以后就没有使用它。建议在 SessionBean 中再调用 EntityBean ,也就是说,你可以在 UserManager 这个 sessionbean 中调用 User 这个 EntityBean 进行进一步的读取数据库,验证输入的用户名称与密码是否和数据库表中的数据一致,具体的访问操作,在 EntityBean 中操作。

2.       Hibernate 的出现,给 ejb 的使用带来了新的机遇,你可以生成 hibernate 的相关对象,然后在 SessionBean 的方法中不调用 EntityBean ,而是直接调用 Hibernate 的对象,进行数据库的访问。这将带来更大的灵活性,并能提高程序开发的效率

3.       在测试程序中,可以使用 Factory 模式,简化 SessionBean 对象的创建,并能够提高重用。

4.       xdoclet 不止能够创建 ejb 的代码,还能够产生 hibernate 等很多代码,需要进行相关的配置即可,这需要对 xdoclet 的文档进行进一步的查看与研究,另外还能够自定义 tag ,例如生成 javascript 的校验代码。 Xdoclet 是个好东西,就是用起来很复杂。

5.       eclipse export 功能可以输出 ant build.xml 文件,不过这个配置文件很基本,你可以根据生成的 build 配置文件,进一步的扩充,使开发 - 〉测试 - 〉打包 - 〉部署自动化,能提高开发效率。

 


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


网站导航: