在所有的
EJB3.0
规范中定义的
EJB
,都不必实现
Home
接口。
一个会话
Bean
必须有一个业务接口,这个接口由会话
Bean
来实现,或者也可以由会话
Bean
来产生。这样,你可以只写一个文件,就可以生成业务逻辑实现类、远程接口、本地接口等。
… @Remote @Local @Stateless
public class CounterBean { …… }
|
在目前
jboss
的实现中,必须要有一个独立的业务接口。
这个接口不必实现
EJBObject
或者
EJBLocalObject
。
一个无状态会话
Bean
必须使用
Stateless
注释,以表明它是一个无状态的会话
Bean
。
EJB
容器将根据这个注释来判定它的类型。或者实现
javax.ejb.SessionBean
接口。
一个无状态的会话
Bean
可以实现
setSessionContext
方法,也可以不实现。
一个无状态的会话
Bean
可以实现
ejbCreate/ejbRemove
方法。
一个无状态的会话
Bean
可以通过依赖注入(
Dependency Injection
)也就是现在吵得挺火的
IOC
获取容器的资源和环境属性。详细介绍请看后面的章节。
在
Eclipse
中导入本文提供的例子
Stateless
。
这个例子是一个计数器的例子,它实现了两个业务方法
add
和
getNumber
,
add
方法就是给计数器加上一个整数值,
getNumber
方法将得到计数器的当前值。
这个例子主要有
5
个文件:
Counter.java
:业务接口。
CounterBean.java
:业务实现类。将来我们开发的
EJB
也都是这样命名(在接口名上加上
Bean
)。
Client.java
:测试
EJB
的客户端类。
jndi.properties
:
jndi
属性文件,提供访问
jdni
的基本配置属性。
Build.xml
:
ant
配置文件,用以编译、发布、测试、清除
EJB
。
下面针对每个文件的内容做一个介绍。
Counter.java package com.kuaff.ejb3.stateless;
import javax.ejb.Remote;
@Remote
public interface Counter {
public int add(int i);
public int getNumber(); }
|
这个接口很简单,定义了上面介绍的两个业务方法,同时,我们为这个接口加上了
Remote
注释,这样我们的远程客户端就可以通过
JNDI
名称查找到它,并调用它的业务方法。
它的
JNDI
名称怎么配置呢?
你不必配置它的
JNDI
名称,也不必写它的配置文件。在
JBOSS
实现的
EJB3.0
中,你不必写任何的
EJB
部署文件和
jboss
部署文件。
JBOSS
默认使用接口的全称作为它的
JNDI
名。在上面的例子中,它的全称就是:
com.kuaff.ejb3.stateless.Counter
,你也可以通过
Counter.class.forName()
得到。
CounterBean.java
package com.kuaff.ejb3.stateless;
import javax.ejb.Stateless;
@Stateless
public class CounterBean implements Counter {
private int number = 0;
//
给计数器加上
i
public int add(int i)
{
number += i;
return number;
}
//
得到当前的计数
public int getNumber()
{
return number;
}
}
|
这个是计数器的实现类。注意这个类使用
Stateless
做了注释,这是必须的。
Client.java
package com.kuaff.ejb3.stateless; import javax.naming.InitialContext; import javax.naming.NamingException;
public class Client
{
public static void main(String[] args)
{
InitialContext ctx;
try
ctx = new InitialContext();
Counter counter = (Counter) ctx.lookup(Counter.class.getName());
counter.add(10);
System.out.println("
当前的
number:" + counter.getNumber());
counter.add(10);
System.out.println("
当前的
number:" + counter.getNumber());
Counter counter2 = (Counter) ctx.lookup(Counter.class.getName());
counter2.add(10);
System.out.println("
当前的
number:" + counter2.getNumber());
catch (NamingException e)
{
e.printStackTrace();
}
}
}
|
这个类用来测试我们发布的计数器
EJB
。首先通过
ctx = new InitialContext();
得到上下文,然后通过
lookup
查找计数器,然后给计数器加
10
,显示当前的计数器信息。
jndi.properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
|
这个文件配置了
JNDI
操作所需的属性,因为我们是测试本机的
EJB
服务,所以不必修改上面的属性。
Build.xml
<
project name="kuaff_ejb3_tutorial" default="ejbjar" basedir="."
>
<
property environment="env"/
>
<
property name="src.dir" value="${basedir}/src"/
>
<
property name="jboss.home" value="${env.JBOSS_HOME}"/
>
<
property name="build.dir" value="${basedir}/build"/
>
<
property name="build.classes.dir" value="${build.dir}/classes"/
>
<
path id="classpath"
>
<
fileset dir="${jboss.home}/lib"
>
<
include name="**/*.jar"/
>
<
/fileset
>
<
fileset dir="${jboss.home}/server/all/lib"
>
<
include name="**/*.jar"/
>
<
/fileset
>
<
fileset dir="${jboss.home}/server/all/deploy/ejb3.deployer"
>
<
include name="*.jar"/
>
<
/fileset
>
<
fileset dir="${jboss.home}/server/all/deploy/jboss-aop.deployer"
>
<
include name="*.jar"/
>
<
/fileset
>
<
pathelement location="${build.classes.dir}"/
>
<
pathelement location="${basedir}"/
>
<
/path
>
<
property name="build.classpath" refid="classpath"/
>
<
target name="prepare"
>
<
mkdir dir="${build.dir}"/
>
<
mkdir dir="${build.classes.dir}"/
>
<
/target
>
<
target name="compile" depends="prepare"
>
<
javac srcdir="${src.dir}" destdir="${build.classes.dir}" debug="on" deprecation="on" optimize="off" includes="**"
>
<
classpath refid="classpath"/
>
<
/javac
>
<
/target
>
<
target name="ejbjar" depends="compile"
>
<
jar jarfile="build/StatelessSample.ejb3"
>
<
fileset dir="${build.classes.dir}"
>
<
include name="**/*.class"/
>
<
/fileset
>
<
/jar
>
<
copy file="build/StatelessSample.ejb3" todir="${jboss.home}/server/all/deploy"/
>
<
/target
>
<
target name="run" depends="ejbjar"
>
<
java classname="com.kuaff.ejb3.stateless.Client" fork="yes" dir="."
>
<
classpath refid="classpath"/
>
<
/java
>
<
/target
>
<
target name="clean.db"
>
<
delete dir="${jboss.home}/server/all/data/hypersonic"/
>
<
/target
>
<
target name="clean"
>
<
delete dir="${build.dir}"/
>
<
delete file="${jboss.home}/server/all/deploy/StatelessSample.ejb3"/
>
<
/target
>
<
/project
>
|
请运行
{$JBOSS_HOME}/bin
目录下的
run.bat: run –c all,
启动
JBOSS
。
在
Eclipse
的
Ant
视图中执行
ejbjar target
。或者在命令行下,进入到此工程目录下,执行
ant ejbjar,
将编译打包发布此
EJB
。
在
Eclipse
的
Ant
视图中执行
run target
。或者在命令行下,进入到此工程目录下,执行
ant run,
测试这个
EJB
。
G:\eclipse\eclipse-SDK-3.2RC7-win32\workspace2\test>ant run
Buildfile: build.xml
prepare:
compile:
[javac] Compiling 1 source file to G:\eclipse\eclipse-SDK-3.2RC7-win32\workspace2\test\build\classes
ejbjar:
[jar] Building jar: G:\eclipse\eclipse-SDK-3.2RC7-win32\workspace2\test\build\StatelessSample.ejb3
[copy] Copying 1 file to G:\jboss\jboss-4.0.2\server\all\deploy
run:
[java] CounterRemote.class.getName()=====================================com.kuaff.ejb3.stateless.CounterRemote
[java] log4j:WARN No appenders could be found for logger (org.jboss.remoting.Client).
[java] log4j:WARN Please initialize the log4j system properly.
[java] 当前的number:30
[java] 当前的number:40
[java] 当前的 number:50
BUILD SUCCESSFUL
Total time: 22 seconds
G:\eclipse\eclipse-SDK-3.2RC7-win32\workspace2\test>