Xdoclet
生成
SessionBean
和
EntityBean
代码
GzlLm
MSN
:
GzlLm@msn.com
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
配置文件,进一步的扩充,使开发
-
〉测试
-
〉打包
-
〉部署自动化,能提高开发效率。