Copyright © 2006 ObjectWeb Consortium
This work is licensed under the Creative Commons Attribution-ShareAlike License. To view a copy of this license,visit http://creativecommons.org/licenses/by-sa/2.0/deed.en or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
$Id: userguide.xml 283 2006-03-29 12:45:33Z studzine $
Abstract
The EasyBeans user guide is intended for developers wanting to develop EJB3 applications.
Table of Contents
Table of Contents
EJB3 is included in the next J2EE specification, JAVA EE 5. ( http://java.sun.com/javaee/5/ )
The EJB3 specification is defined in JSR 220, which can be found at the following location: http://www.jcp.org/en/jsr/detail?id=220
The publication is published as three separate files:
The core
The persistence provider
The simplified specification, which contains new features
EJB 2.x was too complex. Developers were using additional tools to make it easier.
XDoclet (Attribute oriented programming): http://xdoclet.sourceforge.net
Hibernate for persistence: http://www.hibernate.org
Simplifying EJB development should produce a wider range of Java EE developers.
The deployment descriptors are no longer required; everything can be accomplished using metadata annotations.
The CMP (Container Managed Persistence) has been simplified; it is now more like Hibernate or JDO.
Programmatic defaults have been incorporated. For example, the transaction model is set to REQUIRED by default. The value needs to be set only if a specific value other than the default value is desired.
The use of checked exceptions is reduced; the RemoteException is no longer mandatory on each remote business method.
Inheritance is now allowed; therefore, beans can extend some of the base code.
The native SQL queries are supported as an EJB-QL (Query Language) enhancement.
Metadata annotations is new. FOr example, to define a stateless session bean, the @Stateless annotation is declared on the bean class.
The new business interceptors allow the developer to intercept each business method of the bean. The parameters and the returned values can be changed. For example, an interceptor can be used to determine the time that a method takes to execute.
In addition to business interceptors, the EJB2 callbacks ( such as
the ejbActivate()
method) are now defined using
annotation. For the ejbActivate()
method, this
is done with the help of @PostActivate
annotation. This annotation is set on a method that will be called by
the container.
Dependency injection makes it possible to request that the container inject resources, instead of trying to get them. For example, with the EJB2 specification, in order to get an EJB, the following code was used:
try { Object o = new InitialContext().lookup("java:comp/env/ejb/MyEJB"); myBean = PortableRemoteObject.narrow(o, MyInterface.clas); } catch (NamingException e) { .... }
With EJB3 this is done using only the following code:
@EJB private MyInterface myBean;
If the @EJB annotation is found in the
class, the container will look up and inject an instance of the bean in
the myBean
variable.
New features are linked to the persistence layer. For example,
EJB3 entities are POJO (Plain Old Java Object). This means that they can
be created by using the new()
constructor:
new MyEntity();
Also
entities are managed by an
EntityManager: entitymanager.persist(entity);
In addition, entities have callbacks available.
Anyone can check out source code from the SVN server using the following command (for GUI SVN client use, configuration values are the same as for command line use):
svn checkout svn://svn.forge.objectweb.org/svnroot/easybeans easybeans
Table of Contents
Before running the examples, be sure to follow the requirements for compiling and running these EasyBeans examples.
The ant tool is used to build the
examples. To compile the examples, use the
build.xml
file that is located in the examples
directory.
The command ant
install_all_examples
must be launched in the examples
directory:
Buildfile: /home/benoitf/workspace/easybeans/examples/build.xml install_all_examples: init: [mkdir] Created dir: /home/benoitf/workspace/easybeans/output/dist/clients [mkdir] Created dir: /home/benoitf/workspace/easybeans/output/dist/ejbjars [mkdir] Created dir: /home/benoitf/workspace/easybeans/clients compile: [javac] Compiling 5 source files to /home/benoitf/workspace/easybeans/output/classes install.persistence: install: [copy] Copying 4 files to /home/benoitf/workspace/easybeans/ejb3s/stateless.jar [jar] Building jar: /home/benoitf/workspace/easybeans/clients/client-stateless.jar init: compile: [javac] Compiling 3 source files to /home/benoitf/workspace/easybeans/output/classes install.persistence: install: [copy] Copying 2 files to /home/benoitf/workspace/easybeans/ejb3s/stateful.jar [jar] Building jar: /home/benoitf/workspace/easybeans/clients/client-stateful.jar init: compile: [javac] Compiling 4 source files to /home/benoitf/workspace/easybeans/output/classes install.persistence: [mkdir] Created dir: /home/benoitf/workspace/easybeans/ejb3s/entitybean.jar/META-INF [copy] Copying 1 file to /home/benoitf/workspace/easybeans/ejb3s/entitybean.jar/META-INF install: [copy] Copying 4 files to /home/benoitf/workspace/easybeans/ejb3s/entitybean.jar [jar] Building jar: /home/benoitf/workspace/easybeans/clients/client-entitybean.jar BUILD SUCCESSFUL Total time: 4 secondsThe examples are copied under the
ejb3s/
folder of the project and are
available for the deployment.
![]() | Note |
---|---|
If the EasyBeans server is running, it will detect these new applications and deploy them automatically. |
Each example has its own build.xml
file; this
allows each example to be run independently.
The build.xml
file for this example is
located in the examples/statelessbean
folder.
This example is a stateless session bean. It contains a
helloWorld()
method that displays text on the
server side. Additionally, it demonstrates the use of EJB3 annotation,
such as @Stateless.
The trace()
method is annotated with
@AroundInvoke EJB3 annotation. This method
will be called at each call on a business method. The business methods
are defined in the interface implemented by the SessionBean
class.
The signature of the method annotated by @AroundInvoke when it is defined in the bean class, must follow this signature:
(private|protected|public) Object methodName(InvocationContext invocationContext)
throws Exception;
![]() | Note |
---|---|
As a new feature of the EJB3, the bean's interface does not need to extend the Remote interface. |
If the server is not available, it must be run by following the steps described in Chapter 3, "Running the EasyBeans Server."
The stateless session bean must be deployed. If the bean has
been installed in the ejb3s
folder, this is done automatically.
On the server side, the following output should be seen:
[java] INFO: Creating container for archive /home/benoitf/workspace/easybeans/ejb3s/stateless.jar. [java] INFO: Analyze elapsed during : 95 ms [java] INFO: Binding bean XXX with interface XXX into registry with jndi name XXX [java] INFO: Enhancement elapsed during : 105 ms [java] INFO: Container started in : 274 ms
Once this information is displayed on the screen, the container is ready to receive client calls.
Once the container has been started, the client can be launched.
Run the client with the following ant command: ant run.client
If the client runs successfully, the following output is displayed:
[java] Calling helloWorld method... [java] Add 1 + 2... [java] Sum = '3'.
![]() | Note |
---|---|
In the client's code, the use of the PortableRemoteObject.narrow() call is no longer required. |
The build.xml
file for this example is
located in the examples/statefulbean
folder.
This is an example of a stateful session bean using the
SessionSynchronization
interface.
It uses the @Stateful annotation and uses the default transaction model, which is REQUIRED.
If the server is not available, it must be run by following the steps described in Chapter 3, "Running the EasyBeans Server."
The stateful session bean must be deployed. It is done
automatically if the bean has been installed in the ejb3s
folder.
On the server side, the following output should be seen:
[java] INFO: Creating container for archive /home/benoitf/workspace/easybeans/ejb3s/stateful.jar. [java] INFO: Analyze elapsed during : 89 ms [java] INFO: Enhancement elapsed during : 76 ms [java] INFO: Binding bean XXX with interface XXX into registry with jndi name XXX [java] INFO: Container started in : 251 ms
Once this information is displayed on the screen, the container is ready to receive client calls.
Once the container has been started, the client can be launched.
Run the client with the following ant command: ant run.client
If the client runs successfully, the following output is displayed:
[java] Start a first transaction [java] First request on the new bean [java] Second request on the bean [java] Commit the transaction [java] Start a second transaction [java] Buy 50 amount. [java] Rollback the transaction [java] after rollback, value = 30 [java] Request outside any transaction [java] Check that value = 30 [java] ClientStateful OK. Exiting.
The build.xml
file for this example is
located in the examples/entitybean
folder.
This is an example of an entity bean. It describes how to use the new Java Persistence Model of an EJB3 persistence provider. To access EJB3 entities that are POJO, a stateless session bean is used. It is a facade bean.
The Entity class is a POJO class annotated with @Entity. The entities class is managed by the persistence provider.
Currently, the persistence provider is supplied by the Hibernate product, but the ObjectWeb Speedo product should be available soon. Users will have the choice between providers.
This example uses the @Stateful annotation and uses the default transaction model, which is REQUIRED.
The example shows an entity bean using EJB3 Hibernate-prototype persistence provider.
If the server is not available, it must be run following the steps described in Chapter 3, "Running the EasyBeans Server."
The entity bean must be deployed. It is done automatically if
the bean has been installed in the ejb3s
folder.
On the server side, the following output should be seen:
[java] INFO: Creating container for archive /home/benoitf/workspace/easybeans/ejb3s/entitybean.jar. [java] INFO: Analyze elapsed during : 95 ms [java] INFO: Enhancement elapsed during : 102 ms [java] INFO: No persistence provider was set, set to value org.hibernate.ejb.HibernatePersistence. [java] INFO: Hibernate 3.1.1 [java] INFO: Using provided datasource [java] INFO: RDBMS: HSQL Database Engine, version: 1.8.0 [...] [java] INFO: Binding bean XXX with interface XXX into registry with jndi name XXX [java] INFO: Container started in : 2010 ms
Once this information is displayed on the screen, the container is ready to receive client calls.
Table of Contents
This example illustrates the basics of an EJB3 application, showing all the steps used to build and run the EJB.
The only addtional information required is to know how to run the server.
The HelloWorld bean is divided into two parts: the business interface, and the class implementing this interface.
The interface declares only one method:
helloWorld()
package org.objectweb.easybeans.tutorial.helloworld; /** * Interface of the HelloWorld example. * @author Florent Benoit */ public interface HelloWorldInterface { /** * Hello world. */ void helloWorld(); }
![]() | Note |
---|---|
Even if this interface is used as a remote interface, it does
not need to extend |
The following code implements the existing interface:
package org.objectweb.easybeans.tutorial.helloworld; /** * Business code for the HelloWorld interface. * @author Florent Benoit */ public class HelloWorldBean implements HelloWorldInterface { /** * Hello world implementation. */ public void helloWorld() { System.out.println("Hello world !"); } }
![]() | Note |
---|---|
At this moment, the bean is not an EJB; this is only a class implementing an interface. |
Now that the EJB code has been written, it is time to define the EJB application.
This bean will be a stateless session bean, thus the class will be annotated with @Stateless annotation.
In addition, the interface must be a remote interface to be available for remote clients. This is done by using the @Remote annotation.
package org.objectweb.easybeans.tutorial.helloworld;
/**
* Business code for the HelloWorld interface.
* @author Florent Benoit
*/
@Stateless
@Remote(HelloWorldInterface.class)
public class HelloWorldBean implements HelloWorldInterface {
/**
* Hello world implementation.
*/
public void helloWorld() {
System.out.println("Hello world !");
}
}
![]() | Note |
---|---|
If a class implements a single interface, this interface is defined as a local interface by default. |
The client can access the business interface directly and can call the methods of the bean directly.
package org.objectweb.easybeans.tutorial.helloworld; import javax.naming.Context; import javax.naming.InitialContext; /** * Client of the helloworld bean. * @author Florent Benoit */ public final class Client { /** * JNDI name of the bean. */ private static final String JNDI_NAME = "org.objectweb.easybeans.tutorial.helloworld.HelloWorldBean" + "_" + HelloWorldInterface.class.getName() + "@Remote" /** * Utility class. No public constructor */ private Client() { } /** * Main method. * @param args the arguments (not required) * @throws Exception if exception is found. */ public static void main(final String[] args) throws Exception { Context initialContext = new InitialContext(); HelloWorldInterface businessItf = (HelloWorldInterface) initialContext.lookup(JNDI_NAME); System.out.println("Calling helloWorld method..."); businessItf.helloWorld(); } }
![]() | Note |
---|---|
The client does not call the PortableRemoteObject.narrow() method. Also, no create() method is required. |
An interceptor can be defined in the bean class or in another class. In this example, it will be defined in the bean's class. A business interceptor is defined by using the @AroundInvoke annotation.
The following interceptor will print the name of the method that is invoked. Of course, this can be extended to do more stuff.
/** * Dummy interceptor. * @param invocationContext contains attributes of invocation * @return method's invocation result * @throws Exception if invocation fails */ @AroundInvoke public Object intercept(final InvocationContext invocationContext) throws Exception { System.out.println("Intercepting method '" + invocationContext.getMethod().getName() + "'."); try { return invocationContext.proceed(); } finally { System.out.println("End of intercepting."); } }
![]() | Caution |
---|---|
Don't forget to call the |
The bean can be notified of some lifecycle events, for example when a bean is created or destroyed.
In the following example, a method of the bean will received an event when an instance of the bean is built. This is done by using the @PostConstruct annotation.
Llifecycle interceptors of a bean may be defined in another class.
/** * Notified of postconstruct event. */ @PostConstruct public void notified() { System.out.println("New instance of this bean"); }