Externalizing a reference to an object for which object wrappers have been installed, using the VisiBroker ORB Object's
object_to_string method, will not propagate those wrappers to the recipient of the stringified reference if the recipient is a different process.
VisiBroker offers two kinds of object wrappers: typed and
untyped. You can mix the use of both of these object wrappers within a single application. For information on typed wrappers, see
“Typed object wrappers”. For information on untyped wrappers, see
“Untyped object wrappers”. The following table summarizes the important distinctions between these two kinds of object wrappers.
Whenever you plan to use typed or untyped object wrappers, you must ensure that you use the -obj_wrapper option with the
idl2java compiler when you generate the code for your applications. This will result in the generation of:
The following figure shows how an untyped object wrapper's pre_method is invoked before the client stub method and how the
post_method is invoked afterward. It also shows the calling sequence on the server-side with respect to the object implementation.
When a client invokes a method on a bound object, each untyped object wrapper pre_method will receive control before the client's stub routine is invoked. When a server receives an operation request, each untyped object wrapper
pre_method will be invoked before the object implementation receives control. In both cases, the first
pre_method to receive control will be the one belonging to the object wrapper that was
registered first.
When a server's object implementation completes its processing, each post_method will be invoked before the reply is sent to the client. When a client receives a reply to an operation request, each
post_method will be invoked before control is returned to the client. In both cases, the first
post_method to receive control will be the one belonging to the object wrapper that was
registered last.
The implementation of the TimingUnTypedObjectWrapperFactory, part of the
objectWrappers sample applications, shows how to define an untyped object wrapper factory, derived from the
UntypedObjectWrapperFactory.
Your factory's create method will be invoked to create an untyped object wrapper whenever a client binds to an object or a server invokes a method on an object implementation. The
create method receives the target object, which allows you to design your factory to not create an untyped object wrapper for those object types you wish to ignore. It also receives an enum specifying whether the object wrapper created is for the server side object implementation or the client side object.
The following code sample illustrates an example of the TimingObjectWrapperFactory, which is used to create an untyped object wrapper that displays timing information for method calls.
The following code sample shows the implementation of the TimingObjectWrapper. Your untyped wrapper must be derived from the
UntypedObjectWrapper class, and you may provide an implementation for both the
pre_method or
post_method methods in your untyped object wrapper.
Once your factory has been installed, either automatically by the factory's constructor or manually by invoking the ChainUntypedObjectWrapper::add method, an untyped object wrapper object will be created automatically whenever your client binds to an object or when your server invokes a method on an object implementation.
The pre_method shown in the following code sample obtains the current time, saves it in a private variable, and prints a message. The
post_method also obtains the current time, determines how much time that has elapsed since the
pre_method was called, and prints the elapsed time.
package UtilityObjectWrappers;
import com.inprise.vbroker.interceptor.*;
Public class TimingUntypedObjectWrapper implements
UntypedObjectWrapper {
private long time;
public void
pre_method(String
operation,
org.omg.CORBA.Object
target,
Closure
closure) {
System.out.println("Timing: " +
((com.inprise.vbroker.CORBA.Object) target)._object_name() + "->"
+ operation + "()");
time = System.currentTimeMillis();
}
public void
post_method(String
operation,
org.omg.CORBA.Object
target,
org.omg.CORBA.Environment
env,
Closure
closure) {
long diff = System.currentTimeMillis() - time;
System.out.println("Timing: Time for call \t" + ((com.inprise.vbroker.CORBA.Object)
target)._object_name() + "->" + operation + "() = " + diff + " ms.");
}
}
Both the pre_method and
post_method receive the parameters shown in the following table.
The following code shows a portion of the sample file UntypedClient.java, which shows the creation and installation of two untyped object wrapper factories for a client. The factories are created after the VisiBroker ORB has been initialized, but before the client binds to any objects.
The following code sample illustrates the sample file UntypedServer.Java, which shows the creation and registration of untyped object wrapper factories for a server. The factories are created after the VisiBroker ORB is initialized, but before any object implementations are created.
The ChainUntypedObjectWrapperFactory class
remove method can be used to remove an untyped object wrapper factory from a client or server application. You must specify a location when removing a factory. This means that if you have added a factory with a location of
Both , you can selectively remove it from the
Client location, the
Server location, or
Both.
On the client side, the first object wrapper registered is client_wrapper_1, so its methods will be the first to receive control. After performing its processing, the
client_wrapper_1 method may pass control to the next object's method in the chain or it may return control to the client.
On the server side, the first object wrapper registered is server_wrapper_1, so its methods will be the first to receive control. After performing its processing, the
server_wrapper_1 method may pass control to the next object's method in the chain or it may return control to the servant.
You derive typed object wrappers from the <interface_name>ObjectWrapper class that is generated by the
idl2java compiler.
Notice that this class is derived from the AccountObjectWrapper interface and provides a simple caching implementation of the
balance method, which provides these processing steps:
A typed object wrapper is registered on the client-side by invoking the addClientObjectWrapperClass method in Java that is generated for the class by the
idl2java compiler. Client-side object wrappers must be registered after the
ORB.init method has been called, but before any objects are bound. The following code sample shows a portion of the
TypedClient.java file that creates and registers a typed object wrapper.
// TypedClient.java
import com.inprise.vbroker.interceptor.*;
Public class TypedClient {
public static void main(String[] args) throws Exception {
// Initialize the ORB.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
domain (orb, args);
}
public static void domain(org.omg.CORBA.ORB orb, String[] args) {
// Add a typed object wrapper for Account objects
Bank.AccountHelper.addClientObjectWrapperClass(orb,
BankWrappers.CachingAccountObjectWrapper.class);
// Locate an account manager.
Bank.AccountManager manager =
Bank.AccountManagerHelper.bind(orb, "BankManager");
...
}
}
The VisiBroker ORB keeps track of any object wrappers that have been registered for it on the client side. When a client invokes the _bind method to bind to an object of that type, the necessary object wrappers will be created. If a client binds to more than one instance of a particular class of object, each instance will have its own set of wrappers.
As with a client application, a typed object wrapper is registered on the server side by invoking the addServerObjectWrapperClass method offered by the
Helper class. Server side, typed object wrappers must be registered after the
ORB.init method has been called, but before an object implementation services a request. The following code sample shows a portion of the
TypedServer.java file that installs a typed object wrapper.
The Helper class also provides methods for removing a typed object wrapper from a client or server application.
If you choose to use both typed and untyped object wrappers in your application, all pre_method methods defined for the untyped wrappers will be invoked prior to any typed object wrapper methods defined for an object. Upon return, all typed object wrapper methods defined for the object will be invoked prior to any
post_method methods defined for the untyped wrappers.
The sample applications Client.java and
Server.java make use of a sophisticated design that allows you to use command-line properties to specify which, if any, typed and untyped object wrappers are to be used.
The typed wrappers are defined in the BankWrappers package and include a service initializer,
BankWrappers/Init.java, as shown in the following code. This initializer will be invoked if you specify
-Dvbroker.orb.dynamicLibs=BankWrappers.Init on the command-line when starting the client or server with
vbj. Various typed object wrappers can be installed, based on the command-line properties you supply.
package BankWrappers;
import java.util.*;
import com.inprise.vbroker.orb.ORB;
import com.inprise.vbroker.properties.PropertyManager;
import com.inprise.vbroker.interceptor.*;
public class
Init implements
ServiceLoader {
com.inprise.vbroker.orb.ORB _orb;
public void init(final org.omg.CORBA.ORB orb) {
_orb = (ORB) orb;
PropertyManager pm = _orb.getPropertyManager();
// install my CachingAccountObjectWrapper
String val = pm.getString("CachingAccount", this.toString());
Class c = CachingAccountObjectWrapper.class;
if( !val.equals(this.toString())) {
if( val.equalsIgnoreCase("client") ) {
Bank.AccountHelper.addClientObjectWrapperClass(orb, c);
} else if( val.equalsIgnoreCase("server") ) {
Bank.AccountHelper.addServerObjectWrapperClass(orb, c);
} else {
Bank.AccountHelper.addClientObjectWrapperClass(orb, c);
Bank.AccountHelper.addServerObjectWrapperClass(orb, c);
}
}
// install my CachingAccountManagerObjectWrapper
val = pm.getString("CachingAccountManager", this.toString());
c = CachingAccountManagerObjectWrapper.class;
if( !val.equals(this.toString())) {
if( val.equalsIgnoreCase("client") ){
Bank.AccountManagerHelper.addClientObjectWrapperClass(orb, c);
} else if( val.equalsIgnoreCase("server") ) {
Bank.AccountManagerHelper.addServerObjectWrapperClass(orb, c);
} else {
Bank.AccountManagerHelper.addClientObjectWrapperClass(orb, c);
Bank.AccountManagerHelper.addServerObjectWrapperClass(orb, c);
}
}
// install my CachingAccountManagerObjectWrapper
val = pm.getString("SecureAccountManager",
this.toString());
c = SecureAccountManagerObjectWrapper.class;
if( !val.equals(this.toString())) {
if( val.equalsIgnoreCase("client") ){
Bank.AccountManagerHelper.addClientObjectWrapperClass(orb, c);
} else if( val.equalsIgnoreCase("server") ) {
Bank.AccountManagerHelper.addServerObjectWrapperClass(orb, c);
} else {
Bank.AccountManagerHelper.addClientObjectWrapperClass(orb, c);
Bank.AccountManagerHelper.addServerObjectWrapperClass(orb, c);
}
}
}
public void init_complete(org.omg.CORBA.ORB orb) {}
public void shutdown(org.omg.CORBA.ORB orb) {}
}
The untyped wrappers are defined in the UtilityObjectWrappers package and include a service initializer,
UtilityObjectWrappers/Init.java, shown below. This initializer will be invoked if you specify
-Dvbroker.orb.dynamicLibs=UtilityObjectWrappers.Init on the command-line when starting the client or server with
vbj. The Command-line properties for enabling or disabling UtilityObjectWrappers table summarizes the command-line arguments that you can use to install the various untyped object wrappers.
package UtilityObjectWrappers;
import java.util.*;
Import com.inprise.vbroker.orb.ORB;
import com.inprise.vbroker.properties.PropertyManager;
import com.inprise.vbroker.interceptor.*;
Public class Init implements
ServiceLoader {
com.inprise.vbroker.orb.ORB _orb;
public void init(final org.omg.CORBA.ORB orb) {
_orb = (ORB) orb;
PropertyManager PM= _orb.getPropertyManager();
try {
ChainUntypedObjectWrapperFactory factory =
ChainUntypedObjectWrapperFactoryHelper.narrow(
orb.resolve_initial_references("ChainUntypedObjectWrapperFactory"));
// install my Timing ObjectWrapper
String val = pm.getString("Timing", this.toString());
if( !val.equals(this.toString())) {
UntypedObjectWrapperFactory f= new
TimingUntypedObjectWrapperFactory();
if( val.equalsIgnoreCase("client") ){
factory.add(f, Location.CLIENT);
} else if( val.equalsIgnoreCase("server") ) {
factory.add(f, Location.SERVER);
} else {
factory.add(f, Location.BOTH);
}
}
// install my Tracing ObjectWrapper
val = pm.getString("Tracing", this.toString());
if( !val.equals(this.toString())) {
UntypedObjectWrapperFactory f= new TracingUntypedObjectWrapperFactory();
if( val.equalsIgnoreCase("client") ){
factory.add(f, Location.CLIENT);
} else if( val.equalsIgnoreCase("server") ) {
factory.add(f, Location.SERVER);
} else {
factory.add(f, Location.BOTH);
}
}
} catch( org.omg.CORBA.ORBPackage.InvalidName e ) {
return;
}
}
public void init_complete(org.omg.CORBA.ORB orb) {}
public void shutdown(org.omg.CORBA.ORB orb) {}
}
Specifying the -runCoLocated command-line option allows you to execute the client and server within the same process.