Oh god, throwing a RedirectException does not always make sense, so

I made an even more general base class that throws a TimeoutException.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@1199 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
ray
2003-08-15 02:23:47 +00:00
parent 0f732a6453
commit 34b01d80a7
2 changed files with 185 additions and 128 deletions
@@ -1,37 +1,14 @@
// //
// $Id: ServiceWaiter.java,v 1.2 2003/08/13 01:55:05 ray Exp $ // $Id: ServiceWaiter.java,v 1.3 2003/08/15 02:23:47 ray Exp $
package com.samskivert.servlet.util; package com.samskivert.servlet.util;
import com.samskivert.Log;
import com.samskivert.servlet.RedirectException; import com.samskivert.servlet.RedirectException;
import com.samskivert.util.ResultListener;
/** /**
* A handy base class for issuing server-side service requests and * Extends the basic ServiceWaiter to be useful for servlets.
* awaiting their responses from within a servlet.
*
* <em>Note:</em> You might think that it would be keen to use this
* anonymously like so:
*
* <pre>
* ServiceWaiter waiter = new ServiceWaiter() {
* public void handleSuccess (int invid, ...) {
* // handle success
* }
* // ...
* };
* </pre>
*
* But that won't work because public methods in anonymous inner classes
* do not have public visibility and so the invocation manager will not be
* able to reflect your response methods when the time comes to deliver
* the response. Unfortunately, there appears to be no manner in which to
* instruct the Java compiler to give public scope to an anonymous inner
* class rather than default scope. Sigh.
*/ */
public class ServiceWaiter public class ServiceWaiter extends com.samskivert.util.ServiceWaiter
implements ResultListener
{ {
/** Timeout to specify when you don't want a timeout. Use at your own /** Timeout to specify when you don't want a timeout. Use at your own
* risk. */ * risk. */
@@ -42,7 +19,7 @@ public class ServiceWaiter
*/ */
public ServiceWaiter () public ServiceWaiter ()
{ {
this(DEFAULT_WAITER_TIMEOUT); super();
} }
/** /**
@@ -52,56 +29,7 @@ public class ServiceWaiter
*/ */
public ServiceWaiter (int timeout) public ServiceWaiter (int timeout)
{ {
setTimeout(timeout); super(timeout);
}
/**
* Change the timeout being used for this ServiceWaiter after it
* has been constructed.
*/
public void setTimeout (int timeout)
{
_timeout = timeout;
}
/**
* Reset the service waiter so that it can be used again.
*/
public void reset ()
{
_success = 0;
_argument = null;
}
/**
* Marks the request as successful and posts the supplied response
* argument for perusal by the caller.
*/
public synchronized void postSuccess (Object arg)
{
_success = 1;
_argument = arg;
notify();
}
/**
* Marks the request as failed and posts the supplied response
* argument for perusal by the caller.
*/
public synchronized void postFailure (Object arg)
{
_success = -1;
_argument = arg;
notify();
}
/**
* Returns the argument posted by the waiter when the response
* arrived.
*/
public Object getArgument ()
{
return _argument;
} }
/** /**
@@ -110,33 +38,15 @@ public class ServiceWaiter
* @return true if a success response was posted, false if a failure * @return true if a success response was posted, false if a failure
* repsonse was posted. * repsonse was posted.
*/ */
public synchronized boolean awaitResponse () public boolean awaitResponse ()
throws RedirectException throws RedirectException
{ {
while (_success == 0) { try {
try { return waitForResponse();
// wait for the response, timing out after a while
if (_timeout == NO_TIMEOUT) {
wait();
} else { } catch (TimeoutException te) {
wait(1000L * _timeout); throw new RedirectException(getTimeoutRedirectURL());
}
// if we get here without some sort of response, then
// we've timed out and we should freak out
if (_success == 0) {
Log.warning("Service waiter timed out.");
Thread.dumpStack();
throw new RedirectException(getTimeoutRedirectURL());
}
} catch (InterruptedException ie) {
// fall through and wait again
}
} }
return (_success > 0);
} }
/** /**
@@ -147,32 +57,4 @@ public class ServiceWaiter
// TODO // TODO
return "/"; return "/";
} }
// documentation inherited from interface ResultListener
public void requestCompleted (Object result)
{
postSuccess(result);
}
// documentation inherited from interface ResultListener
public void requestFailed (Exception cause)
{
postFailure((cause != null) ? cause.getMessage() : null);
}
/** Whether or not the response succeeded; positive for success,
* negative for failure, zero means we haven't received the response
* yet. */
protected int _success = 0;
/** The argument posted by the waiter upon receipt of the response. */
protected Object _argument;
/** How many seconds to wait before giving up the ghost. */
protected int _timeout;
/** If a response is not received within the specified timeout, an
* exception is thrown which redirects the user to an internal error
* page. */
protected static final int DEFAULT_WAITER_TIMEOUT = 30;
} }
@@ -0,0 +1,175 @@
//
// $Id: ServiceWaiter.java,v 1.1 2003/08/15 02:23:47 ray Exp $
package com.samskivert.util;
import com.samskivert.Log;
/**
* A handy base class for issuing server-side service requests and
* awaiting their responses from within a servlet.
*
* <em>Note:</em> You might think that it would be keen to use this
* anonymously like so:
*
* <pre>
* ServiceWaiter waiter = new ServiceWaiter() {
* public void handleSuccess (int invid, ...) {
* // handle success
* }
* // ...
* };
* </pre>
*
* But that won't work because public methods in anonymous inner classes
* do not have public visibility and so the invocation manager will not be
* able to reflect your response methods when the time comes to deliver
* the response. Unfortunately, there appears to be no manner in which to
* instruct the Java compiler to give public scope to an anonymous inner
* class rather than default scope. Sigh.
*/
public class ServiceWaiter
implements ResultListener
{
/** Timeout to specify when you don't want a timeout. Use at your own
* risk. */
public static final int NO_TIMEOUT = -1;
public static class TimeoutException extends Exception
{
public TimeoutException ()
{
super("Timeout! Pow!");
}
}
/**
* Construct a ServiceWaiter with the default (30 second) timeout.
*/
public ServiceWaiter ()
{
this(DEFAULT_WAITER_TIMEOUT);
}
/**
* Construct a ServiceWaiter with the specified timeout.
*
* @param timeout the timeout, in seconds.
*/
public ServiceWaiter (int timeout)
{
setTimeout(timeout);
}
/**
* Change the timeout being used for this ServiceWaiter after it
* has been constructed.
*/
public void setTimeout (int timeout)
{
_timeout = timeout;
}
/**
* Reset the service waiter so that it can be used again.
*/
public void reset ()
{
_success = 0;
_argument = null;
}
/**
* Marks the request as successful and posts the supplied response
* argument for perusal by the caller.
*/
public synchronized void postSuccess (Object arg)
{
_success = 1;
_argument = arg;
notify();
}
/**
* Marks the request as failed and posts the supplied response
* argument for perusal by the caller.
*/
public synchronized void postFailure (Object arg)
{
_success = -1;
_argument = arg;
notify();
}
/**
* Returns the argument posted by the waiter when the response
* arrived.
*/
public Object getArgument ()
{
return _argument;
}
/**
* Blocks waiting for the response.
*
* @return true if a success response was posted, false if a failure
* repsonse was posted.
*/
public synchronized boolean waitForResponse ()
throws TimeoutException
{
while (_success == 0) {
try {
// wait for the response, timing out after a while
if (_timeout == NO_TIMEOUT) {
wait();
} else {
wait(1000L * _timeout);
}
// if we get here without some sort of response, then
// we've timed out and we should freak out
if (_success == 0) {
Log.warning("Service waiter timed out.");
Thread.dumpStack();
throw new TimeoutException();
}
} catch (InterruptedException ie) {
// fall through and wait again
}
}
return (_success > 0);
}
// documentation inherited from interface ResultListener
public void requestCompleted (Object result)
{
postSuccess(result);
}
// documentation inherited from interface ResultListener
public void requestFailed (Exception cause)
{
postFailure((cause != null) ? cause.getMessage() : null);
}
/** Whether or not the response succeeded; positive for success,
* negative for failure, zero means we haven't received the response
* yet. */
protected int _success = 0;
/** The argument posted by the waiter upon receipt of the response. */
protected Object _argument;
/** How many seconds to wait before giving up the ghost. */
protected int _timeout;
/** If a response is not received within the specified timeout, an
* exception is thrown which redirects the user to an internal error
* page. */
protected static final int DEFAULT_WAITER_TIMEOUT = 30;
}