Recently I did some research on EJB3 programming, find that it's really simple than programming with previous EJB version. Coding in EJB2.X or previous version is really a nightmare for most developers, maybe for this, EJB3 gives me much more impression than Spring when it first comes to me, this article is the first one of these series articles which record the new knowledge I find interesting in EJB3.
Well, let's begin.
EJB3 is simple with AOP and DI, there is no Home interface any more, only with Service Interface and your Service implementation you can create an typical EJB3 application. I will create a simple hello world program in this article, the service interface as follow:
1 package com.ramon.expejb3.session;
2
3 import javax.ejb.Remote;
4
5 @Remote
6 public interface Greeting {
7
8 /**
9 * say hello test
10 * @param name
11 */
12 void greeting(String name);
13
14 }
It's really simple, especially for you that are familiar with programing with Interface, after that is the service implementation code:
1 package com.ramon.expejb3.session.impl;
2
3 import javax.annotation.PostConstruct;
4 import javax.annotation.PreDestroy;
5 import javax.ejb.Stateless;
6
7 import com.ramon.expejb3.session.Greeting;
8
9 @Stateless(name = "Greeting")
10 public class GreetingBean implements Greeting {
11
12 @PostConstruct
13 public void init() {
14 System.out.println("Init Greeting Bean.");
15 }
16
17 @PreDestroy
18 public void destroy() {
19 System.out.println("Garbage collect Greeting Bean.");
20 }
21
22 /* (non-Javadoc)
23 * @see com.ramon.expejb3.session.Greeting#greeting(java.lang.String)
24 */
25 public void greeting(String name) {
26 System.out.println("Hello " + name + ".");
27 }
28 }
29
Still simple and very self-explanation,
@Stateless(name = "Greeting") specify the JNDI name for client invocation. OK, that's all for our EJB jar file, no more file needed for this simple hello application. Execute your ANT script make a jar for it, part of ANT script may look like:
1 <target name="prepareexpejb3" description="Create exp_jsf distribution.">
2 <mkdir dir="${dist.dir}" />
3 <mkdir dir="${build.dir}" />
4 <mkdir dir="${build.core.dir}"/>
5 </target>
6
7 <!-- =================================
8 target: Compile expejb3 classes
9 ================================= -->
10 <target name="compileexpejb3" depends="cleanDist,prepareexpejb3">
11 <javac destdir="${build.core.dir}" debug="yes" deprecation="on" srcdir="${src.dir}">
12 <include name="${core.src.dir}/**" />
13 <classpath refid="expejb3.classpath" />
14 </javac>
15
16 </target>
17
18 <!-- =================================
19 target: Create EJB3 jar
20 ================================= -->
21 <target name="createEJB3Jar" depends="compileexpejb3">
22 <jar jarfile="${dist.dir}/${expejb3.core.name}.jar">
23 <fileset dir="${build.core.dir}"></fileset>
24 </jar>
25 </target>
Put the EJB jar into jboss server server\default\deploy, you should see some log from jboss console like:
1 10:59:27,036 INFO [JmxKernelAbstraction] creating wrapper delegate for: org.jboss.ejb3.stateless.St
2 atelessContainer
3 10:59:27,051 INFO [JmxKernelAbstraction] installing MBean: jboss.j2ee:jar=expejb3core.jar,name=Gree
4 ting,service=EJB3 with dependencies:
5 10:59:27,208 INFO [EJBContainer] STARTED EJB: com.ramon.expejb3.session.impl.GreetingBean ejbName:
6 Greeting
Which mean that you have successfully deploy your EJB into jboss server, create a client code to invoke your EJB service:
1 package com.ramon.expejb3.session;
2
3 import java.util.Properties;
4
5 import javax.naming.Context;
6 import javax.naming.InitialContext;
7
8 import junit.framework.TestCase;
9
10 public class ExpEJB3BaseTestCase extends TestCase {
11
12 private Properties properties = null;
13
14 private Context context;
15
16 protected void setUp() throws Exception {
17 super.setUp();
18 properties = new Properties();
19 properties.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
20 properties.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
21 properties.put("java.naming.provider.url", "localhost:1099");
22 context = new InitialContext(properties);
23 }
24
25 protected void tearDown() throws Exception {
26 super.tearDown();
27 context = null;
28 properties = null;
29 }
30
31 public final Context getContext() {
32 return context;
33 }
34
35 public final void setContext(Context context) {
36 this.context = context;
37 }
38
39 }
40
1 package com.ramon.expejb3.session.impl;
2
3 import javax.naming.NamingException;
4
5 import com.ramon.expejb3.session.ExpEJB3BaseTestCase;
6 import com.ramon.expejb3.session.Greeting;
7
8 public class GreetingBeanTest extends ExpEJB3BaseTestCase {
9
10 public void testGreeting() {
11 try {
12 Greeting greetService = (Greeting)this.getContext().lookup("Greeting/remote");
13 greetService.greeting("Ramon");
14 } catch (NamingException e) {
15 // TODO Auto-generated catch block
16 e.printStackTrace();
17 }
18 }
19
20 }
21
That's really simple, right? What you should note is that you must include following jars into your classpath when you run this clien test case, otherwise you will get the annoying classNotFound Exception:
1 concurrent.jar
2 jboss-aop-jdk50.jar
3 jboss-aspect-library-jdk50.jar
4 jboss-common.jar
5 jboss-ejb3.jar
6 jboss-ejb3-client.jar
7 jboss-remoting.jar
8 jbossx-client.jar
9 jboss-transaction-client.jar
10 jnp-client.jar