•
|
Bridges or adapters between script environments and CORBA objects. For example, a script calls your bridge, passing object and method identifiers and parameter values. Your bridge constructs and issues a dynamic request, receives the result, and returns it to the scripting environment. Such a bridge could not use static invocation because its developer could not know in advance what kinds of objects the script environment would want to invoke.
|
•
|
Generic object testers. For example, a client takes an arbitrary object identifier, looks up its interface in the interface repository (see “Using Interface Repositories”), and then invokes each of its methods with artificial argument values. Again, this style of generic tester could not be built with static invocation.
|
Clients must pass valid arguments in DII requests. Failure to do so can produce unpredictable results, including server crashes. Although it is possible to dynamically type-check parameter values with the interface repository, it is expensive. For best performance, ensure that the code (for example, script) that invokes a DII-using client can be trusted to pass valid arguments.
A Request object represents one invocation of one method on one CORBA object. If you want to invoke two methods on the same CORBA object, or the same method on two different objects, you need two
Request objects. To invoke a method you first need the
target reference, an object reference representing the CORBA object. Using the target reference, you create a
Request, populate it with arguments, send the
Request, wait for the reply, and obtain the result from the
Request.
There are two ways to create a Request. The simpler way is to invoke the target object's
_request method, which all CORBA objects inherit. This does not, in fact, invoke the target object. You pass
_request the IDL name of the method you intend to invoke in the
Request, for example, “
get_balance.” To add argument values to a
Request created with
_request, you invoke the
Request's
add_value method for each argument required by the method you intend to invoke. To pass one or more
Context objects to the target, you must add them to the
Request with its
ctx method.
Although not intuitively obvious, you must also specify the type of the Request's result with its
result method. For performance reasons, the messages exchanged between the VisiBroker ORBs do not contain type information. By specifying a place holder result type in the
Request, you give the VisiBroker ORB the information it needs to properly extract the result from the reply message sent by the target object. Similarly, if the method you are invoking can raise user exceptions, you must add place holder exceptions to the
Request before sending it.
The more complicated way to create a Request object is to invoke the target object's
_create_request method, which, again, all CORBA objects inherit. This method takes several arguments which populate the new
Request with arguments and specify the types of the result and user exceptions, if any, that it may return. To use the
_create_request method you must have already built the components that it takes as arguments. The potential advantage of the
_create_request method is performance. You can reuse the argument components in multiple
_create_request calls if you invoke the same method on multiple target objects.
There are two overloaded forms of the _create_request method: one that includes
ContextList and
ExceptionList parameters, and one that does not. If you want to pass one or more
Context objects in your invocation, and/or the method you intend to invoke can raise one or more user exceptions, you must use the
_create_request method that has the extra parameters.
The target method's arguments, result, and exceptions are each specified in special objects called Anys. An
Any is a generic object that encapsulates an argument of any type. An
Any can hold any type that can be described in IDL. Specifying an argument to a
Request as an
Any allows a
Request to hold arbitrary argument types and values without making the compiler complain of type mismatches. (The same is true of results and exceptions.)
An Any consists of a
TypeCode and a value. A value is just a value, and a
TypeCode is an object that describes how to interpret the bits in the value (that is, the value's type). Simple
TypeCode constants for simple IDL types, such as
long and
Object, are built into the header files produced by the
idl2java compiler.
TypeCodes for IDL constructed types, such as
structs,
unions, and
typedefs, have to be constructed. Such
TypeCodes can be recursive because the types they describe can be recursive.
Consider a struct consisting of a
long and a
string. The
TypeCode for the
struct contains a
TypeCode for the
long and a
TypeCode for the
string. You can get a
TypeCode at runtime from an interface repository (see
“Using Interface Repositories”) or by asking the VisiBroker ORB to create one by invoking
ORB::create_struct_tc or
ORB::create_exception_tc.
If you use the _create_request method, you need to put the
Any-encapsulated target method arguments in another special object called an
NVList. No matter how you create a
Request, its result is encoded as an
NVList. Everything said about arguments in this paragraph applies to results as well. “NV” stands for named value, and an
NVList consists of a count and number of items, each of which has a name, a value, and a flag. The name is the argument name, the value is the
Any encapsulating the argument, and the flag denotes the argument's IDL mode (for example,
in or
out). The result of
Request is represented a single named value.
Once you create and populate a Request with arguments, a result type, and exception types, you send it to the target object. There are several ways to send a
Request,
•
|
More complex, but not blocking, is the Request's send_deferred method. This is an alternative to using threads for parallelism. For many operating systems the send_deferred method is more economical than spawning a thread.
|
•
|
If your motivation for using the send_deferred method is to invoke multiple target objects in parallel, you can use the VisiBroker ORB object's send_multiple_requests_deferred method instead. It takes a sequence of Request objects.
|
•
|
Use the Request's send_oneway method if, and only if, the target method has been defined in IDL as oneway.
|
If you send a Request by calling its
invoke method, there is only one way to get the result: use the
Request object's
env method to test for an exception, and if none, extract the
NamedValue from the
Request with its
result method. If you used the
send_oneway method, then there is no result. If you used the
send_deferred method, you can periodically check for completion by calling the
Request's
poll_response method which returns a code indicating whether the reply has been received. If, after polling for a while, you want to block waiting for completion of a deferred send, use the
Request's
get_response method.
If you have sent Requests with the
send_multiple_requests_deferred method, you can find out if a particular
Request is complete by invoking that
Request's
get_response method. To learn when any outstanding
Request is complete, use the VisiBroker ORB's
get_next_response method. To do the same thing without risking blocking, use the VisiBroker ORB's
poll_next_response method.
2
|
Create a Request object for the target object.
|
The idl2java compiler has a flag (
-dynamic_marshal) which, when switched on, generates stub code using DII. To understand how to do any type of DII:
The code sample below shows how your client program can use the bind method offered by the VisiBroker ORB object to bind to any object by specifying its name. This method returns a generic
org.omg.CORBA.Object.
...
org.omg.CORBA.ORB orb;
org.omg.CORBA.Object account;
try {
// initialize the ORB.
orb = org.omg.CORBA.ORB.init(args, null);
} catch(Exception e) {
System.err.println ("Failure during ORB_init");
e.printStackTrace();
}
...
try {
// Request ORB to bind to the object supporting the account interface.
account = ((com.inprise.vbroker.CORBA.ORB)orb).bind("IDL:Account:1.0", "", "", null);
} catch(Exception excep) {
System.err.println ("Error binding to account" );
excep.printStackTrace();
}
System.out.println ("Bound to account object");
...
When your client program invokes a method on an object, a Request object is created to represent the method invocation. The
Request object is written, or
marshalled, to a buffer and sent to the object implementation. When your client program uses client stubs, this processing occurs transparently. Client programs that wish to use the DII must create and send the
Request object themselves.
There is no constructor for this class. The Object's
_request method or
Object's
_create_request method are used to create a
Request object.
package org.omg.CORBA;
public abstract class Request {
public abstract org.omg.CORBA.Object
target();
public abstract java.lang.String
operation();
public abstract org.omg.CORBA.NVList
arguments();
public abstract org.omg.CORBA.NamedValue
result();
public abstract org.omg.CORBA.Environment
env();
public abstract org.omg.CORBA.ExceptionList
exceptions();
public abstract org.omg.CORBA.ContextList
contexts();
public abstract void
ctx(org.omg.CORBA.Context ctx);
public abstract org.omg.CORBA.Context
ctx();
public abstract org.omg.CORBA.Any
add_in_arg();
public abstract org.omg.CORBA.Any
add_named_in_arg(
public abstract org.omg.CORBA.Any
add_inout_arg();
public abstract org.omg.CORBA.Any
add_named_inout_arg(
public abstract org.omg.CORBA.Any
add_out_arg();
public abstract org.omg.CORBA.Any
add_named_out_arg(
public abstract void
set_return_type(
public abstract org.omg.CORBA.Any
return_value();
public abstract void
invoke();
public abstract void
send_oneway();
public abstract void
send_deferred();
public abstract void
get_response();
public abstract boolean
poll_response();
}
package org.omg.CORBA;
public interface
Object {
...
public org.omg.CORBA.Request
_request(java.lang.String operation);
public org.omg.CORBA.Request
_create_request(
org.omg.CORBA.Context ctx,
java.lang.String operation,
org.omg.CORBA.NVList arg_list,
org.omg.CORBA.NamedValue result
);
public org.omg.CORBA.Request
_create_request(
org.omg.CORBA.Context ctx,
java.lang.String operation,
org.omg.CORBA.NVList arg_list,
org.omg.CORBA.NamedValue result,
org.omg.CORBA.ExceptionList exceptions,
org.omg.CORBA.ContextList contexts
);
...
}
You can use the _create_request method to create a
Request object, initialize the
Context, the operation name, the argument list to be passed, and the result. Optionally, you can set the
ContextList for the request, which corresponds to the attributes defined in the request's IDL. The request parameter points to the
Request object that was created for this operation.
The code sample in “Example of creating a Request object” shows the use of the
_request method to create a
Request object, specifying only the operation name. After creating a float request, calls to its
add_in_arg method add an input parameter Account name. Its result type is initialized as an Object reference type via a call to
set_return_type method. After a call has been made, the return value is extracted with the result's call to the
result method. The same steps are repeated to invoke another method on an Account Manager instance with the only difference being in-parameters and return types.
The req, an
Any object is initialized with the desired account
name and added to the request's argument list as an input argument. The last step in initializing the request is to set the
result value to receive a
float.
A Request object maintains ownership of all memory associated with the operation, the arguments, and the result so you should never attempt to free these items. The following code sample is an example of creating a request object.
The arguments for a Request are represented with a NVList object, which stores name-value pairs as
NamedValue objects. You can use the
arguments method to obtain a pointer to this list. This pointer can then be used to set the names and values of each of the arguments.
Always initialize the arguments before sending a Request. Failure to do so will result in marshalling errors and may even cause the server to abort.
This class implements a list of NamedValue objects that represent the arguments for a method invocation. Methods are provided for adding, removing, and querying the objects in the list. The following code sample is an example of the NVList class:
package org.omg.CORBA;
public abstract class
NVList {
public int
count();
public void
add(int flags);
public void
add_item(java.lang.String name, int flags);
public void
add_value(
java.lang.String name,
org.omg.CORBA.Any value,
int flags
);
public org.omg.CORBA.NamedValue
item(int index);
public void
remove(int index);
}
This class implements a name-value pair that represents both input and output arguments for a method invocation request. The NamedValue class is also used to represent the result of a request that is returned to the client program. The
name property is simply a character string and the
value property is represented by an
Any class. The following code sample is an example of the NamedValue class.
There is no constructor for this class. The ORB.create_named_value method is used to obtain a reference to a
NamedValue object.
package org.omg.CORBA;
public abstract class
NamedValue {
public java.lang.String
name();
public org.omg.CORBA.Any
value();
public int
flags();
}
Objects of this class have a reference to a TypeCode that defines the contained object's type and a reference to the contained object. Methods are provided to construct, copy, and release an object as well as initialize and query the object's value and type. In addition, streaming operators methods are provided to read and write the object from and to a stream. The following code sample is an example.
package org.omg.CORBA;
public abstract class
Any {
public abstract TypeCode
type();
public abstract void
type(TypeCode type);
public abstract void
read_value(InputStream input, TypeCode type);
public abstract void
write_value(OutputStream output);
public abstract boolean
equal(Any rhs);
...
}
This class is used by the Interface Repository and the IDL compiler to represent the type of arguments or attributes. TypeCode objects are also used in a
Request object to specify an argument's type, in conjunction with the
Any class.
TypeCode objects have a
kind and parameter list property, represented by one of the values defined by the
TCKind class.
There is no constructor for this class. Use the ORB.get_primitive_tc method or one of the
ORB.create_*_tc methods to create a
TypeCode object.
|
|
|
repository_id, interface_name
|
|
repository_id, alias_name, TypeCode
|
|
|
|
|
|
|
|
|
|
|
|
repository_id, enum-name, enum-id1, enum-id2, ... enum-idn
|
|
repository_id, exception_name, StructMembers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
repository_id, interface_id
|
|
|
|
|
|
|
|
|
|
|
|
repository_id, struct-name, {member1, TypeCode1}, {membern, TypeCoden}
|
|
|
|
|
|
|
|
repository_id, union-name, switch TypeCode, {label-value1, member-name1, TypeCode1}, {labell-valuen, member-namen, TypeCoden}
|
|
|
|
repository_id, value_name, boxType
|
|
repository_id, value_name, typeModifier, concreteBase, members
|
|
|
|
|
|
|
public abstract class TypeCode extends java.lang.Object
implements org.omg.CORBA.portable.IDLEntity {
public abstract boolean equal(org.omg.CORBA.TypeCode tc);
public boolean
equivalent(org.omg.CORBA.TypeCode tc);
public abstract org.omg.CORBA.TCKind
kind();
public TypeCode
get_compact_typecode()
public abstract java.lang.String
id()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public abstract java.lang.String
name()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public abstract int
member_count()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public abstract java.lang.String
member_name(int index)
throws org.omg.CORBA.TypeCodePackage.BadKind,
org.omg.CORBA.TypeCodePackage.Bounds;
public abstract org.omg.CORBA.TypeCode
member_type(int index)
throws org.omg.CORBA.TypeCodePackage.BadKind,
org.omg.CORBA.TypeCodePackage.Bounds;
public abstract org.omg.CORBA.Any
member_label(int index)
throws org.omg.CORBA.TypeCodePackage.BadKind,
org.omg.CORBA.TypeCodePackage.Bounds;
public abstract org.omg.CORBA.TypeCode
discriminator_type()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public abstract int
default_index()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public abstract int
length()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public abstract org.omg.CORBA.TypeCode
content_type()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public short
fixed_digits()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public short
fixed_scale()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public short
member_visibility(int index)
throws org.omg.CORBA.TypeCodePackage.BadKind,
org.omg.CORBA.Bounds;
public short
type_modifier()
throws org.omg.CORBA.TypeCodePackage.BadKind;
public TypeCode
concrete_base_type()
throws org.omg.CORBA.TypeCodePackage.BadKind;
}
The Request class, as discussed in
“Creating and initializing a request”, provides several methods for sending a request once it has been properly initialized.
The simplest way to send a request is to call its invoke method, which sends the request and waits for a response before returning to your client program. The
return_value method returns a reference to an
Any object that represents the return value. The following code sample shows how to send a request with invoke.
A non-blocking method, send_deferred, is also provided for sending operation requests. It allows your client to send the request and then use the
poll_response method to determine when the response is available. The
get_response method blocks until a response is received. The following codes show how these methods are used. The following sample shows you how to use the
send_deferred and
poll_response methods to send a deferred DII request.
The send_oneway method can be used to send an asynchronous request. Oneway requests do not involve a response being returned to the client from the object implementation.
A sequence of DII Request objects can be created using array of Request objects. A sequence of requests can be sent using the VisiBroker ORB methods send_multiple_requests_oneway or
send_multiple_requests_deferred. If the sequence of requests is sent as oneway requests, no response is expected from the server to any of the requests.
When a sequence of requests is sent using send_multiple_requests_deferred, the
poll_next_response and
get_next_response methods are used to receive the response the server sends for each request.
The VisiBroker ORB method poll_next_response can be used to determine if a response has been received from the server. This method returns
true if there is at least one response available. This method returns
false if there are no responses available.
The VisiBroker ORB method get_next_response can be used to receive a response. If no response is available, this method will block until a response is received. If you do not wish your client program to block, use the
poll_next_response method to first determine when a response is available and then use the
get_next_response method to receive the result. The following code sample shows an example of receiving multiple requests.
package org.omg.CORBA;
public abstract class
ORB {
public abstract org.omg.CORBA.Environment
create_environment();
public abstract void
send_multiple_requests_oneway(org.omg.CORBA.Request[] reqs);
public abstract void
send_multiple_requests_deferred(org.omg.CORBA.Request[] reqs);
public abstract boolean
poll_next_response();
public abstract org.omg.CORBA.Request
get_next_response();
...
}
One source of the information needed to populate a DII Request object is an interface repository (IR) (see
“Using Interface Repositories”). The following example uses an interface repository to get obtain the parameters of an operation. Note that the example, atypical of real DII applications, has built-in knowledge of a remote object's type (
Account) and the name of one of its methods (
balance). An actual DII application would get that information from an outside source, for example, a user.
•
|
Looks up the Account's balance method in the IR and builds an operation list from the IR OperationDef.
|