EasyBeans is an open source implementation by ObjectWeb of the EJB3 container specification. 
X Wiki

EasyBeans User's guide

Florent BENOIT

EasyBeans
OW2 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 4784 2009-03-11 10:34:46Z benoitf $

Abstract

The EasyBeans user guide is intended for developers wanting to develop EJB3 applications.


Chapter 1. Introduction to EJB3

1.1. Overview

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:

  1. The core

  2. The persistence provider

  3. The simplified specification, which contains new features

The EJB3 persistence provider is plugged into the EJB3 container. Available persistence providers are: Hibernate EntityManager, Apache OpenJPA, TopLink Essentials, and Eclipse Link etc.

1.2. The Advantage of EJB3

EJB 2.x was too complex. Developers were using additional tools to make it easier.

The main focus for this specification is on Ease Of Development (EoD). One major way this has been simplified is by using metadata attribute annotations suppported by JDK 5.0.

Simplifying EJB development should produce a wider range of Java EE developers.

1.3. EJB2 vs EJB3: EoD

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.

1.4. New Features

1.4.1. Metadata Annotations

Metadata annotations is new. For example, to define a stateless session bean, the @Stateless annotation is declared on the bean class.

1.4.2. Business Interceptors

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.

1.4.3. Lifecycle Interceptors

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.

1.4.4. Dependency Injection

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.

1.4.5. Persistence

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.

Chapter 2. Getting EasyBeans From the SVN Repository

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/trunk/easybeans

Chapter 3. Using the Examples

3.1. Compiling the Examples

3.1.1. Requirements

Before running the examples, be sure to follow the requirements for compiling and running these EasyBeans examples.

3.1.2. Compile

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:

$ ant install_all_examples
Buildfile: build.xml

install_all_examples:

init-maven-task:

init:
    [mkdir] Created dir: /home/benoitf/workspace/easybeans/output/example-classes
    [mkdir] Created dir: /home/benoitf/workspace/easybeans/clients
    [mkdir] Created dir: /home/benoitf/workspace/easybeans/webapps

compile:
    [javac] Compiling 4 source files to /home/benoitf/workspace/easybeans/output/example-classes

ejb:

ejb-standalone:
[easybeans:ejb] Building Ejb in '/home/benoitf/workspace/easybeans/easybeans-deploy/entitybean.jar'.
[easybeans:ejb] Building jar: /home/benoitf/workspace/easybeans/easybeans-deploy/entitybean.jar

war:

ear:

client:

client-standalone:
[easybeans:client] Building Client in '/home/benoitf/workspace/easybeans/clients/client-entitybean.jar'.
[easybeans:client] Building jar: /home/benoitf/workspace/easybeans/clients/client-entitybean.jar

install:

init-maven-task:

init:

compile:
    [javac] Compiling 3 source files to /home/benoitf/workspace/easybeans/output/example-classes

ejb:

ejb-standalone:
[easybeans:ejb] Building Ejb in '/home/benoitf/workspace/easybeans/easybeans-deploy/mdb.jar'.
[easybeans:ejb] Building jar: /home/benoitf/workspace/easybeans/easybeans-deploy/mdb.jar

war:

ear:

client:

client-standalone:
[easybeans:client] Building Client in '/home/benoitf/workspace/easybeans/clients/client-mdb.jar'.
[easybeans:client] Building jar: /home/benoitf/workspace/easybeans/clients/client-mdb.jar

install:

init-maven-task:

init:

compile:
    [javac] Compiling 7 source files to /home/benoitf/workspace/easybeans/output/example-classes

ejb:

ejb-standalone:
[easybeans:ejb] Building Ejb in '/home/benoitf/workspace/easybeans/easybeans-deploy/migration21.jar'.
[easybeans:ejb] Building jar: /home/benoitf/workspace/easybeans/easybeans-deploy/migration21.jar

war:

ear:

client:

client-standalone:
[easybeans:client] Building Client in '/home/benoitf/workspace/easybeans/clients/client-migration21.jar'.
[easybeans:client] Building jar: /home/benoitf/workspace/easybeans/clients/client-migration21.jar

install:

init-maven-task:

init:

compile:
    [javac] Compiling 5 source files to /home/benoitf/workspace/easybeans/output/example-classes

ejb:

ejb-standalone:
[easybeans:ejb] Building Ejb in '/home/benoitf/workspace/easybeans/easybeans-deploy/security.jar'.
[easybeans:ejb] Building jar: /home/benoitf/workspace/easybeans/easybeans-deploy/security.jar

war:

ear:

client:

client-standalone:
[easybeans:client] Building Client in '/home/benoitf/workspace/easybeans/clients/client-security.jar'.
[easybeans:client] Building jar: /home/benoitf/workspace/easybeans/clients/client-security.jar

install:

init-maven-task:

init:

compile:
    [javac] Compiling 7 source files to /home/benoitf/workspace/easybeans/output/example-classes

ejb:

ejb-standalone:
[easybeans:ejb] Building Ejb in '/home/benoitf/workspace/easybeans/easybeans-deploy/stateless.jar'.
[easybeans:ejb] Copying 5 files to /home/benoitf/workspace/easybeans/easybeans-deploy/stateless.jar

war:

war-standalone:
[easybeans:war] Building War in '/home/benoitf/workspace/easybeans/webapps/web.war'.
[easybeans:war] Copying 6 files to /home/benoitf/workspace/easybeans/webapps/web.war/WEB-INF/classes
[easybeans:war] Copying 1 file to /home/benoitf/workspace/easybeans/webapps/web.war/WEB-INF

ear:

client:

client-standalone:
[easybeans:client] Building Client in '/home/benoitf/workspace/easybeans/clients/client-stateless.jar'.
[easybeans:client] Building jar: /home/benoitf/workspace/easybeans/clients/client-stateless.jar

install:

init-maven-task:

init:

compile:
    [javac] Compiling 3 source files to /home/benoitf/workspace/easybeans/output/example-classes

ejb:

ejb-standalone:
[easybeans:ejb] Building Ejb in '/home/benoitf/workspace/easybeans/easybeans-deploy/stateful.jar'.
[easybeans:ejb] Building jar: /home/benoitf/workspace/easybeans/easybeans-deploy/stateful.jar

war:

ear:

client:

client-standalone:
[easybeans:client] Building Client in '/home/benoitf/workspace/easybeans/clients/client-stateful.jar'.
[easybeans:client] Building jar: /home/benoitf/workspace/easybeans/clients/client-stateful.jar

install:

init-maven-task:

init:

compile:
    [javac] Compiling 6 source files to /home/benoitf/workspace/easybeans/output/example-classes

ejb:

ejb-standalone:
[easybeans:ejb] Building Ejb in '/home/benoitf/workspace/easybeans/easybeans-deploy/timer.jar'.
[easybeans:ejb] Building jar: /home/benoitf/workspace/easybeans/easybeans-deploy/timer.jar

war:

ear:

client:

client-standalone:
[easybeans:client] Building Client in '/home/benoitf/workspace/easybeans/clients/client-timer.jar'.
[easybeans:client] Building jar: /home/benoitf/workspace/easybeans/clients/client-timer.jar

install:

init-maven-task:

init:

compile:
    [javac] Compiling 5 source files to /home/benoitf/workspace/easybeans/output/example-classes

ejb:

ejb-standalone:

war:

war-standalone:

ear:
[easybeans:ear] Building Ear in '/home/benoitf/workspace/easybeans/easybeans-deploy/ear3.ear'.
      [ejb] Building Ejb in '/tmp/easybeans-ant33717.tmp'.
      [ejb] Building jar: /tmp/easybeans-ant33717.tmp
      [war] Building War in '/tmp/easybeans-ant33718.tmp'.
      [war] Building war: /tmp/easybeans-ant33718.tmp
[easybeans:ear] Building jar: /home/benoitf/workspace/easybeans/easybeans-deploy/ear3.ear

client:

install:

BUILD SUCCESSFUL
Total time: 22 seconds

The examples are copied under the easybeans-deploy/ folder of the project and are available for the deployment.

[Note] Note

If the EasyBeans server is running, it will detect these new applications and deploy them automatically.

3.2. Running Examples

Each example has its own build.xml file; this allows each example to be run independently.

3.2.1. Stateless Session Bean

The build.xml file for this example is located in the examples/statelessbean folder.

3.2.1.1. Description

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] Note

As a new feature of EJB3, the bean's interface does not need to extend the Remote interface.

3.2.1.2. Running the Server

If the server is not available, it must be run by following the steps described in Chapter 3, "Running the EasyBeans Server" of the developer's guide.

3.2.1.3. Deploying the Bean

The stateless session bean must be deployed. If the bean has been installed in the easybeans-deploy folder, this is done automatically.

On the server side, the following output should display:

     [java] 5/16/07 10:59:32 AM (I) AbsDeployer.deployEJB : Deploying EJB3DeployableImpl[archive=easybeans-deploy/stateless.jar]
     [java] 5/16/07 10:59:32 AM (I) JContainer3.start : Container started in : 408 ms

Once this information is displayed on the screen, the container is ready to receive client calls.

3.2.1.4. Running the Client

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] Note

In the client's code, the use of the PortableRemoteObject.narrow() call is no longer required.

3.2.2. Stateful Session Bean

The build.xml file for this example is located in the examples/statefulbean folder.

3.2.2.1. Description

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.

3.2.2.2. Running the Server

If the server is not available, it must be run by following the steps described in Chapter 3, "Running the EasyBeans Server" of the developer's guide.

3.2.2.3. Deploying the Bean

The stateful session bean must be deployed. It is done automatically if the bean has been installed in the easybeans-deploy folder.

On the server side, the following output should be seen:

     [java] 5/16/07 10:59:37 AM (I) AbsDeployer.deployEJB : Deploying EJB3DeployableImpl[archive=easybeans-deploy/stateful.jar]
     [java] 5/16/07 10:59:37 AM (I) JContainer3.start : Container started in : 94 ms

Once this information is displayed on the screen, the container is ready to receive client calls.

3.2.2.4. Running the Client

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.

3.2.3. Entity Bean

The build.xml file for this example is located in the examples/entitybean folder.

3.2.3.1. Description

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.

3.2.3.2. Running the Server

If the server is not available, it must be run following the steps described in Chapter 3, "Running the EasyBeans Server" of the developer's guide.

3.2.3.3. Deploying the Bean

The entity bean must be deployed. It is done automatically if the bean has been installed in the easybeans-deploy folder.

On the server side, the following output should be seen:

     [java] 5/16/07 10:59:36 AM (I) AbsDeployer.deployEJB : Deploying EJB3DeployableImpl[archive=easybeans-deploy/entitybean.jar]
     [java] 5/16/07 10:59:36 AM (I) JPersistenceUnitInfoHelper.getPersistenceUnitInfo : No persistence provider was set, set to value org.hibernate.ejb.HibernatePersistence.
     [java] 5/16/07 10:59:36 AM (I) JPersistenceUnitInfoHelper.getPersistenceUnitInfo : Found a default configuration for the persistence provider org.hibernate.ejb.HibernatePersistence
     [java] 5/16/07 10:59:36 AM (I) JPersistenceUnitInfoHelper.getPersistenceUnitInfo : Setting the property hibernate.transaction.manager_lookup_class with value org.hibernate.transaction.JOTMTransactionManagerLookup
     [java] 5/16/07 10:59:36 AM (I) JPersistenceUnitInfoHelper.getPersistenceUnitInfo : Setting the property hibernate.cache.provider_class with value org.hibernate.cache.HashtableCacheProvider
     [java] 5/16/07 10:59:36 AM (I) Ejb3Configuration.configure : Processing PersistenceUnitInfo [
     [java] name: entity
     [java] ...]
     [java] 5/16/07 10:59:36 AM (I) Ejb3Configuration.scanForClasses : found EJB3 Entity bean: org.objectweb.easybeans.examples.entitybean.Employee
     [java] 5/16/07 10:59:36 AM (I) Ejb3Configuration.scanForClasses : found EJB3 Entity bean: org.objectweb.easybeans.examples.entitybean.Employee
  ...
     [java] 5/16/07 10:59:36 AM (I) JContainer3.start : Container started in : 412 ms

