BEA Logo BEA WebLogic Enterprise Release 5.0

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

 

   WLE Doc Home   |   CORBA Programming & Related Topics   |   Previous   |   Next   |   Contents   |   Index

FactoryFinder Interface

This chapter contains the following topics:

The FactoryFinder interface provides clients with one object reference that serves as the single point of entry into the WLE domain. The WLE NameManager provides the mapping of factory names to object references for the FactoryFinder. Multiple FactoryFinders and NameManagers together provide increased availability and reliability. In this release, the level of functionality has been extended to support multiple domains.

Note: The NameManager is not a naming service, such as CORBAservices Naming Service, but is merely a vehicle for storing registered factories.

In the WLE environment, application factory objects are used to create objects that clients interact with to perform their business operations (for example, TellerFactory and Teller). Application factories are generally created during server initialization and are accessed by both remote clients and clients located within the server application.

The FactoryFinder interface and the NameManager services are contained in separate (nonapplication) servers. A set of application programming interfaces (APIs) is provided so that both client and server applications can access and update the factory information.

The support for multiple domains in this release benefits customers that need to scale to a large number of machines or who want to partition their application environment. To support multiple domains, the mechanism used to find factories in a WLE environment has been enhanced to allow factories in one domain to be visible in another. The visibility of factories in other domains is under the control of the system administrator.

Capabilities, Limitations, and Requirements

During server application initialization, application factories need to be registered with the NameManager. Clients can then be provided with the object reference of a FactoryFinder to allow them to retrieve a factory object reference based on associated names that were created when the factory was registered.

The following functional capabilities, limitations, and requirements apply to this release:

Functional Description

The WLE environment promotes the use of the factory design pattern as the primary means for a client to obtain a reference to an object. Through the use of this design pattern, client applications require a mechanism to obtain a reference to an object that acts as a factory for another object. Because the WLE environment has chosen CORBA as its visible programming model, the mechanism used to locate factories is modeled after the FactoryFinder as described in the CORBAservices Specification, Chapter 6 "Life Cycle Service," December 1997, published by the Object Management Group.

In the CORBA FactoryFinder model, application servers register active factories with a FactoryFinder. When an application server's factory becomes inactive, the application server removes the corresponding registration from the FactoryFinder. Client applications locate factories by querying a FactoryFinder. The client application can control the references to the factory object returned by specifying criteria that is used to select one or more references.

Locating a FactoryFinder

A client application must obtain a reference to a FactoryFinder before it can begin locating an appropriate factory. To obtain a reference to a FactoryFinder in the domain to which a client application is associated, the client application must invoke the Tobj_Bootstrap.resolve_initial_references operation with a value of "FactoryFinder" . This operation returns a reference to a FactoryFinder that is in the domain to which the client application is currently attached. For more information, see the description of the com.beasys.Tobj_Bootstrap object in the Java API Reference.

Note: The references to the FactoryFinder that are returned to the client application can be references to factory objects that are registered on the same machine as the FactoryFinder, on a different machine than the FactoryFinder, or possibly in a different domain than the FactoryFinder.

Registering a Factory

For a client application to be able to obtain a reference to a factory, an application server must register a reference to any factory object for which it provides an implementation with the FactoryFinder (see Figure 5-1). Using the WLE TP Framework, the registration of the reference for the factory object can be accomplished using the TP.register_factory operation, once a reference to a factory object has been created. The reference to the factory object, along with a value that identifies the factory, is passed to this operation. The registration of references to factory objects is typically done as part of initialization of the application; normally, as part of the implementation of the Server.initialize operation.

Figure 5-1 Registering a Factory Object

When the server application is shutting down, it must unregister any references to the factory object that it has previously registered in the application server. This is done by passing the same reference to the factory object, along with the corresponding value used to identify the factory, to the TP.unregister_factory operation. Once unregistered, the reference to the factory object can then be destroyed. The process of unregistering a factory with the FactoryFinder is typically done as part of the implementation of the Server.release operation. For more information about these operations, see the section "Java TP Framework Interfaces" on page 3-18.

Locating a Factory

For a client application to request a factory to create a reference to an object, it must first obtain a reference to the factory object. The reference to the factory object is obtained by querying a FactoryFinder with specific selection criteria, as shown in Figure 5-2. The criteria are determined by the format of the particular FactoryFinder interface and method used.

Figure 5-2 Locating a Factory Object

The WLE software extends the CosLifeCycle.FactoryFinder interface by introducing three methods in addition to the find_factories method declared for the FactoryFinder. Therefore, using the Tobj extensions, a client can use either the find_factories or find_factories_by_id methods to obtain a list of application factories. A client can also use the find_one_factory or find_one_factory_by_id method to obtain a single application factory, and the list_factories method to obtain a list of all registered factories.

