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

## Session IIOP Service

All client/server network communications route requests over an accepted protocol between both entities. Most network communications to the Oracle8i database routed over the two-task common (TTC) layer. This is the service that processes incoming Net8 requests for database SQL services. However, with the addition of Java into the database, JServer required that clients communicate with the server over an IIOP transport that recognized database sessions. This is accomplished through the session IIOP service.

The session IIOP service is used for facilitating requests for IIOP applications, which includes CORBA and EJB applications. The following sections describe how to manage your applications within one or more database sessions:

- Session IIOP Service Overview

- Session Management

- Service Context Class

- Session Context Class

- Session Management Scenarios

- Setting Session Timeout

### Session IIOP Service Overview

As discussed in the Oracle8i Java Developer's Guide, since the EJB is loaded into the database, your client application must start up the EJB within the context of a database session. Because beans are activated within a session, each client cannot see bean instances active in another session, unless given a handle to that session. Also, you can activate objects within the existing session or another session.

The session IIOP service session component tag--TAG_SESSION_IIOP-- exists inside the IIOP profile--`SessionIIOP`. The value for this Oracle session IIOP component tag is 0x4f524100 and contains information that uniquely identifies the session in which the object was activated. The client ORB runtime uses this information to send requests to objects in a particular session.

Although the Oracle8i session IIOP service provides an enhancement of the standard IIOP protocol--it includes session ID information--it does not differ from standard IIOP in its on-the-wire data transfer protocol.

#### Client Requirements

Clients must have an ORB implementation that supports session IIOP to be able to access objects in different sessions simultaneously, from within the same program, and to be able to disconnect from and reconnect to the same session. The version of the Visigenic ORB that ships with Oracle8i has been extended to support session IIOP.

#### Session Routing

When a client makes an IIOP connection to the database, Oracle8i decides if a new session should be started to handle the request, or if the request should be routed to an existing session. If the client initializes a new request for a connection (using the `InitialContext`.`lookup()` method) and no session is active for that connection, a new session is automatically started. If a session has already been activated for the client, the session identifier is encoded into the object key of the object. This information enables the session IIOP service to route the request to the correct session. In addition, you can also use this session identifier to allow a single client to access multiple sessions. See "Session Management Scenarios" for more information.

#### JServer Tools

When using the Oracle8i JServer tools, especially when developing EJB and CORBA applications, it is very important to distinguish the two network service protocol types: TTC and IIOP.

#### Figure 5-2 TTC and IIOP Services

Figure 5-2 shows which tools and requests use TTC and which use IIOP database ports. 1521 is the default port number for TTC, and 2481 is the default for IIOP.

- Tools such as `publish`, `deployejb`, and the session shell access IIOP objects, and so must connect using an IIOP port. In addition, EJB and CORBA clients must use an IIOP port when sending requests to Oracle.

- Tools such as `loadjava` and `dropjava` connect using a TTC port.

### Session Management

In the simple cases, a client (or a server object acting as a client) starts a new server session implicitly when it performs the lookup for a server object. Oracle8i also gives you the ability to control session start-up explicitly. Two Oracle-specific classes are provided that gives you control over the session IIOP service connection and over the sessions within the database.

- Service Context Class--Controls the session IIOP service connection to the database. Given a URL to that database, you can create a service context. Off of this service context, you can open one or more named sessions within the database.

- Session Context Class--Controls named database sessions created off of a service context. Once created, you can activate CORBA or EJB objects within the session using the named session context object.

### Service Context Class

Controls the session IIOP service connection to the database. Given a URL to that database, you can create a service context. Off of this service context, you can open one or more named sessions within the database. This Oracle-specific class extends the JNDI `Context` class.

#### Variables

The `ServiceCtx` class defines a number of final public static variables that you can use to define environment properties and other variables. Table 5-1 shows these.

##### Table 5-1 ServiceCtx Public Variables

String Name | Value
--- | ---
NON_SSL_CREDENTIAL | "Credential"
NON_SSL_LOGIN | "Login"
SSL_CREDENTIAL | "SecureCredential"
SSL_LOGIN | "SecureLogin"
SSL_CLIENT_AUTH | "SslClientAuth"
SSL_30 | "30"
SSL_20 | "20"
SSL_30_WITH_20_HELLO | "30_WITH_20_HELLO"
Integer Name | Integer Constructor
SESS_IIOP | new Integer(2)
IIOP | new Integer(1)

#### Methods