Once this information is displayed on the screen, the container is ready to receive client calls.

3.2.3.4. Running the Client

Once the container has been started, the client can be launched.

The client is run with the following ant command: ant run.client

If the client runs successfully, the following output is displayed:

     [java] Employee with id 1 = Florent
     [java] Employee with id 2 = Whale

3.2.3.5. Properties for the persistence

These properties are defined in the META-INF/persistence.xml file.

3.2.3.5.1. JDBC Dialect

By default, the dialect used to communicate with the database is set to HSQL, as it is embedded in EasyBeans.

This dialect configuration is done with the following properties:

      <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
      <property name="toplink.target-database" value="HSQL"/>
      <property name="openjpa.jdbc.DBDictionary" value="hsql"/>

These properties are for Hibernate, Apache OpenJPA and Oracle TopLink Essentials.

3.2.3.5.2. Database (tables)

By default, the tables are created and the database is empty after loading the entity beans.

This configuration is done with the following properties:

      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      <property name="toplink.ddl-generation" value="drop-and-create-tables"/>
      <property name="toplink.ddl-generation.output-mode" value="database"/>
      <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>

In order to keep data in the database, this property should be changed.

3.2.4. Message Driven Bean

The build.xml file for this example is located in the examples/messagedrivenbean folder.

3.2.4.1. Description

This is an example of a message driven bean. It describes how to use a JMS message driven bean.

The class is a class annotated with @MessageDriven. Then, it is mapped to a JMS queue through the properties of this annotation.

@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "SampleQueue"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
        }
)

The Message Driven Bean will receive message from the SampleQueue queue.

3.2.4.2. Running the Server

If the server is not available, it must be run following the steps described in Chapter 3, "Running the EasyBeans Server" of the developer's guide.

3.2.4.3. Deploying the Bean

The entity bean must be deployed. It is done automatically if the bean has been installed in the easybeans-deploy folder.

On the server side, the following output should be seen:

5/16/07 2:42:24 PM (I) AbsDeployer.deployEJB : Deploying EJB3DeployableImpl[archive=easybeans-deploy/mdb.jar]
5/16/07 2:42:24 PM (I) JContainer3.start : Container started in : 267 ms

Once this information is displayed on the screen, the container is ready to receive client calls.

3.2.4.4. Running the Client

Once the container has been started, the client can be launched.

The client is run with the following ant command: ant run.client

If the client runs successfully, the following output is displayed:

run.client:
     [java] May 16, 2007 3:39:08 PM org.objectweb.carol.util.configuration.ConfigurationRepository init
     [java] INFO: No protocols were defined for property 'carol.protocols', trying with default protocol = 'jrmp'.
     [java] May 16, 2007 3:39:08 PM org.objectweb.util.monolog.wrapper.javaLog.Logger log
     [java] INFO: Debug.initialize() - a3debug.cfg
     [java] May 16, 2007 3:39:09 PM org.objectweb.util.monolog.wrapper.javaLog.Logger log
     [java] INFO: ReliableTcpConnection.windowSize=100
     [java] Message [ID:0.0.1026c2m1, text:Message_0] sent
     [java] Message [ID:0.0.1026c2m2, text:Message_1] sent
     [java] Message [ID:0.0.1026c2m3, text:Message_2] sent
     [java] Message [ID:0.0.1026c2m4, text:Message_3] sent
     [java] Message [ID:0.0.1026c2m5, text:Message_4] sent

And on the server side, the messages have been received:

Receiving a message named '(([email protected],messageID=ID:0.0.1026c2m1,destination=queue#0.0.1027,correlationId=null,deliveryMode=2,expiration=0,priority=4,redelivered=false,replyTo=null,timestamp=1179322749177,type=null),text=Message_0,RObody=true)'. with the content 'Message_0
Receiving a message named '((org.objectweb.joram.[email protected],messageID=ID:0.0.1026c2m4,destination=queue#0.0.1027,correlationId=null,deliveryMode=2,expiration=0,priority=4,redelivered=false,replyTo=null,timestamp=1179322749216,type=null),text=Message_3,RObody=true)'. with the content 'Message_3
Receiving a message named '(([email protected],messageID=ID:0.0.1026c2m5,destination=queue#0.0.1027,correlationId=null,deliveryMode=2,expiration=0,priority=4,redelivered=false,replyTo=null,timestamp=1179322749261,type=null),text=Message_4,RObody=true)'. with the content 'Message_4
Receiving a message named '(([email protected],messageID=ID:0.0.1026c2m2,destination=queue#0.0.1027,correlationId=null,deliveryMode=2,expiration=0,priority=4,redelivered=false,replyTo=null,timestamp=1179322749209,type=null),text=Message_1,RObody=true)'. with the content 'Message_1
Receiving a message named '(([email protected],messageID=ID:0.0.1026c2m3,destination=queue#0.0.1027,correlationId=null,deliveryMode=2,expiration=0,priority=4,redelivered=false,replyTo=null,timestamp=1179322749212,type=null),text=Message_2,RObody=true)'. with the content 'Message_2

3.2.5. Timer example

The build.xml file for this example is located in the examples/timerservice folder.

3.2.5.1. Description

This example shows the use of the @Timeout annotation on a method. The client invokes the TimerBean that will launch a timer. This timer will send a message to an MDB and then calls another bean which implements javax.ejb.TimedObject interface.

