Oracle8i Enterprise JavaBeans Developer's Guide and Reference Release 3 (8.1.7) Part Number A83725-01 |
Library | Service | Contents | Index

## Developing Your Client Application

All EJB clients perform the following to instantiate a bean, invoke its methods, and destroy the bean:

1. Look up the bean home interface, which is published in the Oracle8i database as part of the bean deployment process. Use the Java Naming and Directory Interface (JNDI) to look up the home interface.

2. Create instances of the bean in the server through the home interface. Invoking the `create` method on the home interface causes a new bean to be instantiated. This returns a bean reference to the bean's remote interface.

3. Invoke the methods defined in the remote interface. The container forwards the requests to the instantiated bean.

4. After the bean is no longer needed, invoke the `remove` method to destroy the bean.

These steps are completely illustrated by example in Figure 2-1.

As a quick example, suppose that `EmployeeHome` is a reference that you have obtained to the home interface of a bean called `Employee`. The `Employee` home interface must have at least one `create` method that lets you instantiate the bean. You create a new instance of the bean on the remote server by coding:

    Context ic = new InitialContext(env);

    EmployeeHome home =
          (EmployeeHome) ic.lookup(serviceURL + objectName);  // lookup the bean
    Employee testBean = home.create();   // create a bean instance

Then, you would invoke `Employee` methods using the usual syntax

    testBean.getEmployee(empNumber);

### Using the getEJBHome Method

When you use the getEJBHome method to retrieve the home interface given an object reference, you cannot cast the returned object to the home interface's type. Instead, the returned object is of type org.omg.CORBA.Object. Once received, the object is cast to the correct home interface type through the Helper.narrow method. The following shows the Hello example retrieve Hello's home interface using JNDI, creating the remote interface, and then later retrieving the home interface again using the getEJBHome interface. Notice that the HelloHomeHelper.narrow method is used to correctly typecast the home interface:

    HelloHome hello_home = (HelloHome)ic.lookup (serviceURL + objectName);
    Hello hello = hello_home.create ();
    System.out.println (hello.helloWorld ());

    org.omg.CORBA.Object newHome = (org.omg.CORBA.Object) hello.getEJBHome();
    HelloHome newHello = HelloHomeHelper.narrow(newHome);

### Parameter Passing

When you implement an EJB or write the client code that calls EJB methods, you have to be aware of the parameter-passing conventions used with EJBs.

A parameter that you pass to a bean method--or a return value from a bean method--can be any Java type that is serializable. Java primitive types, such as `int`, `double`, are serializable. Any non-remote object that implements the `java.io.Serializable` interface can be passed. A non-remote object passed as a parameter to a bean or returned from a bean is passed by value, not by reference. So, for example, if you call a bean method as follows:

    public class theNumber {
      int x;
    }
    ...
    bean.method1(theNumber);

then `method1()` in the bean receives a copy of `theNumber`. If the bean changes the value of `theNumber` object on the server, this change is not reflected back to the client, because of pass-by-value semantics.

If the non-remote object is complex--such as a class containing several fields--only the non-static and non-transient fields are copied.

When passing a remote object as a parameter, the stub for the remote object is passed. A remote object passed as a parameter must extend remote interfaces.

The next section demonstrates parameter passing to a bean and remote objects as return values.

### A Parameter Object

The `EmployeeBean` `getEmployee` method returns an `EmpRecord` object, so this object must be defined somewhere in the application. In this example, an `EmpRecord` class is included in the same package as the EJB interfaces.

The class is declared as public, and must implement the `java.io.Serializable` interface so that it can be passed back to the client by value, as a serialized remote object. The declaration is as follows:

    package employee;

    public class EmpRecord implements java.io.Serializable {
      public String ename;
      public int empno;
      public double sal;
    }

Note: The `java.io.Serializable` interface specifies no methods, it just indicates that the class is serializable. Therefore, there is no need to implement extra methods in the `EmpRecord` class.

### The Client Code

This section shows the client code that you can use to send messages to the example bean described above, and get and print results from it. This client code demonstrates how a client:

- locates a remote object such as the bean home interface

- authenticates itself to the server

- activates an instance of the bean

- invokes a method on the bean

#### Locating Remote Objects

The first step with any remote object implementation, whether it's pure RMI, or EJBs, or CORBA, is to find out how to locate a remote object. To get a remote object reference you must know:

- the name of the object

- where the name server is located

With EJBs, the initial object name is the name of an EJB home interface, and you locate it using the Java Naming and Directory Interface (JNDI). The EJB specification requires that EJB implementations expose a JNDI interface as the means of locating a remote bean.

#### About JNDI

JNDI is an interface to a naming and directory service. For example, JNDI can serve as an interface to a file system that you can use to look up directories and the files they contain. Or, JNDI can be used as an interface to a naming or directory service, for example a directory protocol such as LDAP.

This section briefly describes JNDI. The EJB specification requires the use of JNDI for locating remote objects by name.

This section of the manual describes only those parts of JNDI that you need to know to write EJB applications for Oracle8i. To obtain the complete JNDI API (and SPI) specifications, see http://www.javasoft.com/products/jndi.

Sun Microsystems supplies JNDI in the `javax.naming` package, so you must import these classes in your client code:

    import javax.naming.*;

For the Oracle8i EJB server, JNDI serves as an interface (SPI driver) to the OMG CosNaming service. But you do not have to know all about CosNaming, or even all about JNDI, to write and deploy EJBs for the Oracle8i server. To start, all you must know is how to use the JNDI methods used to access permanently-stored home interface objects and how to set up the environment for the JNDI `Context` object.

