SDSU CS 696 Emerging Technologies: Java Distributed Computing
Spring Semester, 1999
A Simple Transaction Example
Previous    Lecture Notes Index    Next    
© 1999, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 02-May-99

Contents of Doc 32, A Simple Transaction Example


References

Past lecture notes.

Doc 32, A Simple Transaction Example Slide # 2

A Simple Transaction Example


This is a simple example that uses the transaction manager. The classes and files are involved:

ClientLauncher
This class uses multicast discovery to contact a Jini lookup service that belongs to a group. Once it discovers the lookup service it creates an instance TransactionClient, passing a remote reference to the lookup manager to the TransactionClient object.

TransactionClient
Extracts a remote reference for the transaction manager from the Jini lookup service. When mahalo, the transaction manager, is started the -Dcom.sun.jini.mahalo.managerName flag provides the name of the transaction manager in the lookup service. TransactionClient performs two different transactions. The first with three YesParticipants and the second with two YesParticipants and a NoParticipant. Since the second transaction has a NoParticipant, an exception is thrown.

YesParticipant
Implements the four TransactionParticipant methods. Prints a message each time a method is called. Always accepts a transaction. Since this class has no state, its prepare method should return NOTCHANGED. However, to show operation of the transaction manager, it returns PREPARED.

NoParticipant
Implements the four TransactionParticipant methods. Prints a message each time a method is called. Always rejects a transaction.

Service Script – startJini
This script file starts an http server, rmid, reggie, and mahalo. Sleep is used between starting rmid, reggie and mahalo to insure the previous service is running. The script uses the following file structure. The directory ~whitney/jini_data contains the policy file for the services in the file policy. The directory ~whitney/jini_data/jini_logs is used for the logs of the jini services in the subdirectories ~whitney/jini_data/jini_logs/rmid, ~whitney/jini_data/jini_logs/mahalo, ~whitney/jini_data/jini_logs/reggie. The directory ~whitney/jini_data/jini_http_root contains the files the http server can access. The script uses a number of variables. The values of these variables when run on rohan.sdsu.edu from the whitney account are given below.
httpPort=8789;
rmidPort=8689;
user=whitney
jiniDir=/opt/jini1_0/lib
jiniLog=/home/ma/whitney/jini_data/jini_logs
jiniData=/home/ma/whitney/jini_data
jiniHTTPRoot =/home/ma/whitney/jini_http_root
host=rohan.sdsu.edu
groupName=whitney.rohan.sdsu.edu
codebase=http://rohan.sdsu.edu:8789


Doc 32, A Simple Transaction Example Slide # 3

Running the Example

No Package

Files


/opt/java/jre/lib/ext/
The table below contains the files in this directory. Being in this location makes the jar files below extensions to java 1.2 on rohan. This means that these jar file do not have to be in your classpath to use classes in the jar files. In particular, jini clients will have access to all the jini files. Hence, clients will not have to dynamically download the reggie-dl.jar, mahalo-dl.jar files. This was done to make developing jini programs on rohan a bit easier (so you don’t need for the http server to be working correctly).

iiimp.jar
mahalo.jar
sdsuLibJKD12.jar
jini-core.jar
outrigger.jar
sun-util.jar
jini-ext.jar
reggie.jar
transient-outrigger.jar

/home/ma/whitney/jini_data/
Contains the file “policy”, which is policy file used by the jini services

/home/ma/whitney/jini_data/jini_logs/
Contains the subdirectories mahalo, reggie, rmid which are used by the Jini services to store the log files. This is set up in the startJini script

/home/ma/whitney/jini_data/jini_http_root/
Contains the files: NoParticipant_Stub.class, YesParticipant_Stub.class, reggie-dl.jar, mahalo-dl.jar. These files are downloaded on demand to clients by the http server. These stub files were moved here after the stubs were generated.

/home/ma/whitney/jini/examples/transaction/noPackage/
Before compiling the example this directory contains the files in the table below.

ClientLauncher.java
TransactionClient.java
NoParticipant.java
YesParticipant.java

/home/ma/whitney/bin/
Contains the script file startJini. The directory is in my path.


Doc 32, A Simple Transaction Example Slide # 4

Command to Run with No Packages


This is done by running the script startJini. This is not done in the directory that contains the class files for the example. This only needs to be done once.
In /home/ma/whitney/jini/examples/transaction/noPackage I compiled the files using:

   javac *.java
