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:
@@ -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;
|
||||
|
||||
import com.samskivert.Log;
|
||||
import com.samskivert.servlet.RedirectException;
|
||||
import com.samskivert.util.ResultListener;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Extends the basic ServiceWaiter to be useful for servlets.
|
||||
*/
|
||||
public class ServiceWaiter
|
||||
implements ResultListener
|
||||
public class ServiceWaiter extends com.samskivert.util.ServiceWaiter
|
||||
{
|
||||
/** Timeout to specify when you don't want a timeout. Use at your own
|
||||
* risk. */
|
||||
@@ -42,7 +19,7 @@ public class ServiceWaiter
|
||||
*/
|
||||
public ServiceWaiter ()
|
||||
{
|
||||
this(DEFAULT_WAITER_TIMEOUT);
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,56 +29,7 @@ public class ServiceWaiter
|
||||
*/
|
||||
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;
|
||||
super(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,33 +38,15 @@ public class ServiceWaiter
|
||||
* @return true if a success response was posted, false if a failure
|
||||
* repsonse was posted.
|
||||
*/
|
||||
public synchronized boolean awaitResponse ()
|
||||
public boolean awaitResponse ()
|
||||
throws RedirectException
|
||||
{
|
||||
while (_success == 0) {
|
||||
try {
|
||||
// wait for the response, timing out after a while
|
||||
if (_timeout == NO_TIMEOUT) {
|
||||
wait();
|
||||
try {
|
||||
return waitForResponse();
|
||||
|
||||
} 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 RedirectException(getTimeoutRedirectURL());
|
||||
}
|
||||
|
||||
} catch (InterruptedException ie) {
|
||||
// fall through and wait again
|
||||
}
|
||||
} catch (TimeoutException te) {
|
||||
throw new RedirectException(getTimeoutRedirectURL());
|
||||
}
|
||||
|
||||
return (_success > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,32 +57,4 @@ public class ServiceWaiter
|
||||
// TODO
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user