3.2.5.2. Running the server

If the server is not available, it must be run following the steps described in Chapter 3, "Running the EasyBeans Server" of the developer's guide.

3.2.5.3. Deploying the Bean

The timer bean example must be deployed. It is done automatically if the bean has been installed in the easybeans-deploy folder.

On the server side, the following output should display:

     [java] 9/29/07 3:52:50 PM (I) AbsDeployer.deployEJB : Deploying EJB3DeployableImpl[archive=easybeans-deploy/timer.jar]
     [java] 9/29/07 3:52:50 PM (I) JContainer3.start : Container started in : 104 ms

Once this information is displayed on the screen, the container is ready to receive client calls.

3.2.5.4. Running the Client

Once the container has been started, the client can be launched.

The client is run with the following ant command: ant run.client

If the client runs successfully, the following output is displayed on the client side:

run.client:
     [java] Sep 29, 2007 4:16:45 PM org.objectweb.carol.util.configuration.ConfigurationRepository init
     [java] INFO: No protocols were defined for property 'carol.protocols', trying with default protocol = 'jrmp'.
     [java] Calling init method that will fire a new timer...

The following output is displayed on the server side:

     [java]  SLSB -> Timer method called by the Timer Service.
     [java]  SLSB -> Timer received = '[email protected]'.
     [java]  SLSB -> Info object inside the timer object is 'Simple Serializable object'.
     [java]  SLSB -> Sending a message to a MDB which will start a timer.
     [java]  SLSB -> Message sent
     [java]  SLSB -> Call a local bean in order to start a new timer.
     [java]   MDB -> Timer method called by the Timer Service.
     [java]   MDB -> Timer received = '[email protected]'.
     [java]   MDB -> Info object inside the timer object is 'Timer started by the onMessage() method'.
     [java]  TimedBean -> Got a timer with value '[email protected]'.

3.2.6. Security example

The build.xml file for this example is located in the examples/security folder.

3.2.6.1. Description

This example illustrates the use of different Java EE 5 annotations which are linked to the security part.

The annotations used by the example are:

  • @DeclareRoles, which is used to declare the roles used by an EJB component

  • @RolesAllowed, which lists the authorized roles in order to call a method

  • @DenyAll, which denies the call to the method (for every role)

  • @RunAs, which sets a new identity when calling other EJBs

3.2.6.2. Running the Server

If the server is not available, it must be run following the steps described in Chapter 3, "Running the EasyBeans Server" of the developer's guide.

3.2.6.3. Deploying the Bean

The security bean example must be deployed. It is done automatically if the bean has been installed in the easybeans-deploy folder.

On the server side, the following output should display:

     [java] 5/16/07 10:59:37 AM (I) AbsDeployer.deployEJB : Deploying EJB3DeployableImpl[archive=easybeans-deploy/security.jar]
     [java] 5/16/07 10:59:37 AM (I) JContainer3.start : Container started in : 115 ms

Once this information is displayed on the screen, the container is ready to receive client calls.

3.2.6.4. Running the Client

Once the container has been started, the client can be launched.

The client is run with the following ant command: ant run.client

If the client runs successfully, the following output is displayed on the client side:

     run.client:
     [java] Oct 16, 2006 5:27:03 PM org.objectweb.carol.util.configuration.ConfigurationRepository init
     [java] INFO: No protocols were defined for property 'carol.protocols', trying with default protocol = 'jrmp'.
     [java] Calling methods that everybody can call...
     [java] Call a bean with run-as in order to have 'admin' role...
     [java] Access denied as expected (method is denied)

The following output is displayed on the server side:

     [java] someRolesAllowed() called
     [java] -> Caller is 'Principal[EasyBeans/Anonymous]'.
     [java] for run-as bean, caller is Caller is 'Principal[EasyBeans/Anonymous]
     [java] onlyAdminAllowed() called
     [java] -> Caller is 'Principal[admin]'.
     [java] someRolesAllowed() called
     [java] -> Caller is 'Principal[admin]'.

3.2.7. Pool example

The build.xml file for this example is located in the examples/pool folder.

3.2.7.1. Description

This example illustrates the definition of some values to limit the size of a pool. In the example, the pool size can be configured through the specific XML deployment descriptor or with annotations.

The example contains two kind of beans, Stateless beans and Message Driven beans.

The annotation used in the example is:

  • @Pool, for configuring the pool.

By using annotation to configure the pool, the @Pool annotation needs to be put on the class of the bean. For example : @Pool(max = MyInterface.MAX_INSTANCE)

By using XML configuration, the settings are located in the META-INF/easybeans.xml entry of the EJB-JAR file.

   ...
      <!-- Configure pool element with pool namespace -->
      <pool:pool>
        <!-- Sets the max value to 2 -->
        <pool:max>2</pool:max>
      </pool:pool>
  ...  

3.2.7.2. Running the Server

If the server is not available, it must be run following the steps described in Chapter 3, "Running the EasyBeans Server" of the developer's guide.

3.2.7.3. Deploying the Bean

The pool bean example must be deployed. It is done automatically if the bean has been installed in the easybeans-deploy folder.

On the server side, the following output should display:

3/7/08 5:26:26 PM (I) AbsDeployer.deployEJB : Deploying EJB3DeployableImpl[archive=easybeans-deploy/pool.jar]
3/7/08 5:26:28 PM (I) JContainer3.start : Container 'easybeans-deploy/pool.jar' [2 SLSB, 0 SFSB, 2 MDB] started in 1,388 ms

Once this information is displayed on the screen, the container is ready to receive client calls.

3.2.7.4. Running the Client

Once the container has been started, the client can be launched.

The client is run with the following ant command: ant run.client

If the client runs successfully, the following output is displayed on the client side:

