ObjectSpace Homepage

JGL - The Generic Collection Library for Java
Contents Iterators Class Summary

ObjectSpace Voyager

Remote Creation and Access
Remote 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. Voyager’s 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.


Remote Creation and Access

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.



Example Voyager1.java
// 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


Remote Iteration

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.



Example Voyager2.java
// 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 )


Remote Algorithms

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.



Example Voyager3.java
// 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 )


Persistence

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.



Example Voyager4A.java
// 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 ) )



To run the second phase, restart the persistent server on port 8000 and connect to the database just created (for example, voyager 8000 -d jgl8000.db) in one window, then run Voyager4B in a second window.


Example Voyager4B.java
// 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


Contents Iterators Class Summary