【问题标题】:Rhino: Ability to pause, save state and resume javascriptRhino:能够暂停、保存状态和恢复 javascript
【发布时间】:2014-09-14 19:59:11
【问题描述】:

我正在使用 Rhino 通过 Java 解释 javascripts。我的用例需要这些 javascript 进行(多个)服务调用(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 (..) {
        ..
    }
}

Java:

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
    }
}

【问题讨论】:

    标签: javascript rhino java-scripting-engine


    【解决方案1】:

    我终于找到了解决办法。关键是使用 ScriptableOutputStream(用来序列化)和 ScriptableInputStream(用来反序列化)Continuation 和 Scope。

    下面是工作代码。

    Javascript:

    function invokeFooService(arg) {
        return foo.bar.Helper.invokeFooServiceAsync(arg);
    }
    
    function main() {
        // Main JS function
        ..
        var response = invokeFooService(arg);
        if (..) {
            ..
        }
    }
    

    Java:

    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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      • 2011-10-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多