The transaction manager sends message to all TransactionParticipants. The TransactionParticipants interface extends java.rmi.Remote. This means all TransactionParticipants need stubs and skeletons. This is done in this example using the commands below. Note for some reason that I do not understand, I have to add the jini jar files to my path for rmic to generate the stubs and skeleton classes for any jini code. Since the jini jar files are extensions to the JVM I should not have to do this.

   rmic NoParticipant
   rmic YesParticipant
I used the following command to do this. This assumes the current directory is /home/ma/whitney/jini/examples/transaction/noPackage
   cp *stub.class /home/ma/whitney/jini_data/jini_http_root/
I used the following command. It assumes the group of my reggie is whitney.rohan.sdsu.edu.
   java ClientLauncher –group=whitney.rohan.sdsu.edu

Doc 32, A Simple Transaction Example Slide # 5

Using Packages

I ran the example placing the classes in a package. The package for all four classes is whitney.jini.examples.transaction.

Files


/opt/java/jre/lib/ext/
The table below contains the files in this directory. This makes the jar files below extensions to java 1.2 on rohan. This means that these jar files do not have to be in your classpath to use classes in the jar files. In particular, jini clients will have access to all the jini files. Hence, clients will not have to dynamically download the reggie-dl.jar, mahalo-dl.jar files. This was done to make developing jini programs on rohan a bit easier (reduce need for the http server to be working correctly).

iiimp.jar
mahalo.jar
sdsuLibJKD12.jar
jini-core.jar
outrigger.jar
sun-util.jar
jini-ext.jar
reggie.jar
transient-outrigger.jar

/home/ma/whitney/jini_data/
Contains the file “policy”, which is policy file used by the jini services

/home/ma/whitney/jini_data/jini_logs/
Contains the subdirectories mahalo, reggie, rmid which are used by the Jini services to store the log files. This is set up in the startJini script

/home/ma/whitney/jini_data/jini_http_root/
Contains the files: reggie-dl.jar, mahalo-dl.jar. These files are downloaded on demand to clients by the http server.

/home/ma/whitney/jini_data/jini_http_root/whitney/jini/examples/transaction/
Contains the files: NoParticipant_Stub.class and YesParticipant_Stub.class. These stub files were moved here after the stubs were generated.
/home/ma/whitney/jini/examples/transaction/
Before compiling the example this directory contains the files in the table below.

ClientLauncher.java
TransactionClient.java
NoParticipant.java
YesParticipant.java

/home/ma/whitney/bin/
Contains the script file startJini. The directory is in my path.


Doc 32, A Simple Transaction Example Slide # 6

Command to Run with Packages


This is done by running the script startJini. This is not done in the directory that contains the class files for the example. This only needs to be done once.
In /home/ma/whitney/jini/examples/transaction/ I compiled the files using:

   javac *.java
The transaction manager sends message to all TransactionParticipants. The TransactionParticipants interface extends java.rmi.Remote. This means all TransactionParticipants need stubs and skeletons. This is done in this example using the commands below. Note for some reason that I do not understand, I have to add the jini jar files to my path for rmic to generate the stubs and skeleton classes for any jini code. Since the jini jar files are extensions to the JVM I should not have to do this.

   rmic whitney.jini.examples.transaction.NoParticipant
   rmic whitney.jini.examples.transaction.YesParticipant
I used the following command to do this. This assumes the current directory is /home/ma/whitney/jini/examples/transaction/noPackage
   cp *stub.class ~/jini_data/jini_http_root/whitney/jini/examples/transaction
I used the following command. It assumes the group of my reggie is whitney.rohan.sdsu.edu.
java whitney.jini.examples.transaction.ClientLauncher –group=whitney.rohan.sdsu.edu


Doc 32, A Simple Transaction Example Slide # 7

Rohan & Moria


I was able to run the example on rohan. This means the Jini services were running on rohan and the ClientLauncher was run on rohan. When I ran the ClientLauncher on moria, it found the reggie service on rohan, but an exception was thrown when the client tried to contact the transaction manager. This appears to be a problem with the host names of the machines not being properly read by the java VM.

Doc 32, A Simple Transaction Example Slide # 8

Source Code

ClientLauncher


