我正在使用Rhino来解释Java的javascripts。我的用例需要这些javascripts进行(多个)服务调用(RESTful / Webservices / HTTP GET / POST)。其中一些服务调用本质上是异步的(具有24小时的SLA)。
我希望能够在这种情况下暂停执行我的脚本,序列化状态(将其保存,例如S3,将密钥传递给服务在回调时返回的异步服务的有效负载)并在恢复时执行我从服务中得到了结果。
我面临的挑战是ContinuationPending(扩展RuntimeException)不可序列化(因为Context不是)。
问题:是否有其他方法可以存储脚本状态并从序列化表单中恢复?
使用Javascript:
function invokeFooService(arg) {
return foo.bar.Helper.invokeFooServiceAsync(arg);
}
function main() {
// Main JS function
..
var response = invokeFooService(arg);
if (..) {
..
}
}
爪哇:
package foo.bar;
public class Helper {
public static final void invokeFooServiceAsync(String arg) {
Context cx = getContext();
ContinuationPending pending = cx.captureContinuation();
// At this point the script is paused
// Serialize the state of script
invokeFooService(arg, key);
}
public static final void returnResponse(FooResponse response, String key) {
// De serialize the state of script
ContinuationPending pending = ..
Context cx = getContext();
cx.resumeContinuation(pending.getContinuation(), getScope(), response);
// Script is resumed
}
}
答案 0 :(得分:2)
我终于找到了解决方案。关键是使用ScriptableOutputStream(序列化)和ScriptableInputStream(反序列化)Continuation和Scope。
以下是工作代码。
使用Javascript:
function invokeFooService(arg) {
return foo.bar.Helper.invokeFooServiceAsync(arg);
}
function main() {
// Main JS function
..
var response = invokeFooService(arg);
if (..) {
..
}
}
爪哇:
package foo.bar;
public class Helper {
public static final void invokeFooServiceAsync(String arg) {
Context cx = getContext();
ContinuationPending pending = cx.captureContinuation();
// Script is paused here
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ScriptableOutputStream sos = new ScriptableOutputStream(baos, getScope());
sos.writeObject(pending.getContinuation());
sos.writeObject(getScope());
String servicePayload = Base64.encodeBase64String(baos.toByteArray());
invokeFooServiceForReal(arg, servicePayload); // This method invokes the async service
}
public static final void returnFooServiceResponse(FooResponse response, String servicePayload) {
// De serialize the state of script
byte[] continuationAndScope = Base64.decodeBase64(servicePayload);
ScriptableInputStream sis = new ScriptableInputStream(new ByteArrayInputStream(continuationAndScope), getScope());
Scriptable continuation = (Scriptable) sis.readObject();
Scriptable scope = (Scriptable) sis.readObject();
getContext().resumeContinuation(continuation, scope, response);
// Script resumed
}
}