run.client:
     [java] Mar 7, 2008 5:31:35 PM org.objectweb.carol.util.configuration.ConfigurationRepository init
     [java] Calling bean's methods...
     [java] Waiting some time before checking the number of instances...
     [java] Number of instances Annotation Bean = 5
     [java]   --> This value is OK, pool is limited to 5
     [java] Number of instances XML Bean = 2
     [java]   --> This value is OK, pool is limited to 2
     [java] 3/7/08 5:31:41 PM (I) Logger.log : Debug.initialize() - a3debug.cfg
     [java] 3/7/08 5:31:42 PM (I) Logger.log : ReliableTcpConnection.windowSize=100
     [java] Sending messages with multiple threads...
     [java] Waiting some time to ensure that all messages have been sent...
     [java] Look at the server side console to check pool values of MDB ...

The following output is displayed on the server side:

     [java] MDBAnnotationBean: Number of instances = '5', max = '5'.
     [java] MDBAnnotationBean: Number of instances = '5', max = '5'.
     [java] MDBAnnotationBean: Number of instances = '5', max = '5'.
     [java] MDBXMLBean:Number of instances = '2', max = '2'.
     [java] MDBAnnotationBean: Number of instances = '5', max = '5'.
     [java] MDBAnnotationBean: Number of instances = '5', max = '5'.
     [java] MDBXMLBean:Number of instances = '2', max = '2'.
     [java] MDBAnnotationBean: Number of instances = '5', max = '5'.

...

The instances are not exceeding the limits fixed in the example then everything is working fine.

3.2.8. Migration EJB 2.1/3.0 example

The build.xml file for this example is located in the examples/migrationejb21 folder.

3.2.8.1. Description

This example illustrates the use of annotations that provide Home and Remote interface for clients written for the EJB 2.1 specification.

The annotations used by the example are:

  • @Remote, for the definition of the business interface.

  • @RemoteHome, for defining the EJB 2.1 Remote Home interface.

  • @LocalHome, for defining the EJB 2.1 Local Home interface.

An EJB that is using these annotations can be used by an EJB3 client and a EJB 2.1 client. These annotations can be used to do a migration of your beans on the server side while the clients are the same.

3.2.8.2. Running the Server

If the server is not available, it must be run following the steps described in Chapter 3, "Running the EasyBeans Server" of the developer's guide.

3.2.8.3. Deploying the Bean

The migration bean example must be deployed. It is done automatically if the bean has been installed in the easybeans-deploy folder.

On the server side, the following output should display:

5/16/07 2:42:24 PM (I) AbsDeployer.deployEJB : Deploying EJB3DeployableImpl[archive=easybeans-deploy/migration21.jar]
5/16/07 2:42:25 PM (I) JContainer3.start : Container started in : 166 ms 

Once this information is displayed on the screen, the container is ready to receive client calls.

3.2.8.4. Running the Client

Once the container has been started, the client can be launched.

The client is run with the following ant command: ant run.client

If the client runs successfully, the following output is displayed on the client side:

run.client:
     [java] May 16, 2007 2:43:18 PM org.objectweb.carol.util.configuration.ConfigurationRepository init
     [java] INFO: No protocols were defined for property 'carol.protocols', trying with default protocol = 'jrmp'.
     [java] Calling hello() method on EJB 3.0 view of the Bean...
     [java] Calling hello() method on Remote EJB 2.1 view of the Bean...

The following output is displayed on the server side:

Hello world EJB 3.0 !
Hello world EJB 2.1 Remote View !
Link to itself remote = org.objectweb.easybeans.examples.migrationejb21.EJB2And3Bean_org.objectweb.easybeans.examples.migrationejb21.EJB2RemoteHome/8414877
Link to itself local view = org.objectweb.easybeans.examples.migrationejb21.EJB2And3Bean_org.objectweb.easybeans.examples.migrationejb21.EJB2LocalHome/8414877
Calling itself on the local view...
Hello world EJB 2.1 Local View !

3.2.9. EAR example

The build.xml file for this example is located in the examples/ear folder.

[Note] Note

This example required the use of a web container, then it can work in EasyBeans/JOnAS, EasyBeans/Tomcat or EasyBeans/Jetty but not in standalone mode as the war file can't be deployed.

3.2.9.1. Description

This example will deploy the EJB3 included in the EAR file in EasyBeans EJB3 container while the .war file will be deployed in the web container This EAR example includes an EJB3 and a WAR file. This allows to use local interface between the WEB layer and the EJB layer. The EAR file has no entry named META-INF/application.xml, EasyBeans will detect the type of the given archives and use default values for the name of the web context. Due to the use of local interface, the Entities don't need to implement the Serializable interface. The interface is not annotated with @Local annotation as it is the default value. Each entity class provides a @NamedQuery query that allows to get all the objects There is a relationship between Author and Book entities. It is very simple: One Author can write several books, but a Book is written only by one Author. @OneToMany and @ManyToOne annotations are used to define the relationship

3.2.9.2. Running the Server

If the server is not available, it must be run following the steps described in Chapter 3, "Running the EasyBeans Server" of the developer's guide.

3.2.9.3. Deploying the EAR

The EAR application example must be deployed. It is done automatically if the EAR has been installed in the easybeans-deploy folder.

When the EAR is detected by EasyBeans, the following traces will be displayed :

JOnASDeployer.deployEAR : Deploying EARDeployableImpl[archive=/tmp/EasyBeans-Deployer-benoitf/EAR/ear3.ear]
ENCManager.getInterceptorClass : Detecting JOnAS: using JOnAS ENC for the naming.
JPersistenceUnitInfoHelper.loadDefaultValues : Default persistence provider set to value org.hibernate.ejb.HibernatePersistence.
...
Version.&lt;clinit&gt; : Hibernate Annotations 3.3.0.GA
Environment.&lt;clinit&gt; : Hibernate 3.2.4
...
JContainer3.start : Container started in : 5619 ms
AbsJWebContainerServiceImpl.registerWar : War /tmp/EasyBeans-Deployer-benoitf/EAR/ear3.ear/ear-web.war available at the context /ear-web.
JOnASDeployer.deployEAR : 'EARDeployableImpl[archive=/tmp/EasyBeans-Deployer-benoitf/EAR/ear3.ear]' EAR Deployable is now deployed

