在所有的
EJB3.0
規范中定義的
EJB
,都不必實現
Home
接口。
一個會話
Bean
必須有一個業務接口,這個接口由會話
Bean
來實現,或者也可以由會話
Bean
來產生。這樣,你可以只寫一個文件,就可以生成業務邏輯實現類、遠程接口、本地接口等。
… @Remote @Local @Stateless
public class CounterBean { …… }
|
在目前
jboss
的實現中,必須要有一個獨立的業務接口。
這個接口不必實現
EJBObject
或者
EJBLocalObject
。
一個無狀態會話
Bean
必須使用
Stateless
注釋,以表明它是一個無狀態的會話
Bean
。
EJB
容器將根據這個注釋來判定它的類型?;蛘邔崿F
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>