The Carbon Java Framework  

The Carbon EJB Module

Requirements

Author: Erik M Gottesman (egotte at sapient.com)
Version:
Created:

Service Overview

Purpose

The primary purpose of the EJB service is two-fold:

  • to make it easier for developers to integrate Enterprise Java Beans into their applications
  • to encourage good programming practices as they relate to the usage of Enterprise Java Beans, e.g. maintenance of proper security context

This purpose is achieved through a client-oriented lookup interface backed by configuration information declared in XML.

In its present form, the EJB service consists of two "home factory" components; the LocalHomeFactory is dedicated to locally deployed EJBs, while the RemoteHomeFactory provides similar functionality for remotely deployed EJBs. Both components present the developer with a consistent API, but vary in terms of the object-type returned.

A home factory component minimally provides methods to lookup and retrieve the home interface of an EJB given its logical name, i.e. its JNDI name. This information may optionally be accompanied by a security principal and associated credentials or a complete InitialContext object.

The default implementation of an EJB service home factory also provides simple caching functionality for EJB home interfaces to mitigate the performance cost of repeated JNDI lookups; this functionality is extensible and projects are encouraged to tailor it to meet their specific needs.

Usage

Component Configuration

An EJB service home-factory component can be referenced by another component as follows

<Configuration ConfigurationInterface="org.examples.accounts.AccountManagerConfiguration">
    <FunctionalInterface>org.examples.accounts.AccountManager</FunctionalInterface>
    <FunctionalImplementationClass>org.examples.accounts.AccountManagerImpl</FunctionalImplementationClass>

    <!-- This home factory will be used for local EJB lookups -->
    <HomeFactory>ref:///ejb/LocalHomeFactory</HomeFactory>

    <!-- This home factory will be used for remote EJB lookups -->
    <RemoteHomeFactory>ref:///ejb/RemoteHomeFactory</RemoteHomeFactory>
</Configuration>

Sample EJB component configuration for local home factory

<Configuration ConfigurationInterface="org.sape.carbon.services.ejb.HomeFactoryConfiguration">
    <FunctionalInterface>org.sape.carbon.services.ejb.local.LocalHomeFactory</FunctionalInterface>
    <FunctionalImplementationClass>org.sape.carbon.services.ejb.local.LocalHomeFactoryImpl</FunctionalImplementationClass>

    <!-- Default values for lookup -->
    <InitialContextFactory>weblogic.jndi.WLInitialContextFactory</InitialContextFactory>
    <Principal>system</Principal>
    <Credentials>password</Credentials>

    <!-- List of all ejbs which will be retrieved using this service -->
    <EnterpriseBeanArray>
        <!-- EJBs registered with this home factory -->
        <EnterpriseBean>
            <LogicalName>org.examples.accounts.Account</LogicalName>
            <Cacheable>true</Cacheable>
        </EnterpriseBean>

        <!-- second enterprise java bean -->
        <EnterpriseBean>
            .... .... ....
            .... .... ....
            .... .... ....
        </EnterpriseBean>
    </EnterpriseBeanArray>
</Configuration>
The configuration for remote enterprise beans remains the same, except for some minor modifications.
  • If a remote client is accessing the enterprise java bean the ProviderUrl must be specified
  • If RmiIiop property is set to true, the remote home factory downcasts the retrieved object using javax.rmi.PortableRemoteObject.narrow().
  • If RmiIiop is set, it is necessary to specify the HomeInterface of the enterprise java bean, or else the narrow operation will fail
<Configuration ConfigurationInterface="org.sape.carbon.services.ejb.RemoteHomeFactoryConfiguration">
    <FunctionalInterface>org.sape.carbon.services.ejb.local.LocalHomeFactory</FunctionalInterface>
    <FunctionalImplementationClass>org.sape.carbon.services.ejb.local.LocalHomeFactoryImpl</FunctionalImplementationClass>

    <!-- Default values for lookup -->
    <InitialContextFactory>weblogic.jndi.WLInitialContextFactory</InitialContextFactory>
    <Principal>system</Principal>
    <Credentials>password</Credentials>

    <!-- extra parameters required by the home factory configuration -->
    <ProviderUrl>t3://localhost:9001/</ProviderUrl>
    <RmiIiop>true</RmiIiop>


    <!-- List of all ejbs which will be retrieved using this service -->
    <EnterpriseBeanArray>
        <!-- EJBs registered with this home factory -->
        <EnterpriseBean>
            <!-- Home interface of the remote ejb -->
            <HomeInterface>org.donut.store.DonutManagerHome</HomeInterface>
            <LogicalName>org.donut.store.DonutManager</LogicalName>
            <Cacheable>true</Cacheable>
        </EnterpriseBean>

        <!-- second enterprise java bean -->
        <EnterpriseBean>
            .... .... ....
            .... .... ....
            .... .... ....
        </EnterpriseBean>
    </EnterpriseBeanArray>
</Configuration>

Performing EJB Lookups

A locally deployed EJB may be looked-up as follows:


// Obtain a handle to the home factory component
LocalHomeFactory homeFactory = (LocalHomeFactory)
    Lookup.getInstance().fetchComponent("/ejb/LocalHomeFactory");

// Perform the EJB lookup
AccountHome acctHome = (AccountHome)
    homeFactory.lookup("org.examples.accounts.Account");

// Derive the remote interface from the home interface
// Invoke business methods as appropriate

A remotely deployed EJB may be looked-up as follows:


// Obtain a handle to the home factory component
RemoteHomeFactory homeFactory = (RemoteHomeFactory)
    Lookup.getInstance().fetchComponent("/ejb/RemoteHomeFactory");

// Perform the EJB lookup
AccountManagerHome acctMgrHome = (AccountManagerHome)
    homeFactory.lookup("org.examples.accounts.AccountManager");

// Derive the remote interface from the home interface

// Invoke business methods as appropriate

Additionally, the EJB Service provides APIs to perform JNDI lookups using environment parameters not reflected in a Configuration, but specified at runtime. More specfically, the functional interface contains two discovery methods are that allow the client to either pass a fully-specified javax.naming.InitialContext object or merely override the security pricinpal and credentials specified in the Configuration. This means of lookup might typically be used in an EJB-to-EJB scenario wherein it makes sense to maintain the current environment, as opposed to referencing that specified in the Configuration, as illustrated in the example below.


// From within an EJB implementation class...

// Obtain a handle to the home factory component
RemoteHomeFactory homeFactory = (RemoteHomeFactory)
    Lookup.getInstance().fetchComponent("/ejb/RemoteHomeFactory");

// Perform the EJB lookup while maintaining the current security context
AccountManagerHome acctMgrHome = (AccountManagerHome)
    homeFactory.lookup("org.examples.accounts.AccountManager", new InitialContext());

// Derive the remote interface from the home interface

// Invoke business methods as appropriate

Copyright © 2001-2003, Sapient Corporation