The remainder of this JNDI section describes the data structures and methods of the `javax.naming` package that you will need to access EJB objects.

#### Getting the Initial Context

You use JNDI to retrieve a `Context` object. The first `Context` object that you receive is bound to the root naming context of the Oracle8i publishing context. EJB home interfaces are published in the database, and are arranged in a manner similar to a file system hierarchy. See Oracle8i Java Tools Reference for more details about the `publish` tool.

You get the root naming context by creating a new JNDI `InitialContext`, as follows:

    Context initialContext = new InitialContext(environment);

The `environment` parameter is a Java hashtable. Table 2-2 contains the six properties that you can set in the hashtable that are passed to the `javax.naming.Context.`

##### Table 2-2 Context Properties

Property | Purpose
--- | ---
javax.naming.Context. URL_PKG_PREFIXES | The environment property that specifies the list of package prefixes to use when loading in URL context factories. You must use the value `"oracle.aurora.jndi"` for this property.
javax.naming.Context. SECURITY_AUTHENTICATION | The type of security for the database connection. The possible values are: `oracle.aurora.sess_iiop.ServiceCtx. NON_SSL_LOGIN` `oracle.aurora.sess_iiop.ServiceCtx. SSL_CREDENTIAL` `oracle.aurora.sess_iiop.ServiceCtx. SSL_LOGIN` `oracle.aurora.sess_iiop.ServiceCtx. SSL_CLIENT_AUTH`
javax.naming.Context. SECURITY_PRINCIPAL | The Oracle8i username, for example "SCOTT".
javax.naming.Context. SECURITY_CREDENTIALS | The password for the username, for example "TIGER".
oracle.aurora.sess_iiop.ServiceCtx.SECURITY_ROLE | An optional property that establishes a database role for the connection. For example, use the string "CLERK" to connect with the CLERK role.
oracle.aurora.sess_iiop.ServiceCtx.SSL_VERSION | The client-side SSL version number.

See Chapter 5, "JNDI Connections and Session IIOP Service", for more information about JNDI and connecting to an Oracle8i instance.

#### Getting the Home Interface Object

Once you have the initial references context, you can invoke its methods to get a reference to an EJB home interface. To do this, you must know the published full pathname of the object, the host system where the object is located, the IIOP port for the listener on that system, and the database system identifier (SID). When you obtain this information--for example, from the EJB deployer--construct a URL using the following syntax:

    <service_name>://<hostname>:<iiop_listener_port>:<SID>/<published_obj_name>

For example, to get a reference to the home interface for a bean that has been published as `/test/myEmployee`, on the system whose TCP/IP hostname is `myHost`, the listener IIOP port is 2481, and the system identifier (SID) is `ORCL`, construct the URL as follows:

    sess_iiop://myHost:2481:ORCL/test/myEmployee

The listener port for IIOP requests is configured in the listener.ora file. The default for Oracle8i is 2481. See the Net8 Administrator's Guide for more information about IIOP configuration information. See also Chapter 5, "JNDI Connections and Session IIOP Service" for more information about IIOP connections.

You get the home interface using the `lookup` method on the initial context, passing the URL as the parameter. For example, if the home interface's published name is `/test/myEmployee`, you would code:

    ...
    String ejbURL = "sess_iiop://localhost:2481:ORCL/test/myEmployee";
    Hashtable env = new Hashtable();
    env.put(javax.naming.Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
    // Tell sess_iiop who the user is
    env.put(Context.SECURITY_PRINCIPAL, "SCOTT");
    // Tell sess_iiop what the password is
    env.put(Context.SECURITY_CREDENTIALS, "TIGER");
    // Tell sess_iiop to use non-SSL login authentication
    env.put(Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN);
    // Lookup the URL
    EmployeeHome home = null;
    Context ic = new InitialContext(env);
    home = (EmployeeHome) ic.lookup(ejbURL);
    ...

#### Invoking EJB Methods

Once you have the home interface for the bean, you can invoke one of the bean's `create` methods to instantiate a bean. See Chapter 5, "JNDI Connections and Session IIOP Service" for information about granting execution rights. For example:

    Employee testBean = home.create();

Then you can invoke the EJB's methods in the normal way:

    int empNumber = 7499;
    EmpRecord empRec = testBean.getEmployee(empNumber);

Here is the complete code for the client application:

    import employee.Employee;
    import employee.EmployeeHome;
    import employee.EmpRecord;

    import oracle.aurora.jndi.sess_iiop.ServiceCtx;

    import javax.naming.Context;
    import javax.naming.InitialContext;
    import java.util.Hashtable;

    public class Client {

      public static void main (String [] args) throws Exception {

        String serviceURL = "sess_iiop://localhost:2481:ORCL";
        String objectName = "/test/myEmployee";
        int empNumber = 7499;   // ALLEN
        Hashtable env = new Hashtable();

        env.put(Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
        env.put(Context.SECURITY_PRINCIPAL, "scott");
        env.put(Context.SECURITY_CREDENTIALS, "tiger");
        env.put(Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN);

        Context ic = new InitialContext(env);

        EmployeeHome home =
          (EmployeeHome) ic.lookup(serviceURL + objectName);  // lookup the bean
        Employee testBean = home.create();   // create a bean instance
        EmpRecord empRec =

                  testBean.getEmployee(empNumber); // get the data and print it
        System.out.println("Employee name is " + empRec.ename);
        System.out.println("Employee sal is  " + empRec.sal);
      }
    }

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index