在所有的
				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.javapackage 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>