VisiBroker for Java Developer’s Guide : Using RMI over IIOP

Using RMI over IIOP
This section describes the VisiBroker for Java tools which enable you to use RMI over IIOP, and also describes the setup permissions required when running Java applets that use RMI-IIOP.
Overview of RMI over IIOP
RMI (remote method invocation) is a Java mechanism which allows objects to be created and used in a distributed environment. In this sense, RMI is a VisiBroker ORB, which is language-specific (Java) and non-CORBA compliant. The OMG has issued a specification, the Java language to IDL Mapping, which allows Java classes written using RMI to interoperate with CORBA objects using the IIOP encoding.
Setting up Java applets with RMI-IIOP
You can run an applet that uses RMI-IIOP. However, you need to set the permissions in Reflect and Runtime. These permissions are set in the java.policy file located in the JRE installed directory. The following is an example of how to set the permissions in the java.policy file:
grant codeBase "http://xxx.xxx.xxx.xxx:8088/-" {
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
permission java.lang.RuntimePermission "accessDeclaredMembers";
};
java2iiop and java2idl tools
VisiBroker has two compilers which allow you to adapt your existing Java classes to work with other objects using the VisiBroker ORB.
The java2iiop compiler lets you adapt your RMI-compliant classes to use IIOP by generating all the proper skeleton, stub, and helper classes.
The java2idl compiler generates IDL from your Java classes, allowing you to implement them in languages other than Java.
Using java2iiop
The java2iiop compiler lets you define interfaces and data types in Java, rather than IDL, that can then be used as interfaces and data types in CORBA. The compiler does not read Java source code (java files) or IDL, but rather Java bytecode (class files). The compiler then generates IIOP-compliant stubs and skeletons needed to do all the marshalling and communication required for CORBA.
Supported interfaces
When you run the java2iiop compiler, it generates the same files as if you had written the interface in IDL. All primitive data types like the numeric types (short, int, long, float, and double), string, CORBA objects or interface objects, Any objects, typecode objects are understood by the java2iiop compiler and mapped to the corresponding IDL types.
You can use java2iiop on any Java class or interface. For example, if a Java interface adheres to one of the following rules:
Extends java.rmi.Remote and all of its methods throw java.rmi.RemoteException
Extends org.omg.CORBA.Object
then, java2iiop will translate the interface to a CORBA interface in IDL.
The following code sample illustrates a Java RMI interface. This code example can be found in:
<install_dir>/examples/vbroker/rmi-iiop/
public interface Account extends java.rmi.Remote {
String name() throws java.rmi.RemoteException;
float getBalance() throws java.rmi.RemoteException;
void setBalance(float bal) throws java.rmi.RemoteException;
}
Running java2iiop
You must compile your Java classes before you can use the java2iiop compiler. Once you have generated bytecode, you can run java2iiop to generate client stubs, server skeletons, and the associated auxiliary files.
For example, after running java2iiop on the Account.class file found in
<install_dir>/examples/vbroker/rmi-iiop/Bank/
you would have the following files:
Reverse mapping of Java classes to IDL
When mapping IDL interfaces to Java classes, using the idl2java compiler, the interface name may use any of the generated classes suffixes (for example, Helper, Holder, POA, and so on), and the idl2java tool will handle the situation correctly by mangling the interface name (prefixing an underscore “_” to the identifier).
For example, if you define both a Foo and a FooHolder interface in IDL, idl2java will generate, amongst others, Foo.java, FooHolder.java, _FooHolder.java, and _FooHolderHolder.java files.
On the other hand, when generating IIOP-compliant Java classes from RMI Java classes, using the java2iiop compiler, the tool cannot generate the mangled classes.
So, when declaring interfaces which use reserved suffixes, you cannot have them in the same package as the interface with the same name, (for example, you can not have a Foo and a FooHolder class in the same package when using the java2iiop compiler).
Completing the development process
After generating the associated files from your interfaces, you need to provide implementations for the interfaces. Follow these steps:
1
2
3
4
5
Note
If you attempt to marshal a non-conforming class, an org.omg.CORBA.MARSHAL: Cannot marshal non-conforming value of class <class name> will be thrown. For instance, if you create the following two classes,
// This is a conforming class
public class Value implements java.io.Serializable {
java.lang.Object any;
...
}
// This is a non-conforming class
public class Something {
...
}
and then attempt the following,
Value val = new Value();
val.any = new Something();
You will raise an org.omg.CORBA.MARSHAL exception when you attempt to marshal val.
RMI-IIOP Bank example
This code example is located in the following directory:
<install_dir>/examples/vbroker/rmi-iiop/
The Account interface extends the java.rmi.Remote interface and is implemented by the AccountImpl class.
The Client class (below) first creates all the specified Account objects with the appropriate balances by creating AccountData objects for each account and passing them to the AccountManager to create the accounts. It then confirms that the balance is correct on the created account. The client then queries the AccountManager for a list of all the accounts, and proceeds to credit $10.00 to each account. It then verifies if the new balance on the account is accurate.
public class AccountImpl extends Bank.AccountPOA {
public AccountImpl(Bank.AccountData data) {
_name = data.getName();
_balance = data.getBalance();
}
public String name() throws java.rmi.RemoteException {
return _name;
}
public float getBalance() throws java.rmi.RemoteException {
return _balance;
}
public void setBalance(float balance) throws java.rmi.RemoteException {
_balance = balance;
}
private float _balance;
private String _name;
}
The Client class:
public class Client {
public static void main(String[] args) {
try {
// Initialize the ORB.
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
// Get the manager Id
byte[] managerId = "RMIBankManager".getBytes();
// Locate an account manager. Give the full POA name and the
servant ID.
Bank.AccountManager manager = Bank.AccountManagerHelper.bind(orb, "/rmi_bank_poa", managerId);
// Use any number of argument pairs to indicate name,balance of
accounts to create
if (args.length == 0 || args.length % 2 != 0) {
args = new String[2];
args[0] = "Jack B. Quick";
args[1] = "123.23";
}
int i = 0;
while (i < args.length) {
String name = args[i++];
float balance;
try {
balance = new Float(args[i++]).floatValue();
} catch (NumberFormatException n) {
balance = 0;
}
Bank.AccountData data = new Bank.AccountData(name, balance);
Bank.Account account = manager.create(data);
System.out.println("Created account for " + name
+ " with opening balance of $" + balance);
}
java.util.Hashtable accounts = manager.getAccounts();
for (java.util.Enumeration e = accounts.elements();
e.hasMoreElements();) {
Bank.Account account =
              Bank.AccountHelper.narrow((org.omg.CORBA.Object)e.nextElement());
String name = account.name();
float balance = account.getBalance();
System.out.println("Current balance in " + name + "'s account is
$" + balance);
System.out.println("Crediting $10 to " + name + "'s account.");
account.setBalance(balance + (float)10.0);
balance = account.getBalance();
System.out.println("New balance in " + name + "'s account is
$" + balance);
}
} catch (java.rmi.RemoteException e) {
System.err.println(e);
}
}
}
Supported data types
In addition to all of the Java primitive data types, RMI-IIOP supports a subset of Java classes.
Mapping primitive data types
Client stubs generated by java2iiop handle the marshalling of the Java primitive data types that represent an operation request so that they may be transmitted to the object server. When a Java primitive data type is marshalled, it must be converted into an IIOP-compatible format. The following table summarizes the mapping of Java primitive data types to IDL/IIOP types.
Mapping complex data types
This section shows how the java2iiop compiler can be used to handle complex data types.
Interfaces
Java interfaces are represented in IDL as CORBA interfaces, and they must inherit from the org.omg.CORBA.Object interface. When passing objects that implement these interfaces, they are passed by reference.
Arrays
Another complex data type that may be defined in classes is an array. If you have an interface or definitions that use arrays, the arrays map to CORBA boxed sequence of boxed type.