Once this information is displayed on the screen, the application can be used by using an HTTP browser.

3.2.9.4. Using the Client

Once the container has been started, the client can be accessed.

The URL used to connect to the client is the following: http://localhost:9000/ear-web for JOnAS.

The following text should be displayed on the browser:

Initialize authors and their books...

Get authors

List of books with author 'Honore de Balzac' :

    * Title 'Le Pere Goriot'.
    * Title 'Les Chouans'.

List of books with author 'Victor Hugo' :

    * Title 'Les Miserables'.
    * Title 'Notre-Dame de Paris'.

There is no output on the server side.

Chapter 4. Writing a HelloWorld Bean

4.1. Requirements

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.

4.2. Writing Code for the Bean

The HelloWorld bean is divided into two parts: the business interface, and the class implementing this interface.

4.2.1. Writing the 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] Note

Even if this interface is used as a remote interface, it does not need to extend java.rmi.Remote interface.

4.2.2. Writing the Business Code

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] Note

At this moment, the bean is not an EJB; this is only a class implementing an interface.

4.2.3. Defining the EJB Code as a Stateless Session Bean

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;


import javax.ejb.Remote;
import javax.ejb.Stateless;

/**
 * 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] Note

If a class implements a single interface, this interface is defined as a local interface by default.

4.2.4. Packaging the Bean

The two classes ( HelloWorldInterface and HelloWorldBean) must be compiled.

Then, a folder named ejb3s/helloworld.jar/ must be created and classes placed in this folder. They will be deployed and loaded automatically.

4.3. Writing the Client Code

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] Note

The client does not call the PortableRemoteObject.narrow() method. Also, no create() method is required.

4.4. Writing a First Business Method Interceptor

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 could be extended to perform more functions.

    /**
     * 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] Caution

Be sure to call the proceed() method on the invocationContext object; otherwise, the invocation is broken.

4.5. Writing a First Lifecycle Interceptor

The bean can be notified of certain lifecycle events: for example, when a bean is created or destroyed.

In the following example, a method of the bean will receive 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");
    }

Chapter 5. EasyBeans Server Configuration File

5.1. Introduction

EasyBeans is configured with the help of an easy-to-understand XML configuration file.

The following is an example of an EasyBeans XML configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<easybeans xmlns="http://org.ow2.easybeans.server">

    <!-- No infinite loop (daemon managed by WebContainer): wait="false"
         Enable MBeans: mbeans="true"
         No EasyBeans naming, use WebContainer naming: naming="false"
         Use EasyBeans JACC provider: jacc="true"
         Use EasyBeans file monitoring to detect archives: scanning="true"
         Use EasyBeans JMX Connector: connector="true"
         Enable Deployer and J2EEServer MBeans: deployer="true" & j2eeserver="true"
    -->
    <config
        wait="false"
        mbeans="true"
        naming="false"
        jacc="true"
        scanning="true"
        connector="true"
        deployer="true"
        j2eeserver="true" />

    <!-- Define components that will be started at runtime -->
    <components>
        <!-- RMI/JRMP will be used as protocol layer -->
        <rmi>
           <protocol name="jrmp" port="1099" hostname="localhost" />
        </rmi>

        <!-- Start a transaction service -->
        <tm />

        <!-- Start a JMS provider -->
        <jms port="16030" hostname="localhost" />

        <!-- Creates an embedded HSQLDB database -->
        <hsqldb port="9001" dbName="jdbc_1">
            <user name="easybeans" password="easybeans" />
        </hsqldb>

        <!-- Add mail factories -->
        <mail>
          <!-- Authentication ?
          <auth name="test" password="test" />
          -->
          <session name="javax.mail.Session factory example" jndiName="mailSession_1">
            <!-- Example of properties -->
            <property name="mail.debug" value="false" />
          </session>

          <mimepart name="javax.mail.internet.MimePartDataSource factory example" jndiName="mailMimePartDS_1">
            <subject>How are you ?</subject>
            <email type="to">[email protected]</email>
            <email type="cc">[email protected]</email>
            <!-- Example of properties -->
            <property name="mail.debug" value="false" />
          </mimepart>

        </mail>

        <!-- Creates a JDBC pool with jdbc_1 JNDI name -->
        <jdbcpool jndiName="jdbc_1" username="easybeans"
            password="easybeans" url="jdbc:hsqldb:hsql://localhost:9001/jdbc_1"
            driver="org.hsqldb.jdbcDriver" />

        <!-- Start smartclient server with a link to the rmi component-->
        <smart-server port="2503" rmi="#rmi" />


        <!-- JNDI Resolver -->
        <jndi-resolver />

        <!-- JMX component -->
        <jmx />

        <!-- Statistic component -->
        <statistic event="#event" jmx="#jmx" />
    </components>
</easybeans>

By default, an easybeans-default.xml file is used. To change the default configuration, the user must provide a file named easybeans.xml, which is located at classloader/CLASSPATH.

[Note] Note

The namespace used is http://org.ow2.easybeans.server.

5.2. Configuration

Each element defined inside the <components> element is a component.

Note that some elements are required only for the standalone mode. JMS, RMI, HSQL, and JDBC pools are configured through JOnAS server when EasyBeans runs inside JOnAS.

5.2.1. RMI Component

The RMI configuration is done using the <rmi> element.

To run EasyBeans with multiple protocols, the <protocol> element can be added more than once.

The hostname and port attributes are configurable.

Protocols could be "jrmp, jeremie, iiop, cmi". The default is jrmp.

[Note] Note

Some protocols may require libraries that are not packaged by default in EasyBeans.

5.2.2. Transaction Component

The Transaction Component is defined by the <tm> element.

A timeout attribute, which is the transaction timeout (in seconds), can be defined on this element. The default is 60 seconds.

The implementation provided by the JOTM objectweb project is the default implementation.

5.2.3. JMS Component

The JMS component is used for JMS Message Driven Beans. Attributes are the port number and the hostname.

Also, the workmanager settings can be defined: minThreads, maxThreads and threadTimeout. The values are printed at the EasyBeans startup.

The default implementation is the implementation provided by the JORAM objectweb project.

5.2.4. HSQL Database

EasyBeans can run an embedded database. Available attributes are the port number and the database name. The <hsqldb> may be duplicated in order to run several HSQLDB instances.

Users are defined through the <user> element.

5.2.5. JDBC Pool

This component allows the JDBC datasource to be bound into JNDI. The jndi name used is provided by the jndiName attribute.

Required attributes are username, password, url and driver.

Optional attributes are poolMin, poolMax and pstmtMax. This component provides the option to set the minimum size of the pool, the maximum size, and the size of the prepared statement cache.

5.2.6. Mail component

Mails can be sent by using the mail component that provides either Session or MimePartDataSource factories.

5.2.7. SmartServer Component

This component is used by the Smart JNDI factory on the client side. This allows the client to download missing classes. The client can be run without a big jar file that provides all the classes. Classes are loaded on demand.

[Note] Note

Refer to the Chapter titled, Smart JNDI Factory, for more information about this feature.

5.3. Advanced Configuration

This configuration file can be extended to create and set properties on other classes.

5.3.1. Mapping File

A mapping file named easybeans-mapping.xml provides the information that rmi is the CarolComponent, tm is the JOTM component, and jms is the Joram component. This file is located in the org.objectweb.easybeans.server package.

The following is an extract of the easybeans-mapping.xml file.

[Note] Note

The mapping file is using a schema available at http://easybeans.ow2.org/xml/ns/xmlconfig/xmlconfig-mapping_10.xsd

<?xml version="1.0" encoding="UTF-8"?>
 <xmlconfig-mapping xmlns="http://easybeans.ow2.org/xml/ns/xmlconfig"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://easybeans.ow2.org/xml/ns/xmlconfig
                                        http://easybeans.ow2.org/xml/ns/xmlconfig/xmlconfig-mapping_1_0.xsd">

    <class name="org.ow2.easybeans.server.ServerConfig" alias="config">
        <attribute name="shouldWait" alias="wait" />
        <attribute name="useMBeans" alias="mbeans" />
        <attribute name="useNaming" alias="naming" />
        <attribute name="initJACC" alias="jacc" />
        <attribute name="directoryScanningEnabled" alias="scanning" />
        <attribute name="startJMXConnector" alias="connector" />
        <attribute name="registerDeployerMBean" alias="deployer" />
        <attribute name="registerJ2EEServerMBean" alias="j2eeserver" />
        <attribute name="description" />
    </class>

    <class name="org.ow2.easybeans.component.Components"
        alias="components" />

    <class name="org.ow2.easybeans.component.util.Property"
        alias="property" />

    <package name="org.ow2.easybeans.component.carol">
        <class name="CarolComponent" alias="rmi" />
        <class name="Protocol" alias="protocol">
          <attribute name="portNumber" alias="port" />
        </class>
    </package>

    <class name="org.ow2.easybeans.component.cmi.CmiComponent" alias="cmi">
        <attribute name="serverConfig" alias="config" />
        <attribute name="eventComponent" alias="event" />
    </class>

    <class
        name="org.ow2.easybeans.component.smartclient.server.SmartClientEndPointComponent"
        alias="smart-server">
        <attribute name="portNumber" alias="port" />
        <attribute name="registryComponent" alias="rmi" />
    </class>

    <class name="org.ow2.easybeans.component.jotm.JOTMComponent"
        alias="tm" />

    <class name="org.ow2.easybeans.component.joram.JoramComponent" alias="jms">
       <attribute name="topic" isList="true" getter="getTopics" setter="setTopics" element="true"/>
    </class>

    <class
        name="org.ow2.easybeans.component.jdbcpool.JDBCPoolComponent"
        alias="jdbcpool" />

    <class
        name="org.ow2.easybeans.component.remotejndiresolver.RemoteJNDIResolverComponent"
        alias="jndi-resolver">
    </class>

    <package name="org.ow2.easybeans.component.hsqldb">
        <class name="HSQLDBComponent" alias="hsqldb">
            <attribute name="databaseName" alias="dbName" />
            <attribute name="portNumber" alias="port" />
        </class>
        <class name="User" alias="user">
            <attribute name="userName" alias="name" />
        </class>
    </package>

    <package name="org.ow2.easybeans.component.quartz">
        <class name="QuartzComponent" alias="timer" />
    </package>

    <package name="org.ow2.easybeans.component.mail">
      <class name="MailComponent" alias="mail" />
      <class name="Session" alias="session">
        <attribute name="JNDIName" alias="jndiName" />
      </class>
      <class name="MimePart" alias="mimepart">
        <attribute name="subject" element="true" />
        <attribute name="JNDIName" alias="jndiName" />
      </class>
      <class name="MailAddress" alias="email" element-attribute="name" />
      <class name="Auth" alias="auth">
        <attribute name="username" alias="name" />
      </class>
    </package>

    <class name="org.ow2.easybeans.component.event.EventComponent" alias="event">
      <attribute name="eventService" alias="event-service" optional="true" />
    </class>

    <class name="org.ow2.easybeans.component.jmx.JmxComponent" alias="jmx">
      <attribute name="commonsModelerExtService" alias="modeler-service" optional="true" />
    </class>

    <class name="org.ow2.easybeans.component.statistic.StatisticComponent" alias="statistic">
        <attribute name="eventComponent" alias="event" />
        <attribute name="jmxComponent" alias="jmx" />
    </class>

    <package name="org.ow2.easybeans.component.depmonitor">
        <class name="DepMonitorComponent" alias="depmonitor">
        </class>
        <class name="ScanningMonitor" alias="scanning">
            <attribute name="waitTime" alias="period" />
        </class>
        <class name="LoadOnStartupMonitor" alias="loadOnStartup">
        </class>
    </package>


</xmlconfig-mapping>
[Note] Note

This mapping file is referenced by the easybeans configuration file using the XML namespace : xmlns="http://org.ow2.easybeans.server".

Each element configured within this namespace will use the mapping done in the org.ow2.easybeans.server package.

Users can define their own mapping by providing a file in a package. The name of the the file must be easybeans-mapping.xml or element-mapping.xml.

Example: For the element <easybeans xmlns="http://org.ow2.easybeans.server">, the resource searched in the classloader is org/ow2/easybeans/server/easybeans-mapping.xml. And for an element <pool:max>2</pool:max> with xmlns:pool="http://org.ow2.util.pool.impl", the resource searched will be org/ow2/util/pool/impl/easybeans-mapping.xml or org/ow2/util/pool/impl/pool-mapping.xml.

5.3.2. Other Configuration Files

EasyBeans can be configured through other configuration files as it uses a POJO configuration. If done this way, it can be configured using the Spring Framework component or other frameworks/tools.

Chapter 6. Smart JNDI Factory

6.1. Introduction

The smart factory provided by EasyBeans is a factory that allows downloading of some classes from the server.

It is useful when developing heavy clients.

In order to run the clients, the developer must provide all the classes used to compile the client code and include a small jar file (less than 50kB) to add to the CLASSPATH.

Required libraries for running a client are:

  • The client's code (used at compile time)

  • The Interface of the Beans that are accessed (used at compile time)

  • The Java EE API used by the client (used at compile time)

  • The smart factory provided by the ow_easybeans_component_smartclient.jar jar file

6.2. Running the Client

The smart factory is configured through two properties.

6.2.1. Initial Context Factory

The first property is the InitialContextFactory name. The smart factory is named org.ow2.easybeans.component.smartclient.spi.SmartContextFactory.

This property can be set as a System property in one of the following ways:

  • by using -Djava.naming.factory.initial=org.ow2.easybeans.component.smartclient.spi.SmartContextFactory

  • by using System.setProperty(Context.INITIAL_CONTEXT_FACTORY, org.ow2.easybeans.component.smartclient.spi.SmartContextFactory)

It can also be used as a parameter when creating an InitialContext:

        Hashtable<String, Object> env = new Hashtable<String, Object>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, org.ow2.easybeans.component.smartclient.spi.SmartContextFactory);
        return new InitialContext(env);

6.2.2. Provider URL

This property is used to provide the remote address and the remote port.

By default, this property is set (if not defined) to smart://localhost:2503

The port number must match the port defined in the EasyBeans configuration file.

This property can be set using:

        Hashtable<String, Object> env = new Hashtable<String, Object>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, org.ow2.easybeans.component.smartclient.spi.SmartContextFactory);
        env.put(Context.PROVIDER_URL, "smart://localhost:2503");
        return new InitialContext(env);

6.3. Example

The following is the output on the client side when this factory is enabled:

     [java] Oct 17, 2006 5:38:13 PM org.ow2.easybeans.component.smartclient.spi.SmartContextFactory getInitialContext
     [java] INFO: Initializing Smart Factory with remote URL 'smart://localhost:2503'.
     [java] Oct 17, 2006 5:38:13 PM org.ow2.easybeans.component.smartclient.spi.SmartContextFactory getInitialContext
     [java] INFO: Got remote PROVIDER_URL 'rmi://localhost:1099'.

     ...
     [java] Downloaded 'xxx' classes, 'xxx' resources for a total of 'xxx' bytes and it took 'xxx' ms.

The following is the output on the server side:

     [java] 10/17/06 5:38:13 PM (I) SmartClientEndPointComponent.handleReadProviderURLRequest : Provider URL asked by client : 'rmi://localhost:1099'.

6.4. Smart Bootstrap

Sometimes, it's easier to launch the client with a bootstrap class instead of setting a factory. Then, the smart component is providing also a bootstrap class.

6.4.1. Smart Library

The smart bootstrap jar library is provided in the releases of EasyBeans. It can also be downloaded from the maven repository: http://repo2.maven.org/maven2/org/ow2/easybeans/easybeans-component-smartclient/

Select the version corresponding to the EasyBeans version.

6.4.2. Smart Bootstrap class

In order to launch the bootstrap, the ow_easybeans_component_smartclient.jar file needs to be present and then it is invoked by using:

java -jar ow_easybeans_component_smartclient.jar

Usage is printed when no parameteres are specified.

The jars containing the client provided by the developer are given using the -cp flag

java -jar ow_easybeans_component_smartclient.jar -cp myClient.jar:mylib.jar

The name of the client's class is provided on this command

java -jar ow_easybeans_component_smartclient.jar -cp myClient.jar:mylib.jar org.MyClient

In order to download classes, the bootstrap is connecting to the EasyBeans server by using default port/hostname. To specify a different host or port number, the following arguments can be used:

-port for the port number or -hostname for specifying the host name.

Chapter 7. Advanced topics

7.1. Helping debug of enhanced classes

EasyBeans is modifying/enhancing EJB classes at runtime. For debugging purpose, EasyBeans can dump the modified class in order to check/debug generated bytecode by using some decompilers.

In order to enable the dump of the class, the logger org.ow2.easybeans.loader needs to be set at DEBUG/FINEST level. The classes will be dumped in the Java System java.io.tmpdir directory.

Copyright © 2006 EasyBeans / ObjectWeb consortium

http://www.easybeans.org