This examples shows how to write value objects using IDL. We will be writing a doubly linked list value type and we will pass it to the server, which will perform specified operations on it and return the value back.
Here is a doubly linked list. Notice that value types are half way between IDL structs and IDL interfaces. They can have state like structs but can also have methods like interfaces. Unlike interfaces, which are passed by reference only, value objects are passed by value.
module idlValue { valuetype LinkedList { | | // state | private long data; | private LinkedList prev; | private LinkedList next; | | // methods | long getData(); | void setData(in long data); | void delete(); | void insert(in LinkedList element); | void append(in LinkedList element); | LinkedList getNext(); | LinkedList getPrevious(); | boolean isWellFormed(); | void print(); }; exception MalFormed {}; interface Calculator { | LinkedList add(in LinkedList list, in long i) raises(MalFormed); | | LinkedList multiply(in LinkedList list, in long m) raises(MalFormed); }; };
The server will implement an object with interface Calculator
that will manipulate the list and return it back.
The implementation of the linked list is very typical. Notice the methods
isWellFormed
and print
that are used to check if the list
is well formed and to print out its elements respectively.
package idlValue; public class LinkedListImpl extends LinkedList { LinkedListImpl() {} // constructor for the default factory public LinkedListImpl(int data) { setData(data); } public synchronized int getData() { return data; } public synchronized void setData(int data) { this.data = data; } public synchronized LinkedList getNext() { return next; } public synchronized LinkedList getPrevious() { return prev; } public synchronized void delete() { | if (prev != null) prev.next = next; | if (next != null) next.prev = prev; } public synchronized void insert(LinkedList element) { | if (prev != null) prev.next = element; | element.prev = prev; | prev = element; | element.next = this; } public synchronized void append(LinkedList element) { | LinkedList lastNode = this; | while (lastNode.next != null) | lastNode = lastNode.next; | | lastNode.next = element; | element.prev = lastNode; } public synchronized void print() { | LinkedList node = this; | System.out.print("["); | while (node != null) { | | System.out.print(node.data + ((node.next != null) ? ", " : "")); | | node = node.next; | } | System.out.println("]\n"); } public boolean isWellFormed() { | // check nodes after this element | LinkedList thisNode = this, nextNode = next; | while (nextNode != null) { | | if (nextNode.prev != thisNode) return false; | | thisNode = nextNode; | | nextNode = nextNode.next; | } | | // check nodes before this element | LinkedList prevNode = this.prev; thisNode = this; | while (prevNode != null) { | | if (prevNode.next != thisNode) return false; | | thisNode = prevNode; | | prevNode = prevNode.prev; | } | | return true; } }
For IDL value objects, we need to provide, a ValueFactory
to help
the ORB read the value. The value factory is typically named using the
generated Java name for the value type and appending "DefaultFactory" to it.
You can also use a non-default name and register the value factory with the
ORB using the register_value_factory
method on the ORB object.
The idl2java compiler creates a sample implementation of the ValueFactory for you.
// Tue Mar 28 18:29:23 PST 2000 package idlValue; import java.io.Serializable; import org.omg.CORBA.portable.ValueFactory; import org.omg.CORBA_2_3.portable.InputStream; public class LinkedListDefaultFactory implements ValueFactory { public Serializable read_value(InputStream is) { | return is.read_value(new LinkedListImpl()); } }
The server creates the Calucualor object.
Note that a linked list is a graph of pbjects and we expect the structure of
the graph to remain intact when it is passed around. The server calls the
value type's method isWellFormed
to verify that the linked list
is well formed. if you look at LinkedListImpl
above, you will see that
it verifies that all the pointers are correct. That is, for each node, its next
node's (if it exists) previous pointer and its previous node's (if it exists)
next pointer point to the node.
package idlValue; import util.Util; import org.omg.CORBA.ORB; import org.omg.CORBA.Object; import javax.rmi.PortableRemoteObject; public class Server { public static void main(String[] args) { | try { | | | | // create the jBroker ORB | | ORB orb = ORB.init(args, null); | | | | // create the servants and register with ORB | | Calculator calculator = new CalculatorImpl(); | | | | // create a stringified object references | | String calcIOR = orb.object_to_string(calculator); | | | | // write the stringified object references | | Util.writeIOR(calcIOR, "ior", true); | | | | // wait for invocations | | System.out.println("waiting for invocations ..."); | | orb.run(); | | | } catch (Exception ex) { | | ex.printStackTrace(); | } } static class CalculatorImpl extends _CalculatorImplBase { | public LinkedList add(LinkedList list, int i) throws MalFormed | { | | if (list != null) { | | | if (!list.isWellFormed()) throw new MalFormed(); | | | LinkedList node = list; | | | while (node != null) { | | | | node.setData(node.getData()+i); | | | | node = node.getNext(); | | | } | | } | | | | return list; | } | | public LinkedList multiply(LinkedList list, int m) throws MalFormed | { | | if (list != null) { | | | if (!list.isWellFormed()) throw new MalFormed(); | | | LinkedList node = list; | | | while (node != null) { | | | | node.setData(node.getData()*m); | | | | node = node.getNext(); | | | } | | } | | | | return list; | } } }
The client constructs the linked list with five elements and send it over to the Calculator remote object to add five to all list elements. It then passes this list again and asks it to multiply all elements by two.
package idlValue; import java.util.Vector; import util.Util; import org.omg.CORBA.ORB; public class Client { public static void main(String[] args) { | try { | | | | // create the jBroker ORB | | ORB orb = ORB.init(args, null); | | | | // read the stringified object references | | Calculator calc = CalculatorHelper.narrow(orb.string_to_object( | | Util.readIOR("ior"))); | | | | // construct a linked list | | LinkedList list = new LinkedListImpl(1); | | list.append(new LinkedListImpl(2)); | | list.append(new LinkedListImpl(3)); | | list.append(new LinkedListImpl(4)); | | list.append(new LinkedListImpl(5)); | | list.print(); | | | | // add 5 to the list | | list = calc.add(list, 5); list.print(); | | | | // multiply the list by 2 | | list = calc.multiply(list, 2); list.print(); | | | } catch (Exception ex) { | | ex.printStackTrace(); | } } }
The expected output from this program is.
[1, 2, 3, 4, 5] [6, 7, 8, 9, 10] [12, 14, 16, 18, 20]
Copyright © 2003, 2004 Novell, Inc. All rights reserved. Copyright © 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved.