ObjectSpace VoyagerRemote Creation and AccessRemote Iteration Remote Algorithms Persistence |
ObjectSpace Voyager is the ObjectSpace product line designed to help developers produce high-impact distributed systems quickly. Voyager is 100% Java and is designed to use the Java language object model. Voyager allows you to use regular message syntax to construct remote objects, send them messages, and move them between programs. This means that you can still use the JGL containers (and any other Java libraries) you have relied on for reducing your time-to-market for distributed systems.
The root of the Voyager product line is the ObjectSpace Voyager Core Technology. This product contains the core features and architecture of the platform, including a full-featured, intuitive Object Request Broker (ORB) with support for mobile objects and autonomous agents. Also in the core package are services for persistence, scalable group communication, and basic directory services. Voyagers architecture is designed to provide developers with full flexibility and powerful expansion paths.
The ObjectSpace Voyager
Core Technology is everything you need to get
started with building high-impact systems in Java
today. For downloading instructions, white papers, user
success stories and more, please visit the
Voyager website at
http://www.objectspace.com/voyager.
You may construct a remote instance of a JGL container
in any program and send it messages. Messages sent to a virtual reference are
automatically forwarded to the remote object. Return values and exceptions
are automatically shipped back to the virtual reference. The virtual class
has the same name as the shadowed class with a V
prefix. For example, the virtual class for a JGL Array
is
named VArray
. All the virtual containers and iterators may be found in the
com.objectspace.jgl.voyager
package, and the virtual algorithms in the
com.objectspace.jgl.voyager.algorithms
package.
For every constructor in the original class, the
virtual version of the class contains a method with
an additional argument which is the address of the program where the
function should be executed. The following example demonstrates how to
create and interact with a remote object. Note that after creating a
remote object, the syntax for accessing and mutating it is exactly the same
as that for a regular object.
// Copyright(c) 1997 ObjectSpace, Inc.
import com.objectspace.jgl.*;
import com.objectspace.jgl.voyager.*;
import com.objectspace.voyager.*;
public class Voyager1
{
/**
* This example only works with ObjectSpace Voyager(tm).
* Visit the Voyager homepage for more information.
*/
public static void main( String[] args )
{
try
{
// create a remote map that allows duplicate keys
VHashMap map = new VHashMap( true, "localhost:8000" );
// fill remote map
map.add( "city", "Austin" );
map.add( "song", "Texas Fight!" );
map.add( "mascot", "Bevo" );
map.add( "mascot", "Longhorns" );
System.out.println( "map = " + map ); // prints locally
// query remote container
System.out.println( "map.size() = " + map.size() );
System.out.println( "map.empty() = " + map.isEmpty() );
System.out.println( "map.get( \"song\" ) = " + map.get( "song" ) );
// mutate remote container
map.clear();
System.out.println( "\nafter remote map is cleared..." );
System.out.println( "map.size() = " + map.size() );
System.out.println( "map.empty() = " + map.isEmpty() );
System.out.println( "map.get( \"song\" ) = " + map.get( "song" ) );
}
catch ( VoyagerException ex )
{
System.err.println( "caught: " + ex );
}
Voyager.shutdown();
}
}
Output
voyager(tm) 2.0 beta 1, copyright objectspace 1997
address = 285.42.84.60:1597
map = HashMap( Pair( song, Texas Fight! ), Pair( mascot, Bevo ), Pair( mascot, Longhorns ), Pair( city, Austin ) )
map.size() = 4
map.empty() = false
map.get( "song" ) = Texas Fight!
after remote map is cleared...
map.size() = 0
map.empty() = true
map.get( "song" ) = null
By default, a remote message returns a copy of a method result. If the result is large, this can cause undesirable network traffic. This effect can become pronounced when dealing with iterators, because an iterator references the underlying container, and this information does not need to be copied. Luckily, Voyager allows a method to return a virtual reference to a result instead of a copy, thereby leaving the result in the remote program and greatly reducing the amount of network traffic.
To request that an object return a virtual reference for its methods, use
setVirtual()
.
You must ensure that the local program has dynamically linked the virtual
class before attempting to retrieve a virtual reference of that type. The
following example does so with the statement following the creation of the
remote container.
// Copyright(c) 1997 ObjectSpace, Inc.
import com.objectspace.jgl.*;
import com.objectspace.jgl.voyager.*;
import com.objectspace.voyager.*;
public class Voyager2
{
/**
* This example only works with ObjectSpace Voyager(tm).
* Visit the Voyager homepage for more information.
*/
public static void main( String[] args )
{
try
{
// create a remote list
VSList list = new VSList( "localhost:8000" );
new VSListIterator(); // force class loading
// fill remote list
list.add( "yakko" );
list.add( "wakko" );
list.add( "dot" );
System.out.println( "lowercase = " + list );
// obtain a local iterator to the remote list
list.setVirtual( true );
ForwardIterator iterator = list.start();
list.setVirtual( false );
// change all elements in remote list to uppercase
while ( !iterator.atEnd() )
{
String current = (String)iterator.get();
iterator.put( current.toUpperCase() );
iterator.advance();
}
System.out.println( "uppercase = " + list );
}
catch ( VoyagerException ex )
{
System.err.println( "caught: " + ex );
}
Voyager.shutdown();
}
}
Output
voyager(tm) 2.0 beta 1, copyright objectspace 1997
address = 285.42.84.60:1599
lowercase = SList( yakko, wakko, dot )
uppercase = SList( YAKKO, WAKKO, DOT )
Like constructors,
for every static method in the original class the
virtual version of the class contains a method with
an additional argument which is the address of the program where the
function should be executed. This means the JGL algorithms can be used
on remote containers just like you would use them on normal objects.
// Copyright(c) 1997 ObjectSpace, Inc.
import com.objectspace.jgl.*;
import com.objectspace.jgl.algorithms.*;
import com.objectspace.jgl.functions.*;
import com.objectspace.jgl.predicates.*;
import com.objectspace.jgl.voyager.*;
import com.objectspace.jgl.voyager.algorithms.*;
import com.objectspace.voyager.*;
public class Voyager3
{
/**
* This example only works with ObjectSpace Voyager(tm).
* Visit the Voyager homepage for more information.
*/
public static void main( String[] args )
{
try
{
// create and fill remote container
VDeque deque = new VDeque( "localhost:8000" );
new VDequeIterator(); // force class loading
deque.add( "Texas Fight!" );
deque.add( "Bevo" );
deque.add( "Hook 'Em" );
System.out.println( "deque = " + deque );
// print the contents of the container at the remote location
VApplying.forEach( deque, new Print(), "localhost:8000" );
// sort the remote array
VSorting.sort( deque, "localhost:8000" );
System.out.println( "\ndefault sort = " + deque );
// sort the remote array using a custom comparator
VSorting.sort( deque, new LessString(), "localhost:8000" );
System.out.println( " alpha sort = " + deque );
// expand the remote container
deque.pushFront( "White" );
deque.pushBack( "White" );
deque.pushFront( "White" );
deque.pushBack( "White" );
// perform an algorithm on a subrange of the remote container
System.out.println( "\nbefore = " + deque );
deque.setVirtual( true );
BidirectionalIterator b = (BidirectionalIterator)deque.start();
BidirectionalIterator e = (BidirectionalIterator)deque.finish();
b.advance();
e.retreat();
deque.setVirtual( false );
VReplacing.replace( b, e, "White", "Orange", "localhost:8000" );
System.out.println( " after = " + deque );
}
catch ( VoyagerException ex )
{
System.err.println( "caught: " + ex );
}
Voyager.shutdown();
}
}
Server Output
voyager(tm) 2.0 beta 1, copyright objectspace 1997
address = 285.42.132.60:8000
Texas Fight!
Bevo
Hook 'Em
Example Output
voyager(tm) 2.0 beta 1, copyright objectspace 1997
address = 285.42.84.60:1601
deque = Deque( Texas Fight!, Bevo, Hook 'Em )
default sort = Deque( Hook 'Em, Texas Fight!, Bevo )
alpha sort = Deque( Bevo, Hook 'Em, Texas Fight! )
before = Deque( White, White, Bevo, Hook 'Em, Texas Fight!, White, White )
after = Deque( White, Orange, Bevo, Hook 'Em, Texas Fight!, Orange, White )
Voyager supports database-independent distributed object persistence. It includes the Voyager Database object storage system which uses the Java serialization mechanism to persist any serializable object without modification. Alternatively, adapters can be created to support most of the popular database systems. The following examples use the Voyager Database for object storage. As always, for more information on Voyager and its utilities, visit http://www.objectspace.com/voyager.
The following example shows how to save, load, and delete a persistent JGL object.
In the first phase, a Voyager persistent server is started and associated
with the database file jgl8000.db
. Next, the Voyager4A program
creates a persistent map with alias JGL4
in the server.
Finally, the persistent server is shutdown using Control-C.
In the second phase, the persistent server is restarted and associated with the database that was created in the first phase. Next, the Voyager4B program connects to the persistent map, queries its contents, and then tells the map to die. This causes the container to be removed from the database.
To run the initial phase, start a persistent server on port 8000 (for example,
voyager 8000 -dc jgl8000.db
) in one window and
then run Voyager4A in a second window. When Voyager4A finishes, terminate
the server using Control-C.
// Copyright(c) 1997 ObjectSpace, Inc.
import com.objectspace.jgl.*;
import com.objectspace.jgl.voyager.*;
import com.objectspace.voyager.*;
public class Voyager4A
{
/**
* This example only works with ObjectSpace Voyager(tm).
* Visit the Voyager homepage for more information.
*/
public static void main( String[] args )
{
try
{
// create and fill a remote map
VHashMap map = new VHashMap( "localhost:8000/JGL4" );
map.add( "Spider-Man", "Peter Parker" );
map.add( "Wolverine", "Logan" );
map.add( "Batman", "Bruce Wayne" );
map.add( "Oracle", "Barbara Gordon" );
map.liveForever(); // do not garbage collect
map.saveNow(); // save copy to database of server 8000
System.out.println( "saved " + map );
}
catch ( VoyagerException ex )
{
System.err.println( "caught: " + ex );
}
Voyager.shutdown();
}
}
Output
voyager(tm) 2.0 beta 1, copyright objectspace 1997
address = 285.42.84.60:1603
saved HashMap( Pair( Batman, Bruce Wayne ), Pair( Wolverine, Logan ), Pair( Oracle, Barbara Gordon ), Pair( Spider-Man, Peter Parker ) )
voyager 8000 -d jgl8000.db
) in one
window, then run Voyager4B in a second window.
// Copyright(c) 1997 ObjectSpace, Inc.
import com.objectspace.jgl.*;
import com.objectspace.jgl.voyager.*;
import com.objectspace.voyager.*;
public class Voyager4B
{
/**
* This example only works with ObjectSpace Voyager(tm).
* Visit the Voyager homepage for more information.
*/
public static void main( String[] args )
{
try
{
// connect to persistent map in server 8000
VHashMap map = (VHashMap)VObject.forObjectAt("localhost:8000/JGL4");
query( map, "Spider-Man" );
query( map, "Mr. Fantastic" );
map.dieNow(); // kill map, remove from database
}
catch ( VoyagerException ex )
{
System.err.println( "caught: " + ex );
}
Voyager.shutdown();
}
public static void query( VHashMap map, String hero ) throws VoyagerException
{
Object name = map.get( hero );
if ( name == null )
System.out.println( hero + " is not in the database" );
else
System.out.println( hero + " is really " + name );
}
}
Output
voyager(tm) 2.0 beta 1, copyright objectspace 1997
address = 285.42.84.60:1605
Spider-Man is really Peter Parker
Mr. Fantastic is not in the database