Oracle9i Enterprise JavaBeans Developer's Guide and Reference Release 1 (9.0.1) Part Number A90188-01 |
|
This chapter describes in detail how clients connect to an Oracle9i server session and how they authenticate themselves to the server. The term client, as used in this chapter, includes client applications and applets running on a network PC or a workstation, as well as distributed objects such as EJBs and CORBA server objects that are calling other distributed server objects and, thus, acting as clients to these objects.
In addition to authentication, this chapter discusses security of access control to objects in the database. A published object in the data server has a set of permissions that determine who can access and modify the object. In addition, classes that are loaded in the data server are loaded into a particular schema, and the person who deploys the classes can control who can use them.
This chapter covers the following topics:
The client example in Chapter 2 shows how to connect to Oracle, start a database server session, and activate an object using a single URL specification. This is performed through the following steps:
1. Hashtable env = new Hashtable(); 2. env.put(javax.naming.Context.URL_PKG_PREFIXES, "oracle.aurora.jndi"); 3. env.put(javax.naming.Context.SECURITY_PRINCIPAL, username); 4. env.put(javax.naming.Context.SECURITY_CREDENTIALS, password); 5. env.put(javax.naming.Context.SECURITY_AUTHENTICATION,
ServiceCtx.NON_SSL_LOGIN); 6. Context ic = new InitialContext(env); 7. HelloHome hello_home = (HelloHome) ic.lookup("sess_iiop://localhost:2481:ORCL/test/myHello"); myHello hello = hello_home.create (); 8. System.out.println(hello.helloWorld());
In this example, there are four basic operations:
When a client looks up an object through the JNDI lookup
method, the client and server automatically perform the following logic:
/test/myHello
, is located in the session namespace, and a reference to it is returned to the client.
When the client invokes a method--such as helloWorld()
--on the returned reference, the server activates the object in the server.
The name space in the database looks just like a typical file system. You can examine and manipulate objects in the publishing name space using the session shell tool. See the sess_sh
tool in the Oracle9i Java Tools Reference for information about the session shell.
There is a root directory, indicated by a forward slash ('/'). The root directory is built to contain three other directories: bin
, etc
, and test
. The /test
directory is where most objects are published for the example programs. You can create new directories under root to hold objects for separate projects; however, you must have access as database user SYS to create new directories under the root.
There is no effective limit to the depth that you can nest directories.
The /etc
directory contains objects that the ORB uses. The objects contained in /etc
are:
deployejb execute loadjava login transactionFactory
Do not delete objects in the /etc
directory.
The entries in the name space are represented by objects that are instances of the following classes:
oracle.aurora.AuroraServices.PublishingContext
--represents a class that can contain other objects (a directory)
oracle.aurora.AuroraServices.PublishedObject
--used for the leafs of the tree--that is, the object names themselves.
The javadoc on the product CD documents these classes.
Published names for objects are stored in a database table. Each published object also has a set of associated permissions. Each class or resource file can have a combination (union) of the following permissions:
The holder of read rights can list the class or the attributes of the class, such as its name, its helper class, and its owner.
The holder of write for a context can bind new object names into a context. For an object (a leaf node of the tree), write allows the holder to republish the object under a different name.
You must have execute rights to resolve and activate an object represented by a context or published object name.
You use the chmod
command of the session shell tool to view and change object rights.
In addition to authentication and privacy, Oracle9i supports controlled access to the classes that make up CORBA and EJB objects. Only users or roles that have been granted execute rights to the Java class of an object stored in the database can activate the object and invoke methods on it.
You can control execute rights on Java classes with the following tools:
-grant
argument to loadjava
. See the Oracle9i Java Developer's Guide for more information about loadjava
and execution rights on Java classes in the database.
Hello
class, then SCOTT (or SYS) can grant execute privileges on that class to another user, say OTTO, by issuing the SQL command:
SQL> GRANT EXECUTE ON "Hello" TO OTTO;
Use the SQL command REVOKE EXECUTE to remove execute rights for a user from a loaded Java class.
You can control permissions on a published object through the following:
-grant
option with the publish
tool.
chmod
and chown
commands within the Session Shell. You must be connected to the Session Shell as the user SYS to use the chown
command.
Use the ls -l
command in the session shell to view the permissions (EXECUTE, READ, and WRITE) and the owner of a published object.
A client can access the following three built-in server objects without being authenticated:
You can activate these objects using serviceCtx.lookup()
without authentication. See the "Logging In and Out of the Oracle9i Session" for an example that access the Login
object explicitly.
Oracle9i provides universal resource locator (URL) syntax to access services and sessions. The URL lets you use JNDI requests to start up services and sessions, and also to access components published in the database instance. An example service URL is shown in Figure 5-1.
Four components make up the service URL:
myPC-1
. You can also use localhost
or the numeric form of the IP address for the host.
ORCL
--or the service name--for example, mySID.myDomain
.
service_name
or the db_name.db_domain
parameters defined in your database initialization file. If you use the service name within your service URL, the listener will load balance incoming requests across multiple database instances: that is, all database instances registered with the listener. This option is good when you are using parallel servers.
Always use colons to separate the hostname, port, and SID or service name.
When you make a connection to Oracle and look up a published object using JNDI, you use a URL that specifies the service (service name, host, port, and SID), as well as the name of a published object to look up and activate. For example, a complete URL could look like:
sess_iiop://localhost:2481:ORCL/:default/projectAurora/Plans816/getPlans
where sess_iiop://localhost:2481:ORCL
specifies the service name, :default
indicates the default session (when a session has already been established), /projectAurora/Plans816
specifies a directory path in the namespace, and getPlans
is the name of a published object to look up.
Each component of the URL represents a Java class. For example, the service name is represented by a ServiceCtx
class instance, and the session by a SessionCtx
instance. See "Using JNDI to Access Bound Objects" and "Session IIOP Service" starting for more information on the service and session names within the URL.
The JNDI bound name for the published object must use JNDI syntax rules. The underlying naming service that Oracle9i JNDI uses is CosNaming. Thus, if your name includes a dot (".") in one of the names, the behavior diverges from normal CosNaming rules, as follows:
NameComponent
id.
NameComponent
kind.
Normally, in retrieving a CosNaming object, you supply the id and kind as separate entities. The Oracle9i implementation concatenates both id and kind. Thus, to retrieve the object, your application refers to the full name with the dot included as part of the JNDI name, rather than as a separator.
Clients use JNDI to look up published objects in the Oracle9i namespace. JNDI is an interface supplied by Sun Microsystems that gives the Java application developer a methodology to access name and directory services. This section discusses only those parts of the JNDI API that are needed to look up and activate published objects. To obtain a complete set of documentation for JNDI, see the Web site URL: http://java.sun.com/products/jndi/index.html
.
As described in "URL Syntax", the JNDI URL required to access any bound name in the Oracle9i namespace requires a compound name consisting of the following two components:
Several namespaces will exist within your network. The service specifies from which namespace to retrieve the JNDI bound object. Service names can be one of the following:
Service Name | Description |
---|---|
|
Specifies the host, port, and SID where the desired namespace is located. Specifying this service name only, without a session name, returns a |
|
Specifies that the desired object exists in a well-known namespace. Used primarily to retrieve JTA |
|
Used to specify that the bound name is actually an EJB environment variable that was specified within its deployment descriptor. |
SessionCtx
object.
You can utilize the service and session contexts to perform some advanced techniques, such as opening different sessions within a database or enabling several clients to access an object in a single session. These are discussed further in the "Session IIOP Service". However, for simple JNDI lookup invocations, you should use the URL syntax specified in "URL Syntax".
When you use JNDI in your client or server object implementations, be sure to include the following import statements in each source file:
import javax.naming.Context; // the JNDI Context interface import javax.naming.InitialContext; import oracle.aurora.jndi.sess_iiop.ServiceCtx; // JNDI property constants import java.util.Hashtable; // hashtable for the initial context environment
Context
is an interface in the javax.naming
package that is used to retrieve the InitialContext
. All Oracle9i EJB and CORBA clients use the InitialContext
for JNDI lookup()
. Before you perform a JNDI lookup()
, set the environment variables, such as authentication information into the Context
. You can use a hash table or a properties list for the environment. Then, this information is made available to the naming service when the lookup()
is performed. The examples in this guide always use a Java Hashtable
, as follows:
Hashtable environment = new Hashtable();
Next, set up properties in the hash table. You must always set the Context
URL_PKG_PREFIXES
property, whether you are on the client or the server. The remaining properties are used for authentication, which are primarily used by clients or by a server authenticating itself as another user.
javax.naming.Context.URL_PKG_PREFIXES
javax.naming.Context.SECURITY_PRINCIPAL
javax.naming.Context.SECURITY_CREDENTIALS
javax.naming.Context.SECURITY_ROLE
javax.naming.Context.SECURITY_AUTHENTICATION
USE_SERVICE_NAME
Context.URL_PKG_PREFIXES
holds the name of the environment property for specifying the list of package prefixes to use when loading in URL context factories. The value of the property should be a colon-separated list of package prefixes for the class name of the factory class that will create a URL context factory.
In the current implementation, you must always supply this property in the Context environment, and it must be set to the String "oracle.aurora.jndi
".
Context.SECURITY_PRINCIPAL
holds the database username.
Context.SECURITY_CREDENTIAL
holds the clear-text password. This is the Oracle database password for the SECURITY_PRINCIPAL (the database user). In all of the three authentication methods mentioned in SECURITY_AUTHENTICATION below, the password is encrypted when it is transmitted to the server.
Context.SECURITY_ROLE
holds the Oracle9i database role with which the user is connecting. For example, "CLERK" or "MANAGER".
Context.SECURITY_AUTHENTICATION
holds the name of the environment property that specifies the type of authentication to use. Values for this property provide for the authentication types supported by Oracle9i. There are four possible values, which are defined in the ServiceCtx
class:
ServiceCtx.NON_SSL_LOGIN
: The client authenticates itself to the server with a username and password, using the Login protocol over a standard TCP/IP connection (not a secure socket layer connection). The Login protocol encrypts the password as it is transmitted from the client to the server. The server does not authenticate itself to the client. See "Providing Username and Password for Client-Side Authentication" for more information about this protocol.
ServiceCtx.SSL_CREDENTIAL
: The client authenticates itself to the server providing a username and password that are encrypted over a secure socket layer (SSL) connection. The server authenticates itself to the client by providing credentials.
SSL_LOGIN
: The client authenticates itself to the server with a username and password within the Login protocol, over an SSL connection. The server does not authenticate itself to the client.
SSL_CLIENT_AUTH
: Both the client and the server authenticate themselves to each other by providing certificates to each other over an SSL connection.
If you are using a service name instead of an SID in the URL, set this property to true. Otherwise, the last string in the URL must contain the SID. Given a Hashtable within the variable env
, the following designates that the service name is used instead of the SID within the URL:
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);
env.put("USE_SERVICE_NAME", "true");
Context ic = new InitialContext(env);
The default is false.
The URL given within the lookup should contain a service name, instead of an SID. The following URL contains the service name orasun12
:
myHello hello =(myHello) ic.lookup("sess_iiop://localhost:2481:orasun12
/test/myHello");
InitialContext
is a class in the javax.naming
package that implements the Context
interface. All naming operations are relative to a context. The initial context implements the Context
interface and provides the starting point for resolution of names.
You construct a new initial context using the constructor:
public InitialContext(Hashtable environment)
It requires a Hashtable
for the input parameter that contains the environment information described in "Retrieving the JNDI InitialContext" above. The following code fragment sets up an environment for a typical client and creates a new initial context:
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);
This is the most common initial context class method that the CORBA or EJB application developer will use:
public Object lookup(String URL)
You use lookup()
to retrieve an object instance or to create a new service context.
HelloHome hello_home = (HelloHome) ic.lookup("sess_iiop://localhost:2481:ORCL/test/myHello"); myHello hello = hello_home.create ();
The service name is "sess_iiop://localhost:2481:ORCL
"; the JNDI bound name for Hello's home interface is "/test/myHello
".
ServiceCtx
when a new service context is being created. For example, if initContext
is a JNDI initial context, the following statement creates a new service context:
ServiceCtx service = (ServiceCtx) initContext.lookup("sess_iiop://localhost:2481:ORCL");
See "Session Management Scenarios" for examples of how to use the JNDI lookup
method within an EJB or CORBA application.
All client/server network communications route requests over an accepted protocol between both entities. Most network communications to the Oracle9i database are routed over the two-task common (TTC) layer. This is the service that processes incoming Oracle Net requests for database SQL services. However, with the addition of Java into the database, Oracle9i requires that clients communicate with the server over an IIOP transport that recognizes 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:
As discussed in the Oracle9i 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. However, you can activate objects either 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 Oracle9i 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.
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 Oracle9i has been extended to support session IIOP.
When a client makes an IIOP connection to the database, Oracle9i determines 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, a client can use this session identifier to access multiple sessions. See "Session Management Scenarios" for more information.
When using the Oracle9i JVM tools, especially when developing EJB and CORBA applications, it is important to distinguish the two network service protocol types: TTC and IIOP.
Figure 5-2 shows which tools and requests use TTC and which use IIOP database ports. The default port number for TTC is 1521, and the default for IIOP is 2481.
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.
loadjava
and dropjava
connect using a TTC port.
In 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. Oracle9i also gives you the ability to control session start-up explicitly. Two Oracle-specific classes give you control over the session IIOP service connection and over the sessions within the database:
Given a URL to that database, you can create a service context. You can open one or more named sessions within the database off of this service context.
Once the session has been created, you can activate CORBA or EJB objects within the session using the named session context object.
The service context class controls the session IIOP service connection to the database. Given a URL to that database, you can create a service context. You can open one or more named sessions within the database off of this service context. This Oracle-specific class extends the JNDI Context
class.
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.
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.
This method can throw the exception: 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)
This method retrieves access to the ORB that is 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 the sharedsession example in Appendix A of the Oracle9i CORBA Developer's Guide and Reference for a usage example.
public Object lookup(String string)
The lookup
method 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.
The session context class controls named database sessions that are created off of a service context. Once the session has been 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. |
The session context methods that a client uses are the following:
public synchronized boolean login()
The login
method 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)
The login
method authenticates the client, using the username, password, and optional database role supplied as parameters.
public Object activate(String name)
The activate
method looks up and activates a published object with the given name.
The following sections describe the five different scenarios for managing database sessions:
default
session.
SessionCtx
.
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 you invoke the lookup
method within the server object, the second object instance is activated in a separate session from the originating 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:
The server can control session termination by executing the following method:
oracle.aurora.mts.session.Session.THIS_SESSION().endSession();
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();
You can explicitly create multiple sessions 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 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. Because each session is a named session, you can activate objects in different sessions within the database.
Hashtable env = new Hashtable(); env.put(Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
Context ic = new InitialContext(env);
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.
ServiceCtx service = (ServiceCtx) ic.lookup("sess_iiop://localhost:2481:ORCL");
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");
login
method on the session context object.
session.login("scott", "tiger", null); // role is null
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);
Hello hello = hello_home.create (); System.out.println (hello.helloWorld ());
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 ());
When the client invokes the JNDI lookup method, Oracle9i creates a session. If you want a second client to access the instantiated object in this session, you must do the following:
Login
object reference.
Login
object reference and uses them to access the object instance.
authenticate
method on a Login
object.
lookup
method that is given the URL.
create
method of the home interface.
LoginServer
object and the server object instance handle are saved to a file for the second client to retrieve.
// Login to the 9i serverLoginServer lserver = (LoginServer)ic.lookup (serviceURL + "/etc/login");
new Login (lserver).authenticate (username, password, null);
// Activate a Hello in the 9i server // This creates a first session in the serverHelloHome 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 accesses the Hello
object instance in the active session by doing the following:
Login
object. This example uses implementation-defined methods of readHandle
and readLogin
to retrieve these objects from storage.
getEJBObject
method.
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);
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.
All object parameters designated within in-session object methods use pass-by-reference semantics, instead of pass-by-value semantics. The following example contains a single input object parameter of myParmObj
into the foo
method for the previously retrieved in-session object, myObj
.
myObj.foo(myParmObj);
With pass-by-reference, the reference to the input object parameter is directly passed to the destination server object. Any changes to the contents of the myParmObj
on the client or the server are reflected to the other party--as both parties reference the same object. Alternatively, if it were pass-by-value, a copy of the myParmObj
object would be passed. In this case, any changes to the party's copy of myParmObj
would be visible only with the party that made the changes.
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, because the client (a server object, in this case) is already authenticated to Oracle9i.
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.
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 Oracle9i, trying to retrieve an object from a Context
results in an inactive object being returned. Instead, you must do the following:
SessionCtx
, instead of a Context
. You can retrieve the SessionCtx
from a ServiceCtx
, in one of the two following ways:
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");
ServiceCtx
and SessionCtx
in the same lookup, as follows:
SessionCtx sess = (SessionCtx) ic.lookup("sess_iiop://localhost:2481:ORCL/test");
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");
//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 Oracle9i 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.
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:
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:
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.
Timeout
object through a JNDI lookup of "/etc/timeout
"
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);
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);
You can retrieve the version of Oracle9i that is installed in the database through the pre-published oracle.aurora.AuroraServices.Version
object, which is published as "/etc/version
" in the JNDI namespace. The Version
object contains the getVersion
method, which returns a string that contains the version, such as "8.1.7". You can retrieve the Version
object by providing "/etc/version
" within the JNDI lookup. The following example retrieves the version number:
Version version = (Version)ic.lookup(serviceURL + "/etc/version"); System.out.println("The server version is : " + version.getVersion());
Non-IIOP server requests, such as HTTP or DCOM, can activate an EJB object within the same session.
If the non-IIOP 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 URL specified 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 URL address.
You invoke a server object from an applet in the same manner as from a client. The only differences are the following:
ORBdisableLocator
, ORBClass
, and ORBSingletonClass.
The security sandbox constricts your applet from accessing anything on the local disk or from connecting to a remote host other than the host that the applet was downloaded from. If you create a signed JAR file as a trusted party, you can bypass the sandbox security. See http://java.sun.com
for more information on applet sandbox security and signed JAR files.
You perform the JNDI lookup within the applet the same as within any Oracle Java client, except that you set the following property within the initial context:
env.put(ServiceCtx.APPLET_CLASS, this);
By default, you do not need to install any JAR files on the client to run the applet. However, if you want to place the Oracle JAR files on the client machine, set the ClassLoader
property in the InitialContext
environment, as follows:
env.put('ClassLoader', this.getClass().getClassLoader());
The following shows the init
method within an applet that invokes the Bank example. The applet sets up the initial context--including setting the APPLET_CLASS
property--and performs the JNDI lookup giving the URL.
public void init() { // This GUI uses a 2 by 2 grid of widgets. setLayout(new GridLayout(2, 2, 5, 5)); // Add the four widgets. add(new Label("Account Name")); add(_nameField = new TextField()); add(_checkBalance = new Button("Check Balance")); add(_balanceField = new TextField()); // make the balance text field non-editable. _balanceField.setEditable(false); try { // Initialize the ORB (using the Applet).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);
env.put(ServiceCtx.APPLET_CLASS, this);
Context ic = new InitialContext(env);
_manager = (AccountManager)ic.lookup
} catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); throw new RuntimeException(); } }
("sess_iiop://hostfunk:2222/test/myBank");
Within the action
method, the applet invokes methods off of the retrieved object. In this example, the open
method of the retrieved AccountManager
object is invoked.
public boolean action(Event ev, Object arg) {
if(ev.target == _checkBalance) {
// Request the account manager to open a named account.
// Get the account name from the name text widget.
Bank.Account account = _manager.open(_nameField.getText());
// Set the balance text widget to the account's balance.
_balanceField.setText(Float.toString(account.balance()));
return true;
}
return false;
}
Oracle9i supports only the following Java plug-ins for the HTML page that loads in the applet: JDK 1.1, Java 2, and Oracle JInitiator. Each plug-in contains different syntax for the applet information. However, each HTML page may contain definitions for the following two properties:
ORBdisableLocator
set to TRUE--Required for all applets.
ORBClass
and ORBSingletonClass
definitions--Required for the applets that use the Java 2 or JInitiator plug-in.
The examples in the following sections show how to create the correct HTML definition for each plug-in type. Each HTML definition defines the applet bank example.
<pre> <html> <title>Applet talking to 8i</title> <h1>applet talking to 8i using java plug in 1.1 </h1> <hr> The bank example Specify the plugin in codebase, the class within the CODE parameter, the JAR files in the ARCHIVE parameter, the plugin version in the type parameter, and set ORBdisableLocator to true. <OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
WIDTH = 500 HEIGHT = 50
codebase="http://java.sun.com/products/plugin/1.1/
<COMMENT> Set the plugin version in the type, set ORBdisableLocator to true, the applet class within the java_CODE tag, the JAR files in the java_ARCHIVE tag, and the plug-in source site within the pluginspage tag.
jinstall-11-win32.cab#Version=1,1,0,0">
<PARAM NAME = CODE VALUE = OracleClientApplet.class >
<PARAM NAME = ARCHIVE VALUE = "oracleClient.jar,
aurora_client.jar,vbjorb.jar,vbjapp.jar" >
<PARAM NAME="type" VALUE="application/x-java-applet;version=1.1">
<PARAM NAME="ORBdisableLocator" VALUE="true"><EMBED type="application/x-java-applet;version=1.1"
ORBdisableLocator="true"
java_CODE = OracleClientApplet.class
java_ARCHIVE = "oracleClient.jar,
aurora_client.jar,vbjorb.jar,vbjapp.jar"
WIDTH = 500 HEIGHT = 50
pluginspage="http://java.sun.com/products/plugin/1.1/plugin-install.html">
<NOEMBED></COMMENT> </NOEMBED></EMBED> </OBJECT> </center> <hr> </pre>
<pre> <html> <title>applet talking to 8i</title> <h1>applet talking to 8i using Java plug in 1.2 </h1> <hr> The bank example Specify the plugin in codebase, the class within the CODE parameter, the JAR files in the ARCHIVE parameter, the plugin version in the type parameter, and set ORBdisableLocator to true. <OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
WIDTH = 500 HEIGHT = 50
codebase="http://java.sun.com/products/plugin/1.2/jinstall-11-win32.cab#
<COMMENT> Set the plugin version in the type, set ORBdisableLocator to true, the ORBClass and ORBSingletonClass to the correct ORB class, the applet class within the java_CODE tag, the JAR files in the java_ARCHIVE tag, and the plug-in source site within the pluginspage tag.
Version=1,1,0,0">
<PARAM NAME = CODE VALUE = OracleClientApplet.class >
<PARAM NAME = ARCHIVE VALUE = "oracleClient.jar,
aurora_client.jar,vbjorb.jar,vbjapp.jar" >
<PARAM NAME="type" VALUE="application/x-java-applet;version=1.1.2">
<PARAM NAME="ORBdisableLocator" VALUE="true">
<PARAM NAME="org.omg.CORBA.ORBClass" VALUE="com.visigenic.vbroker.orb.ORB">
<PARAM NAME="org.omg.CORBA.ORBSingletonClass"
VALUE="com.visigenic.vbroker.orb.ORB"><EMBED type="application/x-java-applet;version=1.1.2"
ORBdisableLocator="true"
org.omg.CORBA.ORBClass="com.visigenic.vbroker.orb.ORB"
org.omg.CORBA.ORBSingletonClass="com.visigenic.vbroker.orb.ORB"
java_CODE = OracleClientApplet.class
java_ARCHIVE = "oracleClient.jar,
aurora_client.jar,vbjorb.jar,vbjapp.jar"
WIDTH = 500 HEIGHT = 50
pluginspage="http://java.sun.com/products/plugin/1.2/plugin-install.html">
<NOEMBED></COMMENT> </NOEMBED></EMBED> </OBJECT> </center> <hr> </pre>
<h1> applet talking to 8i using JInitiator 1.1.7.18</h1> <COMMENT> Set the plugin version in the type, set ORBdisableLocator to true, the ORBClass and ORBSingletonClass to the correct ORB class, the applet class within the java_CODE tag, the source of the applet in the java_CODEBASE and the JAR files in the java_ARCHIVE tag.<EMBED type="application/x-jinit-applet;version=1.1.7.18"
java_CODE="OracleClientApplet"
java_CODEBASE="http://hostfunk:8080/applets/bank"
java_ARCHIVE="oracleClient.jar,aurora_client.jar,vbjorb.jar,vbjapp.jar"
WIDTH=400
HEIGHT=100
ORBdisableLocator="true"
org.omg.CORBA.ORBClass="com.visigenic.vbroker.orb.ORB"
org.omg.CORBA.ORBSingletonClass="com.visigenic.vbroker.orb.ORB"
serverHost="orasundb"
serverPort=8080
<NOEMBED> </COMMENT> </NOEMBED> </EMBED>
|
Copyright © 1996-2001, Oracle Corporation. All Rights Reserved. |
|