The CosLifeCycle.FactoryFinder interface defines a factory_key , which is a sequence of id and kind strings conforming to the CosNaming Name shown in Listing 5-1. The kind field of the NameComponent for all WebLogic Enterprise application factories is set to the string FactoryInterface by the TP Framework when an application factory is registered. Applications supply their own value for the id field.

Assuming that the CORBAservices Life Cycle Service modules are contained in their own file (ns.idl and lcs.idl, respectively), only the OMG IDL code for that subset of both files that is relevant for using the WebLogic Enterprise FactoryFinder is shown in the following listings.

CORBAservices Naming Service Module OMG IDL

Listing 5-1 shows the portions of the ns.idl file that are relevant to the FactoryFinder.

Listing 5-1 CORBAservices Naming OMG IDL


// ------ ns.idl ------

module CosNaming {
typedef string Istring;
struct NameComponent {
Istring id;
Istring kind;
};
typedef sequence <NameComponent> Name;

};

// This information is taken from CORBAservices: Common Object
// Services Specification
, page 3-6. Revised Edition:
// March 31, 1995. Updated: November 1997. Used with permission by OMG.


CORBAservices Life Cycle Service Module OMG IDL

Listing 5-2 shows the portions of the lcs.idl file that are relevant to the FactoryFinder.

Listing 5-2 Life Cycle Service OMG IDL


// ----- lcs.idl -----

#include "ns.idl"

module CosLifeCycle{
typedef CosNaming::Name Key;
typedef Object Factory;
typedef sequence<Factory> Factories;

exception NoFactory{ Key search_key; }

interface FactoryFinder {
Factories find_factories(in Key factory_key)
raises(NoFactory);

};

};

// This information is taken from CORBAservices: Common Object
// Services Specification
, pages 6-10, 11. Revised Edition:
// March 31, 1995. Updated: November 1997. Used with permission by OMG.


Tobj Module OMG IDL

Listing 5-3 shows the Tobj Module OMG IDL.

Listing 5-3 Tobj Module OMG IDL


// ----- Tobj.idl -----

module Tobj {

// Constants

const string FACTORY_KIND = "FactoryInterface";

// Exceptions

exception CannotProceed { };
exception InvalidDomain {};
exception InvalidName { };
exception RegistrarNotAvailable { };

// Extension to LifeCycle Service

struct FactoryComponent {
CosLifeCycle::Key factory_key;
CosLifeCycle::Factory factory_ior;
};

typedef sequence<FactoryComponent> FactoryListing;

interface FactoryFinder : CosLifeCycle::FactoryFinder {
CosLifeCycle::Factory find_one_factory(in CosLifeCycle::Key
factory_key)
raises (CosLifeCycle::NoFactory,
CannotProceed,
RegistrarNotAvailable);
CosLifeCycle::Factory find_one_factory_by_id(in string
factory_id)
raises (CosLifeCycle::NoFactory,
CannotProceed,
RegistrarNotAvailable);
CosLifeCycle::Factories find_factories_by_id(in string
factory_id)
raises (CosLifeCycle::NoFactory,
CannotProceed,
RegistrarNotAvailable);
FactoryListing list_factories()
raises (CannotProceed,
RegistrarNotAvailable);
};
};


Locating Factories in Another Domain

Typically, a FactoryFinder returns references to factory objects that are in the same domain as the FactoryFinder itself. However, it is possible to return references to factory objects in domains other than the domain in which a FactoryFinder exists. This can occur if a FactoryFinder contains information about factories that are resident in another domain (see Figure 5-3). A FactoryFinder finds out about these interdomain factory objects through configuration information that describes the location of these other factory objects.

When a FactoryFinder receives a request to locate a factory object, it must first determine if a reference to a factory object that meets the specified criteria exists. If there is registration information for a factory object that matches the criteria, the FactoryFinder must then determine if the factory object is local to the current domain or needs to be imported from another domain. If the factory object is from the local domain, the FactoryFinder returns the reference to the factory object to the client.

Figure 5-3 Inter-domain FactoryFinder Interaction

If, on the other hand, the information indicates that the factory object is from another domain, the FactoryFinder delegates the request to an interdomain FactoryFinder in the appropriate domain. As a result, only a FactoryFinder in the same domain as the factory object will contain a reference to the factory object. The interdomain FactoryFinder is responsible for returning the reference of the factory object to the local FactoryFinder, which subsequently returns it to the client.

Why Use WLE Extensions?

The WLE software extends the interfaces defined in the CORBAservices specification, Chapter 6 "Life Cycle Service," December 1997, published by the Object Management Group, for the following reasons:

Therefore, WLE extends the interfaces defined in the CORBAservices specification to make using a FactoryFinder easier. The extensions are manifested as refined interfaces to the FactoryFinder that are derived from the interfaces specified in the CORBAservices specification.

Creating Application Factory Keys

Two of the four methods provided in the Tobj.FactoryFinder interface accept CosLifeCycle.Keys , which corresponds to CosNaming.Name . A client must be able to construct these keys.

The CosNaming Specification describes two interfaces that constitute a Names Library interface that can be used to create and manipulate CosLifeCycle.Keys . The pseudo OMG IDL statements for these interfaces is described in the following section.

Names Library Interface Pseudo OMG IDL

Note: This information is taken from the CORBAservices: Common Object Services Specification, pp. 3-14 to18. Revised Edition: March 31, 1995. Updated: November 1997. Used with permission by OMG.

To allow the representation of names to evolve without affecting existing client applications, it is desirable to hide the representation of names from the client application. Ideally, names themselves would be objects; however, names must be lightweight entities that are efficient to create, manipulate, and transmit. As such, names are presented to programs through the names library.

The names library implements names as pseudo-objects. A client application makes calls on a pseudo-object in the same way it makes calls on an ordinary object. Library names are described in pseudo-IDL (to suggest the appropriate language binding). C++ client applications use the same client language bindings for pseudo-IDL (PIDL) as they use for IDL.

Pseudo-object references cannot be passed across OMG IDL interfaces. As described in Chapter 3 of the CORBAservices: Common Object Services Specification, in the section "The CosNaming Module," the CORBAservices Naming Service supports the NamingContext OMG IDL interface. The names library supports an operation to convert a library name into a value that can be passed to the name service through the NamingContext interface.

Note: It is not a requirement to use the names library in order to use the CORBAservices Naming Service.

The names library consists of two pseudo-IDL interfaces, the LNameComponent interface and the LName interface, as shown in Listing 5-4.

Listing 5-4 Names Library Interfaces in Pseudo-IDL


interface LNameComponent { // PIDL
const short MAX_LNAME_STRLEN = 128;

exception NotSet{ };
exception OverFlow{ };

string get_id
raises (NotSet);
void set_id(in string i)
raises (OverFlow);
string get_kind()
raises(NotSet);
void set_kind(in string k)
raises (OverFlow);
void destroy();
};

interface LName { // PIDL
exception NoComponent{ };
exception OverFlow{ };
exception InvalidName{ };
LName insert_component(in unsigned long i,
in LNameComponent n)
raises (NoComponent, OverFlow);
LNameComponent get_component(in unsigned long i)
raises (NoComponent);
LNameComponent delete_component(in unsigned long i)
raises (NoComponent);
unsigned long num_components();
boolean equal(in LName ln);
boolean less_than(in LName ln);
Name to_idl_form()
raises (InvalidName);
void from_idl_form(in Name n);
void destroy();
};

LName create_lname();
LNameComponent create_lname_component();


Creating a Library Name Component

To create a library name component pseudo-object, use the following method:

LNameComponent create_lname_component();

The returned pseudo-object can then be operated on using the operations shown in Listing 5-4.

Creating a Library Name

To create a library name pseudo-object, use the following method:

LName create_lname();

The returned pseudo-object reference can then be operated on using the operations shown in Listing 5-4.

The LNameComponent Interface

A name component consists of two attributes: identifier and kind . The LNameComponent interface defines the operations associated with these attributes, as follows:

string get_id()
raises(NotSet);
void set_id(in string k);
string get_kind()
raises(NotSet);
void set_kind(in string k);

get_id

The get_id operation returns the identifier attribute's value. If the attribute has not been set, the NotSet exception is raised.

set_id

The set_id operation sets the identifier attribute to the string argument.

get_kind

The get_kind operation returns the kind attribute's value. If the attribute has not been set, the NotSet exception is raised.

set_kind

The set_kind operation sets the kind attribute to the string argument.
The LName Interface

The following operations are described in this section:

Destroying a Library Name Component Pseudo-Object

The destroy operation destroys library name component pseudo-objects.

void destroy();

Inserting a Name Component

A name has one or more components. Each component except the last is used to identify names of subcontexts. (The last component denotes the bound object.) The insert_component operation inserts a component after position i .

LName insert_component(in unsigned long i, in LNameComponent lnc)
raises(NoComponent, OverFlow);

If component i -1 is undefined and component i is greater than 1 (one), the insert_component operation raises the NoComponent exception.

If the library cannot allocate resources for the inserted component, the OverFlow exception is raised.

Getting the ith Name Component

The get_component operation returns the i th component. The first component is numbered 1 (one).

LNameComponent get_component(in unsigned long i)
raises(NoComponent);

If the component does not exist, the NoComponent exception is raised.

Deleting a Name Component