The public methods in this class that CORBA and EJB application developers can use are as follows:

    public Context createSubcontext(String name)

This method takes a Java String as the parameter and returns a JNDI `Context` object representing a session in the database. The method creates a new named session. The parameter is the name of the session to be created, which must start with a colon (:).

The return result should be cast to a `SessionCtx` object.

Throws `javax.naming.NamingException`.

    public Context createSubcontext(Name name)

(Each of the methods that takes a String parameter has a corresponding method that takes a `Name` parameter. The functionality is the same.)

    public static org.omg.CORBA.ORB init(String username,
                                         String password,
                                         String role,
                                         boolean ssl,
                                         java.util.Properties props)

Gets access to the ORB created when you perform a look up. Set the `ssl` parameter to true for SSL authentication. Clients that do not use JNDI to access server objects should use this method.

See "sharedsession" in Appendix A of the Oracle8i CORBA Developer's Guide for a usage example.

    public Object lookup(String string)

`lookup()` looks up a published object in the database instance associated with the service context, and either returns an activated instance of the object, or throws `javax.naming.NamingException.`

### Session Context Class

Controls named database sessions created off of a service context. Once created, you can activate CORBA or EJB objects within the session using the named session context object. Session contexts represent sessions and contain methods that enable you to perform session operations such as authenticating the client to the session or activating objects. This class extends the JNDI `Context` class.

Note: Creating a subcontext within the session context affects the object type returned on the final JNDI lookup. See "Lookup of Objects Off of JNDI Context" for more information.

#### Methods

The session context methods that a client uses are the following:

    public synchronized boolean login()

`login()` authenticates the client using the initial context environment properties passed in the `InitialContext` constructor: username, password, and role.

    public synchronized boolean login(String username,

                                     String password,

                                    String role)

`login()` authenticates the client using the username, password, and optional database role supplied as parameters.

    public Object activate(String name)

Looks up and activates a published object having the name.

### Session Management Scenarios

The following sections describe the different scenarios for managing database sessions:

- Client Accessing a Single Session--client activates and accesses an object in the :`default` session.

- Ending a Session--discusses methods that explicitly terminate a session.

- Client Starting a Named Session--client activates and accesses one or more objects in a session other than the :default session. This session is identified by a name within a `SessionCtx`.

- Two Clients Accessing the Same Session--two or more clients can access an activated object within a session by providing x and y to both clients.

- In-Session Activation--a server object, acting as a client, activates another object within the same session.

- Lookup of Objects Off of JNDI Context--lookup of a partial JNDI name requires that you activate the bound object.

##### Client Accessing a Single Session

In general, when you look up a published object from a client with a URL, hostname, and port, the object is activated in a new session. For example, a client would perform the following:

    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);
    SomeObjectHome myObj_home =
        (SomeObjectHome) ic.lookup("sess_iiop://localhost:2481:ORCL/test/myObj");
    SomeObject myObj = myObj_home.create ();

Activating an object in a new session from a server object is identical to starting a session from an application client. If the `lookup` method is invoked within the server object, the second object instance is activated in a separate session from the originating session.

##### Ending a Session

Normally, a session terminates when the client terminates. However, if you want to explicitly terminate a session, you can do one of the following:

Terminate A Session From The Server-Side Using The Endsession Method

The server can control session termination by executing the following method:

    oracle.aurora.mts.session.Session.THIS_SESSION().endSession();

Terminate A Session From The Client-side Using The Logout Object

If the client wishes to exit the session, it can execute the `logout` method of the `LogoutServer` object, which is pre-published as "`/etc/logout`". Only the session owner is allowed to logout. Any other owner receives a NO_PERMISSION exception.

The `LogoutServer` object is analogous to the `LoginServer` object, which is pre-published as "`/etc/login`". You can use the `LoginServer` object to retrieve the `Login` object, which is used to authenticate to the server. This is an alternative method to using the `Login` object within the JNDI lookup.

The following example shows how a client can authenticate using the `LoginServer` object and can exit the session through the `LogoutServer` object.

    import oracle.aurora.AuroraServices.LoginServer;
    import oracle.aurora.AuroraServices.LogoutServer;
    ...
    // To log in using the LoginServer object
    LoginServer loginServer = (LoginServer)ic.lookup(serviceURL + "/etc/login");
    Login login = new Login(loginServer);
    System.out.println("Logging in ..");
    login.authenticate(user, password, null);
    ...
    //To logout using the LogoutServer
    LogoutServer logout = (LogoutServer)ic.lookup(serviceURL + "/etc/logout");
    logout.logout();

