* Implement app.invokeAsync() using public FutureResult interface.
This commit is contained in:
parent
a0ea3b31de
commit
7f58c102bf
2 changed files with 146 additions and 73 deletions
59
src/helma/framework/FutureResult.java
Normal file
59
src/helma/framework/FutureResult.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2006 Hannes Wallnoefer <hannes@helma.at>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package helma.framework;
|
||||
|
||||
/**
|
||||
* A handle for an asynchronous request execution. This allows to wait for
|
||||
* request termination, get the result or the exception of the execution.
|
||||
*/
|
||||
public interface FutureResult {
|
||||
/**
|
||||
* Get the result of the execution. If the execution is still active,
|
||||
* or if the invocation threw an exception, this method immediately returns null.
|
||||
* @return the result, or null
|
||||
*/
|
||||
Object getResult();
|
||||
|
||||
/**
|
||||
* Get the exception of the execution, if one was thrown. If the execution
|
||||
* is still active, or if no exception was thrown, this method immediately returns null.
|
||||
* @return the exception, or null
|
||||
*/
|
||||
Exception getException();
|
||||
|
||||
/**
|
||||
* Returns true if the execution is still active, and false if not.
|
||||
* @return true if the execution is still active
|
||||
*/
|
||||
boolean getRunning();
|
||||
|
||||
/**
|
||||
* Wait for execution to terminat, returning the execution result, if one is available.
|
||||
* @return the execution result, or null
|
||||
* @throws InterruptedException if we were interrupted by some other thread
|
||||
*/
|
||||
Object waitForResult() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Wait for a specific ammount of thime for the execution to terminate, returning
|
||||
* the execution result, if one is available.
|
||||
* @param timeout the number of milliseconds to wait
|
||||
* @return the execution result, or null
|
||||
* @throws InterruptedException if we were interrupted by some other thread
|
||||
*/
|
||||
Object waitForResult(long timeout) throws InterruptedException;
|
||||
}
|
|
@ -22,6 +22,7 @@ import helma.util.CronJob;
|
|||
import helma.util.SystemMap;
|
||||
import helma.util.WrappedMap;
|
||||
import helma.framework.repository.*;
|
||||
import helma.framework.FutureResult;
|
||||
import helma.main.Server;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -33,7 +34,8 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* Application bean that provides a handle to the scripting environment to
|
||||
* application specific functionality.
|
||||
*/
|
||||
public class ApplicationBean implements Serializable {
|
||||
Application app;
|
||||
|
@ -682,11 +684,11 @@ public class ApplicationBean implements Serializable {
|
|||
* this long, we will try to interrupt the invocation
|
||||
* @return an object with the properties described above
|
||||
*/
|
||||
public Object invokeAsync(Object thisObject,
|
||||
public FutureResult invokeAsync(Object thisObject,
|
||||
final Object function,
|
||||
final Object[] args) {
|
||||
// default timeout of 15 minutes
|
||||
return invokeAsync(thisObject, function, args, 60000L * 15);
|
||||
return new AsyncInvoker(thisObject, function, args, 60000L * 15);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -712,76 +714,9 @@ public class ApplicationBean implements Serializable {
|
|||
* this long, we will try to interrupt the invocation
|
||||
* @return an object with the properties described above
|
||||
*/
|
||||
public Object invokeAsync(final Object thisObject,
|
||||
final Object function,
|
||||
final Object[] args,
|
||||
final long timeout) {
|
||||
Thread thread = new Thread() {
|
||||
|
||||
private Object result;
|
||||
private Exception exception;
|
||||
private boolean running = true;
|
||||
|
||||
public void run() {
|
||||
RequestEvaluator reval = null;
|
||||
try {
|
||||
reval = app.getEvaluator();
|
||||
setResult(reval.invokeInternal(thisObject, function, args, timeout));
|
||||
} catch (Exception x) {
|
||||
setException(x);
|
||||
} finally {
|
||||
running = false;
|
||||
app.releaseEvaluator(reval);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean getRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
private synchronized void setResult(Object obj) {
|
||||
result = obj;
|
||||
running = false;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized Object getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized Object waitForResult() throws InterruptedException {
|
||||
if (!running)
|
||||
return result;
|
||||
wait();
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized Object waitForResult(long timeout)
|
||||
throws InterruptedException {
|
||||
if (!running)
|
||||
return result;
|
||||
wait(timeout);
|
||||
return result;
|
||||
}
|
||||
|
||||
private synchronized void setException(Exception x) {
|
||||
exception = x;
|
||||
running = false;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new StringBuffer("AsyncInvokeThread{running: ").append(running)
|
||||
.append(", result: ").append(result).append(", exception: ")
|
||||
.append(exception).append("}").toString();
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
return thread;
|
||||
public FutureResult invokeAsync(Object thisObject, Object function,
|
||||
Object[] args, long timeout) {
|
||||
return new AsyncInvoker(thisObject, function, args, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -791,4 +726,83 @@ public class ApplicationBean implements Serializable {
|
|||
public String toString() {
|
||||
return "[Application " + app.getName() + "]";
|
||||
}
|
||||
|
||||
class AsyncInvoker extends Thread implements FutureResult {
|
||||
|
||||
private Object thisObject;
|
||||
private Object function;
|
||||
private Object[] args;
|
||||
private long timeout;
|
||||
|
||||
private Object result;
|
||||
private Exception exception;
|
||||
private boolean running = true;
|
||||
|
||||
private AsyncInvoker(Object thisObj, Object func, Object[] args, long timeout) {
|
||||
thisObject = thisObj;
|
||||
function = func;
|
||||
this.args = args;
|
||||
this.timeout = timeout;
|
||||
start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
RequestEvaluator reval = null;
|
||||
try {
|
||||
reval = app.getEvaluator();
|
||||
setResult(reval.invokeInternal(thisObject, function, args, timeout));
|
||||
} catch (Exception x) {
|
||||
setException(x);
|
||||
} finally {
|
||||
running = false;
|
||||
app.releaseEvaluator(reval);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean getRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
private synchronized void setResult(Object obj) {
|
||||
result = obj;
|
||||
running = false;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized Object getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized Object waitForResult() throws InterruptedException {
|
||||
if (!running)
|
||||
return result;
|
||||
wait();
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized Object waitForResult(long timeout)
|
||||
throws InterruptedException {
|
||||
if (!running)
|
||||
return result;
|
||||
wait(timeout);
|
||||
return result;
|
||||
}
|
||||
|
||||
private synchronized void setException(Exception x) {
|
||||
exception = x;
|
||||
running = false;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new StringBuffer("AsyncInvokeThread{running: ").append(running)
|
||||
.append(", result: ").append(result).append(", exception: ")
|
||||
.append(exception).append("}").toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue