idl2java
compiler. DSI allows an object to register itself with the ORB, receive operation requests from a client, process the requests, and return the results to the client without inheriting from a skeleton class. From the perspective of a client application, an object implemented with DSI behaves just like any other ORB object. Clients do not need to provide any special handling for object implementations that use DSI.
The ORB presents a client operation request to a DSI object implementation by using the object's invoke method and passing a ServerRequest object. The object implementation is responsible for determining the operation being requested, interpreting the arguments associated with the request, invoking the appropriate internal method or methods to fulfill the request, and returning the appropriate values.
Implementing objects with DSI requires more manual programming activity than using the normal language mapping provided by object skeletons. Nevertheless, an object implemented with DSI can be very useful in providing inter-protocol bridging or in allowing one object to offer multiple interfaces.
The Bank.idl file used in the DSI example.
// Bank.idl
module Bank
{
interface Account
{
float balance();
};
interface AccountManager
{
Account open(in string name);
};
}; Using DSI
To use DSI for your object implementation, follow these steps:
Instead of extending a skeleton object, design your object implementation so that it extends the org.omg.CORBA.DynamicImplementation
abstract class.
The DynamicImplementation base class.
abstract public class
The following code example shows the declaration of the Account and AccountManager objects that are to be implemented with DSI. Both are derived from the DynamicImplementation class, which adds the invoke method. The ORB uses the invoke method to pass client operation requests to the object in the form of ServerRequest objects.DynamicImplementation
extends
org.omg.CORBA.portable.Skeleton {
abstract void invoke
(ServerRequest request);
protected DynamicImplementation
(String object_name,
String repository_id) {
...
}
protected DynamicImplementation
(String object_name,
String[] repository_ids) {
...
}
...
}
A portion of Server.java from the DSI example.
class
Account extends org.omg.CORBA.DynamicImplementation
{
Account(String name) {
super(name, "IDL:Bank/Account:1.0");
}
void invoke
(org.omg.CORBA.ServerRequest request) {
}
...
}
class AccountManager extends org.omg.CORBA.DynamicImplementation
{
Account(String name) {
super(name, "IDL:Bank/AccountManager:1.0");
}
void invoke
(org.omg.CORBA.ServerRequest request) {
}
...
} Specifying Repository Ids
The first form of the DynamicImplementation class' constructor allows you to create a server object, specifying a string that represents the repository identifier of the object that is being implemented. Note that both the Account and AccountManager classes declare a constructor that specifies the appropriate repository identifier. To determine the correct repository identifier to specify, start with the IDL interface name of an object and use the following steps:
Replace all non-leading instances of the delimiter "::" with "/".
IDL:Bank/AccountManager:1.0
.
invoke
method. The ServerRequest object represents the operation request and provides methods for obtaining the name of the requested operation, the parameter list, and the context. It also provides methods for setting the result to be returned to the caller and for reflecting exceptions. This class is described in the Netscape Internet Service Broker for Java Reference Guide.
The ServerRequest class.
abstract public classServerRequest
{
abstract public java.lang.Stringop_name
();
abstract public org.omg.CORBA.Contextctx
();
abstract public voidparams
(
org.omg.CORBA.NVList params
);
abstract public voidresult
(
org.omg.CORBA.Any result
);
abstract public voidexcept
(
org.omg.CORBA.Any except
);
}
invoke
method is fairly straightforward.
The invoke
method first checks to see if the requested operation has the name "balance." If the name does not match, a BAD_OPERATION exception is raised. If the Account object were to offer more than one method, the invoke
method would need to check for all possible operation names and use the appropriate internal methods to process the operation request.
Since the balance
method does not accept any parameters, there is no parameter list associated with its operation request. The balance method is simply invoked and the result is packaged in an Any object that is returned to the caller, using the ServerRequest.result
method.
The Account.invoke method.
classAccount
extendsorg.omg.CORBA.DynamicImplementation
{
Account(float balance) {
super(null, "IDL:Bank/Account:1.0");
_balance = balance;
}
public voidinvoke
(org.omg.CORBA.ServerRequest request) {
// make sure the operation name is correct
if(!request.op_name().equals("balance")
) {
throw new org.omg.CORBA.BAD_OPERATION();
}
// no parameters, so simply invoke the balance operation
float balance = this.balance();
// create an Any for the result
org.omg.CORBA.Any balanceAny = _orb().create_any();
// put in the balance,
balanceAny.insert_float(balance);
// set the request's result
request.result(balanceAny);
}
float balance() {
return _balance;
}
private float _balance;
}
AccountManager.open
method does accept an account name parameter. This makes the processing done by the invoke
method a little more complicated. The following code example shows the implementation of the AccountManager.invoke
method.
The method first checks to see that the requested operation has the name "open." If the name does not match, a BAD_OPERATION exception is raised. If the AccountManager object were to offer more than one method, the invoke method would need to check for all possible operation names and use the appropriate internal methods to process the operation request.
The AccountManager.invoke method.
classAccountManager
extendsorg.omg.CORBA.DynamicImplementation
{
AccountManager(String name) {
super(name, "IDL:Bank/AccountManager:1.0");
}
public voidinvoke
(org.omg.CORBA.ServerRequest request) {
// make sure the operation name is correct
if(!request.op_name().equals("open")
) {
throw new org.omg.CORBA.BAD_OPERATION();
}
// create an empty parameter list
org.omg.CORBA.NVList params = _orb().create_list(0);
// create an Any for the account name parameter
org.omg.CORBA.Any nameAny = _orb().create_any();
// set the Any's type to be a string
nameAny.type(_orb().get_primitive_tc
// add "in" the parameter to the parameter list
(org.omg.CORBA.TCKind.tk_string));
params.add_value("name", nameAny, org.omg.CORBA.ARG_IN.value);
// obtain the parameter values from the request
request.params(params);
// get the name parameter from the Any
String name = nameAny.extract_string();
// invoke the open operation
Account account = this.open(name);
// create an Any for the result
org.omg.CORBA.Any accountAny = _orb().create_any();
// put the new Account object into an Any
accountAny.insert_Object(account);
// set the request's result
request.result(accountAny);
}
public Account open(String name) {
...
}
}
AccountManager.invoke
method uses to process the operation request's input parameters.
Create an NVList to hold the parameter list for the operation.open
method expects an account name parameter, an NVList object is created to hold the parameters contained in the ServerRequest. The NVList class implements a parameter list containing one or more NamedValue object. The NVList and NamedValue classes are described in The Dynamic Invocation Interface and in the Netscape Internet Service Broker for Java Reference Guide.
An Any object is created to hold the account name. This Any is then added to NVList with the argument's name set to "name" and the parameter type set to ARG_IN.
Once the NVList has been initialized, the ServerRequest.params method is invoked to obtain the values of all of the parameters in the list.
After invoking the params method, the NVList will be owned by the ORB. This means that if an object implementation modifies an ARG_INOUT parameter in the NVList, the change will automatically be apparent to the ORB.
An alternative to constructing the NVList for the input arguments is to use the org.omg.CORBA.ORB.create_operation_list
method. This method accepts an OperationDef and returns an NVList object, completely initialized with all the necessary Any objects. The appropriate OperationDef object can be obtained from the Interface Repository, described in Chapter 7.
Setting the Return Value
After invoking the ServerRequest.params
method, the account name value can be extracted and used to create a new Account object. An Any object is created to hold the newly created Account object, which is returned to the caller by invoking the ServerRequest.result
method.
The Server Implementation
The implementation of the Server class, shown below, is the same whether or not you are using DSI.
The Server class implementation.
// Using Enterprise Server's ORB
public class Server {
public static void main(String[] args) {
try {
// Initialize the ORB.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
// Initialize the BOA.
org.omg.CORBA.BOA boa = orb.BOA_init();
// Create the account manager object.
AccountManager manager = new AccountManager("ISB_Bank");
// Export the newly create object.
boa.obj_is_ready(manager);
String host =
java.netInetAddress.getLocalHost().getHostName();
netscape.WAI.Naming.register
("http://" + host + "/ISB_Bank", manager);
// Or, if using Communicator's ORB, the call would be:
// netscape.WAI.Naming.register
// ("http://" + host + "/NameService/ISB_Bank", manager);
System.out.println(manager + " is ready.");
// Wait for incoming requests
boa.impl_is_ready();
}
catch(org.omg.CORBA.SystemException e) {
System.err.println(e);
}
catch(java.net.UnknownHostException u) {
System.err.println(u);
}
}
}
Last Updated: 02/04/98 13:48:01