Often a command pattern is used to execute some type of utility functions around the
execute() or to implement a system wide re-try strategy on a distributed system. Here is an example of a re-try strategy using a command pattern in an RMI system.
Greg
package hr.shared.rmi;
import hr.shared.util.*;
import java.rmi.*;
import java.rmi.server.*;
/**
* Adopted from the code by William Grosso, author of Java RMI
* 10/17/2001
*
* http://www.onjava.com/pub/a/onjava/2001/10/17/rmi.html
* oreillynet.com Copyright © 2000 O'Reilly & Associates, Inc.
*/
public abstract class AbstractRemoteMethodCall {
public Object makeCall() throws HRException, Exception {
Object result = null;
RetryStrategy strategy = getRetryStrategy();
while (strategy.shouldRetry()) {
HRUtil.log("----->ENVOKING REMOTE METHOD");
Remote remoteObject = getRemoteObject();
if (null==remoteObject) {
throw new HRException("remote object is null", 701);
}
try {
result = performRemoteCall(remoteObject);
HRUtil.log("----->REMOTE METHOD RESULT:" + result);
break;
} catch (RemoteException remoteException) {
try {
strategy.remoteExceptionOccurred();
} catch (RetryException retryException) {
handleRetryException(remoteObject);
}
}
}
return result;
}
/*
The next 4 methods define the core behavior. Of these, two must
be implemented by the subclass (and so are left abstract). The
remaining three can be altered to provide customized retry handling.
*/
/**
getRemoteObject is a template method which should, in most cases,
return the stub.
*/
protected abstract Remote getRemoteObject() throws HRException;
/**
performRemoteCall is a template method which actually makes the remote
method invocation.
*/
protected abstract Object performRemoteCall(Remote remoteObject) throws RemoteException, Exception;
protected RetryStrategy getRetryStrategy() {
return new AdditiveWaitRetryStrategy();
}
//simply re-throw the internal exception as an application exception
protected void handleRetryException(Remote remoteObject) throws HRException {
throw new HRException("Repeated attempts to communicate with " + remoteObject + " failed.", 702);
}
}
package hr.shared.rmi;
import hr.shared.util.*;
/**
The most commonly used retry strategy; it extends the waiting
period by a constant amount with each retry.
Note that the default version of this (e.g. the one with a
zero argument constructor) will make 3 calls and wind up waiting
approximately 11 seconds (zero wait for the first call, 3 seconds
for the second call, and 8 seconds for the third call). These
wait times are pretty small, and are usually dwarfed by socket
timeouts when network difficulties occur anyway.
*/
public class AdditiveWaitRetryStrategy extends RetryStrategy {
public static final long STARTING_WAIT_TIME = 3000;
public static final long WAIT_TIME_INCREMENT = 5000;
private long _currentTimeToWait;
private long _waitTimeIncrement;
public AdditiveWaitRetryStrategy () {
this(DEFAULT_NUMBER_OF_RETRIES , STARTING_WAIT_TIME, WAIT_TIME_INCREMENT);
}
public AdditiveWaitRetryStrategy (int numberOfRetries, long startingWaitTime, long waitTimeIncrement) {
super(numberOfRetries);
_currentTimeToWait = startingWaitTime;
_waitTimeIncrement = waitTimeIncrement;
}
protected long getTimeToWait() {
long returnValue = _currentTimeToWait;
_currentTimeToWait += _waitTimeIncrement;
return returnValue;
}
}
package hr.shared.rmi;
import hr.shared.util.*;
/**
Abstract base class for retry strategies.
*/
public abstract class RetryStrategy {
public static final int DEFAULT_NUMBER_OF_RETRIES = 3;
private int _numberOfTriesLeft;
public RetryStrategy() {
this(DEFAULT_NUMBER_OF_RETRIES);
}
public RetryStrategy(int numberOfRetries){
_numberOfTriesLeft = numberOfRetries;
}
public boolean shouldRetry() {
return (0 < _numberOfTriesLeft);
}
public void remoteExceptionOccurred() throws RetryException {
_numberOfTriesLeft --;
if (!shouldRetry()) {
HRUtil.log("----->GIVING UP...");
throw new RetryException();
}
waitUntilNextTry();
}
protected abstract long getTimeToWait();
private void waitUntilNextTry() {
HRUtil.log("-----> RMI FAILED. WAITING TO RETRY...");
long timeToWait = getTimeToWait();
try {
Thread.sleep(timeToWait );
}
catch (InterruptedException ignored) {}
}
}
//////////////////////////////2 different command objects////////////////
package hr.shared.rmi;
import hr.shared.util.*;
import hr.shared.entity.*;
import hr.shared.entity.pk.*;
import hr.server.db.*;
import java.rmi.*;
import java.rmi.server.*;
public class CreateDepartment extends AbstractRemoteMethodCall {
private HRDatabaseInterface hrDb;
private Department entity;
public CreateDepartment(HRDatabaseInterface hrDb, Department entity) {
this.hrDb = hrDb;
this.entity = entity;
}
protected Remote getRemoteObject() throws HRException {
return (Remote) hrDb;
}
protected Object performRemoteCall(Remote remoteObject) throws RemoteException, Exception {
HRDatabaseInterface hrDbInstance = (HRDatabaseInterface) remoteObject;
return hrDbInstance.createDepartment(entity);
}
}
package hr.shared.rmi;
import hr.shared.util.*;
import hr.shared.entity.*;
import hr.shared.entity.pk.*;
import hr.server.db.*;
import java.rmi.*;
import java.rmi.server.*;
public class RemoveDepartment extends AbstractRemoteMethodCall {
private HRDatabaseInterface hrDb;
private Department entity;
public RemoveDepartment(HRDatabaseInterface hrDb, Department entity) {
this.hrDb = hrDb;
this.entity = entity;
}
protected Remote getRemoteObject() throws HRException {
return (Remote) hrDb;
}
protected Object performRemoteCall(Remote remoteObject) throws RemoteException, Exception {
HRDatabaseInterface hrDbInstance = (HRDatabaseInterface) remoteObject;
return hrDbInstance.removeDepartment(entity);
}
}
-----Original Message-----
From: jayaraman sureshkumar [mailto:[EMAIL PROTECTED]]
Sent: Tuesday, June 18, 2002 3:34 AM
To: JDJList
Subject: [jdjlist] Command design pattern
Hello,
I need to know a simple example explaining the subject design pattern in a
nut shell.. please help..
Thanks
Suresh
_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp.
To change your membership options, refer to:
http://www.sys-con.com/java/list.cfm
http://www.sys-con.com/java/list.cfm