import java.io.IOException;
import java.rmi.RMISecurityManager;
import net.jini.core.discovery.LookupLocator;    
import net.jini.core.lookup.ServiceRegistrar; 
import net.jini.discovery.DiscoveryEvent;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.LookupDiscovery;
import sdsu.util.ProgramProperties;
public class ClientLauncher  implements DiscoveryListener
   {
   public static void main (String[] args) throws Exception
      {
      System.setSecurityManager (new RMISecurityManager ());
      ProgramProperties flags = new ProgramProperties( args);
      if ( !flags.containsKey(  "group") )
         {
         System.out.println( "Usage: java ClientLauncher -group=groupName" );
         System.exit(0);
         }
      String groupsString = flags.getString( "group" );
      new ClientLauncher( groupsString );
      Thread.currentThread().sleep( 1000 * 60 * 2 );
      }
   
   public ClientLauncher( String group ) throws IOException
      {
      String[] serverGroup = { group };
      LookupDiscovery findAllLookupServices = 
         new LookupDiscovery( serverGroup );
      
      findAllLookupServices.addDiscoveryListener( this );
      }
   
   public void discovered(DiscoveryEvent lookupService ) 
      {
      startClient( lookupService);
      }
   public void discarded(DiscoveryEvent lookupService) 
      {
      }
   private void startClient( DiscoveryEvent event) 
      {
      try 
         {
         ServiceRegistrar lookupServices[] = event.getRegistrars();
         if ( lookupServices.length > 0 )
            {
            TransactionClient aClient = new TransactionClient( lookupServices[0] );
            }
         } 
      catch (Exception lookupProblem) 
         {
         lookupProblem.printStackTrace();
         }
      }
   }

Doc 32, A Simple Transaction Example Slide # 9

TransactionClient


import java.rmi.RemoteException;
import net.jini.core.entry.Entry;
import net.jini.core.lease.Lease;
import net.jini.core.lookup.ServiceRegistrar; 
import net.jini.core.lookup.ServiceTemplate; 
import net.jini.core.transaction.server.TransactionManager.Created;
import net.jini.core.transaction.server.TransactionManager;
import net.jini.lookup.entry.Name;
public class TransactionClient
   {
   TransactionManager manager;
   public TransactionClient( ServiceRegistrar registrar ) throws RemoteException
      {
      System.out.println( "New Client" );
      Entry[] serverAttributes = new Entry[1];
      serverAttributes[0] = new Name ("TransactionManager");
      ServiceTemplate template = new ServiceTemplate (null, null, serverAttributes);
      System.out.println( "Get Transaction M" );
      manager = (TransactionManager) registrar.lookup (template);
      if (manager == null )
         System.out.println( "Null manager" );
      else
         {
         System.out.println( "Got a good manager" );
         startExample();
         }
      }
      
   public void startExample()
      {
      try
         {
         System.out.println( "Start transcation with three YesParticipants" );
         Created leasedTransaction = manager.create( 1000 * 60 * 2 );
         
         manager.join( leasedTransaction.id, new YesParticipant( "A"), 0 );
         manager.join( leasedTransaction.id, new YesParticipant( "B"), 0 );
         manager.join( leasedTransaction.id, new YesParticipant( "C"), 0 );
         System.out.println( "Start commit" );
         manager.commit( leasedTransaction.id );
                  
         Thread.sleep( 1000 * 10 );
         
         System.out.println( "Start transcation with 2 YesParticipants & 1 no" );
         leasedTransaction = manager.create( 1000 * 60 * 2 );
         
         manager.join( leasedTransaction.id, new YesParticipant( "D"), 0 );
         manager.join( leasedTransaction.id, new NoParticipant( "E"), 0 );
         manager.join( leasedTransaction.id, new YesParticipant( "F"), 0 );
         System.out.println( "Start commit" );
         manager.commit( leasedTransaction.id );
                  
         System.out.println( "Good bye" );
         }
         
      catch (Exception leaseDenied )
         {
         leaseDenied.printStackTrace();
         }
      }      
   }

Doc 32, A Simple Transaction Example Slide # 10

NoParticipant


import net.jini.core.transaction.server.TransactionManager;
import net.jini.core.transaction.server.TransactionParticipant;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
public class NoParticipant extends UnicastRemoteObject implements TransactionParticipant
   {
   String name;
   
   public NoParticipant( String aName ) throws RemoteException
      {
      super();
      name = aName;
      }
   public synchronized void abort(TransactionManager mgr, long transactionID) 
      {
      System.out.println( "Abort called on NoParticipant " + name );
      }
      
   public synchronized void commit(TransactionManager mgr, long transactionID) 
      {
      System.out.println( "Commit called on NoParticipant " + name );
      }
      
   public int prepare(TransactionManager mgr, long transactionID) 
      {
      System.out.println( "Prepare called on NoParticipant " + name );
      return ABORTED;
      }
   public int prepareAndCommit(TransactionManager mgr, long transactionID) 
      {
      System.out.println( "prepare & commit called on NoParticipant " + name );
      int result = prepare( mgr, transactionID );
      if ( result == PREPARED )
         {
         commit(  mgr, transactionID );
         result = COMMITTED;
         }
      return result;
      }
   }