The delete_component operation removes and returns the i th component.

LNameComponent delete_component(in unsigned long i)
raises(NoComponent);

If the component does not exist, the NoComponent exception is raised.

After a delete_component operation has been performed, the compound name has one fewer component and components previously identified as i+1...n are now identified as i...n-1 .

Number of Name Components

The num_components operation returns the number of components in a library name.

unsigned long num_components();

Testing for Equality

The equal operation tests for equality with library name ln .

boolean equal(in LName ln);

Testing for Order

The less_than operation tests for the order of a library name in relation to library name ln .

boolean less_than(in LName ln);

This operation returns true if the library name is less than the library name ln passed as an argument. The library implementation defines the ordering on names.

Producing an OMG IDL form

Pseudo-objects cannot be passed across OMG IDL interfaces. The library name is a pseudo-object; therefore, it cannot be passed across the OMG IDL interface for the CORBAservices Naming Service. Several operations in the NamingContext interface have arguments of an OMG IDL-defined structure, Name . The following PIDL operation on library names produces a structure that can be passed across the OMG IDL request.

Name to_idl_form()
raises(InvalidName);

If the name is of length 0 (zero), the InvalidName exception is returned.

Translating an IDL Form

Pseudo-objects cannot be passed across OMG IDL interfaces. The library name is a pseudo-object; therefore, it cannot be passed across the OMG IDL interface for the CORBAservices Naming Service. The NamingContext interface defines operations that return an IDL struct of type Name . The following PIDL operation on library names sets the components and kind attribute for a library name from a returned OMG IDL defined structure, Name .

void from_idl_form(in Name n);

Destroying a Library Name Pseudo-Object

The destroy operation destroys library name pseudo-objects.

void destroy();

Java Mapping

The names library pseudo OMG IDL interface maps to the Java classes contained in the com.beasys.Tobj package, shown in Listing 5-5. All exceptions are contained in the same package.

For a detailed description of the Library Name class, refer to Chapter 3 in the CORBAservices: Common Object Services Specification.

Listing 5-5 Java Mapping for LNameComponent


package com.beasys.Tobj;

public class LNameComponent {
public static LNameComponent create_lname_component();
public static final short MAX_LNAME_STRING = 128;
public void destroy();
public String get_id() throws NotSet;
public void set_id(String i) throws OverFlow;
public String get_kind() throws NotSet;
public void set_kind(String k) throws OverFlow;
};

package com.beasys.Tobj;

public class LName {

public static LName create_lname();
public void destroy();
public LName insert_component(long i, LNameComponent n)
throws NoComponent, OverFlow;
public LNameComponent get_component(long i)
throws NoComponent;
public LNameComponent delete_component(long i)
throws NoComponent;
public long num_components();
public boolean equal(LName ln);
public boolean less_than(LName ln); // not implemented
public org.omg.CosNaming.NameComponent[] to_idl_form()
throws InvalidName;
public void from_idl_form(org.omg.CosNaming.NameComponent[] nr);
};


Java Methods

The documentation for the Java methods on the FactoryFinder interface is in the Java API Reference.

Java Programming Examples

The following listings show Java programming examples of how to program using the FactoryFinder interface.

Note: Remember to check for exceptions in your code.

Server Registering a Factory

Listing 5-6 shows how to program a server to register a factory.

Listing 5-6 Server Application: Registering a Factory


// Register the factory reference with the factory finder.
//
// The second parameter to TP.register_factory() is a string
// identifier that is used to identify the object.
// This same string is used in the call to TP.unregister_factory().
// It is also used in the call to find_one_factory_by_id() that
// is called by clients of this interface.
//
TP.register_factory(
fact_oref, // factory object reference
tellerFName // factory name
);


Client Obtaining a FactoryFinder Object Reference

Listing 5-7 shows how to program a client to get a FactoryFinder object reference.

Listing 5-7 Client Application: Getting a FactoryFinder Object Reference


// Create the Bootstrap object,
// the TOBJADDR properly contains host and port to connect to.
Tobj_Bootstrap bootstrap = new Tobj_Bootstrap (orb,"");

// Use the Bootstrap object to find the factory finder.
org.omg.CORBA.Object fact_finder_oref =
bootstrap.resolve_initial_references("FactoryFinder");

// Narrow the factory finder.
FactoryFinder fact_finder_ref =
FactoryFinderHelper.narrow(fact_finder_oref);


Client Finding One Factory Using the Tobj Approach

Listing 5-8 shows how to program a client to find one factory using the Tobj approach.

Listing 5-8 Client Application: Finding One Factory Using the Tobj Approach


// Use the factory finder to find the teller factory.
org.omg.CORBA.Object teller_fact_oref =
fact_finder_ref.find_one_factory_by_id("TellerFactory_1");