##### Client Starting a Named Session

You can explicitly create multiple session on the database instance through the JNDI methods provided in the `ServiceCtx` and `SessionCtx` classes.

The following `lookup` method contains a URL that defines the IIOP service URL of "`sess_iiop://localhost:5521:ORCL`" and a default session context.

    SomeObjectHome myObj_home =
        (SomeObjectHome) ic.lookup("sess_iiop://localhost:2481:ORCL/test/myObj");
    SomeObject myObj = myObj_home.create ();

In this simple case, the JNDI initial context `lookup` method implicitly starts a session and authenticates the client. This session becomes the default session, which is identified by the name `":default`". All sessions are named. However, in the default case, the client does not need to know the name of the session, because all requests go to this single session. Unless specified, all additional objects activated will be activated in the default session. Even if you create a new JNDI initial context and look up the same or a new object, the object is instantiated in the same session as the first object.

The only way to activate objects within another session is to create a named session. You can create other sessions in place of or in addition to the default session by creating session contexts off of the service context. Each session would be a named session, so that you can activate objects in different sessions within the database.

1. Instantiate a new hashtable for the environment properties to be passed to the server.

           Hashtable env = new Hashtable();
           env.put(Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");

   Note: Only the `URL_PKG_PREFIXES` `Context` variable is filled in--the other information will be provided in the `login.authenticate()` method parameters.

2. Create a new JNDI Context.

       Context ic = new InitialContext(env);

3. Use the JNDI `lookup` method on the initial context, passing in the service URL, to establish a service context. This example uses a service URL with the service prefix of hostname, listener port, and SID.

   Note: Provide only the service URL of hostname, listener port, and database SID. If you provide the JNDI name of the desired object, a default session will be created for you.

       ServiceCtx service =
               (ServiceCtx) ic.lookup("sess_iiop://localhost:2481:ORCL");

4. Create a session by invoking the `createSubcontext` method on the service context object. Provide the name for the session as a parameter to the `createSubcontext` method. A new session is created within the database.

       SessionCtx session = (SessionCtx) service.createSubcontext(":session1");

   Note: You must name a new session when you create it. The session name must start with a colon (:), and cannot contain a slash (/), but is not otherwise restricted.

5. Authenticate the client program to the database by invoking the `login` method on the session context object.

       session.login("scott", "tiger", null);    // role is null

6. Activate the object, identified by its bound JNDI name, in the named session.

   The activation of an EJB returns the home interface for the bean. Basically, steps 1-6 performs the same functionality as performing a JNDI `lookup()` for the home interface. It simply allows you to specify the specific named session to activate the object in.

       // Activate one Hello object in the session
       HelloHome hello_home = (HelloHome)session.activate (objectName);

7. Retrieve the Remote interface and invoke a method on the Hello Bean.

   ####

           Hello hello = hello_home.create ();
           System.out.println (hello.helloWorld ());

       Example 5-1  Activating Objects in Named Sessions

The following example creates two named sessions of the name `:session1` and `:session2`. Each one retrieves the `Hello` object separately. The client invokes both Hello objects in each named session.

    Hashtable env = new Hashtable ();
    env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
    Context ic = new InitialContext (env);

    // Get a SessionCtx that represents a database instance
    ServiceCtx service = (ServiceCtx) ic.lookup ("sess_iiop://localhost:2481:ORCL");

    // Create and authenticate a first session in the instance.
    SessionCtx session1 = (SessionCtx) service.createSubcontext (":session1");

    // Authenticate
    session1.login("scott", "tiger", null);

    // Create and authenticate a second session in the instance.
    SessionCtx session2 = (SessionCtx) service.createSubcontext (":session2");

    // Authenticate using a login object (not required, just shown for example).
    LoginServer login_server2 = (LoginServer)session2.activate ("/etc/login");
    Login login2 = new Login (login_server2);
    login2.authenticate ("scott", "tiger", null);

    // Activate one Hello object in each session
    HelloHome hello_home1 = (HelloHome)session1.activate (objectName);
    HelloHome hello_home2 = (HelloHome)session2.activate (objectName);

    //create the bean and retrieve the remote interface
    Hello hello1 = hello_home1.create ();
    Hello hello2 = hello_home2.create ();

    // Verify that the objects are indeed different
    System.out.println (hello1.helloWorld ());
    System.out.println (hello2.helloWorld ());

##### Two Clients Accessing the Same Session

When the client invokes the JNDI lookup method, JServer creates a session. If you want a second client to access the instantiated object in this session, you must do the following:

1. The first client saves both the object instance handle and a `Login` object reference.

2. The second client retrieves the handle and `Login` object reference and uses them to access the object instance.

   #### Example 5-2 Two Clients Accessing a Single Instance

3. The first client authenticates itself to the database by providing a username and password through the `authenticate` method on a `Login` object.

4. The session is created through the `lookup` method given the URL.

5. The bean is instantiated with the `create` method of the home interface.

6. Both the `LoginServer` object and the server object instance handle are saved to a file for the second client to retrieve.

       // Login to the 8i server
       LoginServer lserver = (LoginServer)ic.lookup (serviceURL + "/etc/login");
       new Login (lserver).authenticate (username, password, null);

       // Activate a Hello in the 8i server
       // This creates a first session in the server
       HelloHome hello_home = (HelloHome)ic.lookup (serviceURL + objectName);
       Hello hello = hello_home.create ();
       hello.setMessage ("As created by Client1");
       System.out.println ("Client1: " + hello.helloWorld ());

       // save Login object into a file, loginFile, for Client2 to read
       com.visigenic.vbroker.orb.ORB orb = oracle.aurora.jndi.orb_dep.Orb.init();
       String log = orb.object_to_string (lserver);
       OutputStream os = new FileOutputStream (loginFile);
       os.write (log.getBytes ());
       os.close ();

       // save object instance handle into a file, helloFile,

       // for Client2 to read
       Handle obj_hndl = testBean.getHandle ();
       OutputStream os = new FileOutputStream (helloFile);
       os.write (obj_hndl.getBytes ());
       os.close ();

The second client would access the `Hello` object instance in the active session by doing the following:

1. Retrieve the object handle and the `Login` object. This example uses implementation-defined methods of `readHandle` and `readLogin` to retrieve these objects from storage.

2. Retrieve the EJB reference through the `getEJBObject` method.

3. Authenticate to the database session with the same `Login` object as the first client through the `authenticate` method. You can recreate the `Login` object from the `LoginServer` object through the `Login` constructor.

       FileInputStream finstream = new FileInputStream (hellofile);
       ObjectInputStream istream = new ObjectInputStream (finstream);
       javax.ejb.Handle handle  = (javax.ejb.Handle)istream.readObject ();
       Hello hello = (Hello)helloHandle.getEJBObject ();
       finstream.close ();

       // Authenticate with the login Object
       LoginServer lserver = (LoginServer) readLogin(loginFile);

       //Set the VisiBroker bind options to specify that the
       //login is to not try recursively, which means that if it
       //fails on the first try, return with the error immediately.
       //See VisiBroker manuals for more information.
       lserver._bind_options (new BindOptions (false, false));

       Login login = new Login (lserver);
       login.authenticate (username, password, null);

##### In-Session Activation

If the server object wants to look up and activate a new published object in the same session in which it is running, the server object can execute the following:

    Context ic = new InitialContext( );
    SomeObject myObj = (SomeObject) ic.lookup("/test/Hello");

Notice that there are no environment settings for authentication information in the environment or a session URL in the lookup. The authentication already succeeded in order to log into the session. Plus, the object exists on the local machine. So, any other object activation within the session can proceed without specifying authentication information or a target `sess_iiop` URL address.

Note: In-session activation as demonstrated in this section is valid for both IIOP and non-IIOP clients.

##### In-Session Activation in Pre-8.1.7 Releases

In releases previous to Release 8.1.7, in-session activation was performed with the `thisServer/:thisSession` notation in place of the `hostname:port:SID` in the URL. This notation is still valid, but only for IIOP clients.

For example, to look up and activate an object in the same session, do the following:

    Hashtable env = new Hashtable();
    env.put(Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
    Context ic = new InitialContext(env);
    SomeObject myObj =
       (SomeObject) ic.lookup("sess_iiop://thisServer/:thisSession/test/Hello");

In this case, `myObj` is activated in the same session in which the invoking object is running. Note that there is no need to supply login authentication information, as the client (a server object in this case) is already authenticated to Oracle8i.

Realize that objects are not authenticated, instead, clients must be authenticated to a session. However, when a separate session is to be started, then some form of authentication must be done--either login or SSL credential authentication.

Note: You can only use the `thisServer` notation on the server side, that is, from server objects. You cannot use it in a client program.

##### Lookup of Objects Off of JNDI Context

In the Sun Microsystems JNDI, if you bind a name of "`/test/myObject`", you can retrieve an object from a `Context` when executing the following:

    Context ctx = ic.lookup("/test");
    MyObject myobj = ctx.lookup("myObject");

The returned object is activated and ready for you to perform method invocations off of it.

In Oracle8i, trying to retrieve an object from a `Context` results in an inactive object being returned. Instead, you must do the following:

1. Retrieve a `SessionCtx`, instead of a `Context`. You can retrieve the `SessionCtx` from a `ServiceCtx`, in one of the two following ways:

   - Retrieve the `ServiceCtx` first and the `SessionCtx` from the `ServiceCtx`, as follows:

         ServiceCtx service =
                 (ServiceCtx) ic.lookup("sess_iiop://localhost:2481:ORCL");
         //Retrieve the ServiceCtx subcontext
         SessionCtx sess = (SessionCtx) service.lookup("/test");

   - Retrieve the `ServiceCtx` and `SessionCtx` in the same lookup, as follows:

         SessionCtx sess =
                 (SessionCtx) ic.lookup("sess_iiop://localhost:2481:ORCL/test");

2. Execute the Oracle-specific `SessionCtx.activate` method for each object in the session that you want to retrieve. This method activates the object in the session and returns the object reference. You cannot just perform a `lookup` of the object, as it will return an inactive object. Instead, execute the `activate` method, as follows:

       MyObjectHome myObj_home = (MyObjectHome) sess.activate("myObject");

3. Finally, create the bean instance and invoke the bean's methods.

       //create the bean and retrieve the remote interface
       MyObject myObj = myObj_home.create ();

       // Verify that the objects are indeed different
       System.out.println (myObj.printMe ());

The JServer JNDI implementation provides two implementations of the `Context` object:

- `ServiceCtx`--identifies the database instance through a `sess_iiop` URL

- `SessionCtx`--represents database session within the database

In performing a lookup, you must lookup both the `ServiceCtx` for identifying the database and the `SessionCtx` for retrieving the actual JNDI bound object. Normally, you supply the URLs for both objects within the JNDI URL given to the `lookup` method. However, you can also retrieve each individually as demonstrated above.

### Setting Session Timeout

A session--with its state--normally exits when the last connection terminates. However, there are situations where you may want a session and its state to idle for a specified amount of time after the last connection terminates, such as the following:

- A middle-tier layer does not want to keep connections open to the session because connections are expensive; but, the middle-tier may want to keep the session open in case of another incoming client request.

- If you experience a network problem that abnormally terminates the connection, the session will stay around for the specified amount of time to allow the connection to be re-established.

- If your application passes a handle to an existing object within the session to another client before its connection terminates, the second client has time to access the session.

The timeout clock starts when the last connection to the session terminates. If another connection to the session starts within the timed window, the timeout clock is reset. If not, the session exits.

You can set the session idle timeout either from the client or from within a server object:

- Set the Session Timeout from the Client

- Set the Session Timeout from a Server Object

#### Set the Session Timeout from the Client

You can set the idle timeout on the client through the pre-published utility object--`oracle.aurora.AuroraServices.Timeout`. This object is pre-published under "`/etc/timeout`". Use the `setTimeout` method from this object.

1. Retrieve the `Timeout` object through a JNDI lookup of "`/etc/timeout`"

2. Set the timeout with the `setTimeout` method giving the number of seconds for session idle.

       Timeout timeout = (Timeout)ic.lookup(serviceURL + "/etc/timeout");
       System.out.println("Setting a timeout of 20 seconds ");
       timeout.setTimeout(20);

#### Set the Session Timeout from a Server Object

A server object can control the session timeout by using the `oracle.aurora.net.Presentation` object, which contains the `sessionTimeout()` method. This method takes one parameter; the session timeout value in seconds. For example:

    int timeoutValue = 30;
    ...
    // set the timeout to 30 seconds
    oracle.aurora.net.Presentation.sessionTimeout(timeoutValue);
    ...
    // set the timeout to a very long time
    oracle.aurora.net.Presentation.sessionTimout(Integer.MAX_INT);

Note: When you use the `sessionTimeout()` method, you must add `$(ORACLE_HOME)/javavm/lib/aurora.zip to` your CLASSPATH.

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