Doc 32, A Simple Transaction Example Slide # 11

YesParticipant


import net.jini.core.transaction.server.TransactionManager;
import net.jini.core.transaction.server.TransactionParticipant;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
public class YesParticipant extends UnicastRemoteObject implements TransactionParticipant
   {
   String name;
   
   public YesParticipant( String aName ) throws RemoteException
      {
      super();
      name = aName;
      }
      
   public synchronized void abort(TransactionManager mgr, long transactionID) 
      {
      System.out.println( "Abort called on YesParticipant " + name );
      }
      
   public synchronized void commit(TransactionManager mgr, long transactionID) 
      {
      System.out.println( "Commit called on YesParticipant " + name );
      }
      
   public int prepare(TransactionManager mgr, long transactionID) 
      {
      System.out.println( "Prepare called on YesParticipant " + name );
      return PREPARED;
      }
   public int prepareAndCommit(TransactionManager mgr, long transactionID) 
      {
      System.out.println( "prepare & commit called on YesParticipant " + name );
      int result = prepare( mgr, transactionID );
      if ( result == PREPARED )
         {
         commit(  mgr, transactionID );
         result = COMMITTED;
         }
      return result;
      }
   }

Doc 32, A Simple Transaction Example Slide # 12

Service Script – startJini


#/bin/csh
#Start jini services
set httpPort=8789;
set rmidPort=8689;
set user=´whoami´
set jiniDir=/opt/jini1_0/lib
set jiniLog=~$user/jini_data/jini_logs
set jiniData=~$user/jini_data
set jiniHTTPRoot = $jiniData/jini_http_root
set host=´hostname´"."´domainname´
set groupName=´whoami´"."´hostname´"."´domainname´
set codebase=http://${host}:$httpPort
java -jar $jiniDir/tools.jar -port $httpPort -dir $jiniHTTPRoot -verbose & 
echo "http server started"
echo ""
echo "Remove old log files"
echo ""
rm -Rf $jiniLog/rmid
rm -Rf $jiniLog/mahalo 
rm -Rf $jiniLog/reggie 
rmid  -C-Djava.rmi.server.codebase=$codebase \
                -C-Djava.rmi.server.hostname=$host \
                -C-Djava.rmi.activation.port=$rmidPort \
                -log $jiniLog/rmid -port $rmidPort &
echo "rmid started"
echo ""
sleep 5
java -Djava.rmi.server.hostname=$host  -Djava.rmi.activation.port=$rmidPort 
   -jar $jiniDir/reggie.jar $codebase/reggie-dl.jar 
   $jiniData/policy $jiniLog/reggie $groupName &
echo "reggie started"
echo ""
sleep 5
java -Djava.rmi.server.hostname=$host  -Djava.rmi.server.codebase=$codebase 
   -Djava.rmi.activation.port=$rmidPort -Djava.security.policy=$jiniData/policy  
   -Dcom.sun.jini.mahalo.managerName=TransactionManager 
   -jar $jiniDir/mahalo.jar $codebase/mahalo-dl.jar 
   $jiniData/policy $jiniLog/mahalo $groupName &
echo "mahalo started"

Doc 32, A Simple Transaction Example Slide # 13

Policy File


grant codebase "file:${java.class.path}" {
    permission java.io.FilePermission "/export/home/whitney/jini_data/jini_logs/-", 
      "read,write,delete";
    permission java.io.FilePermission "<<ALL FILES>>", "read";
    permission java.lang.RuntimePermission "modifyThreadGroup";
    permission java.lang.RuntimePermission "modifyThread";
    permission java.net.SocketPermission "*:1024-", "connect,accept";
    // for http: codebases
    permission java.net.SocketPermission "*", "connect,accept";
    permission java.net.SocketPermission "224.0.1.85", "connect,accept";
    permission java.util.PropertyPermission "java.rmi.server.hostname", "read";
    permission java.util.PropertyPermission "com.sun.jini.reggie.*", "read";
    permission java.util.PropertyPermission "net.jini.discovery.*", "read";
    permission net.jini.discovery.DiscoveryPermission "*";
};


Copyright ©, All rights reserved.
1999 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.

Previous    visitors since 02-May-99    Next