2014-09-14 3 views
1

자바로 자바 스크립트를 해석하기 위해 Rhino를 사용하고 있습니다. 내 사용 사례 (RESTful/Webservices/HTTP GET/POST) (여러) 서비스 호출을 만드는 이러한 자바 스크립트가 필요합니다. 이러한 서비스 호출 중 일부는 본질적으로 비동기식입니다 (24 시간의 SLA 포함).Rhino : 일시 중지, 상태 저장 및 자바 스크립트 재개

그런 경우에 내 스크립트의 실행을 일시 중지하고 상태를 직렬화하고 (예 : 서비스가 콜백으로 돌아 오는 비동기 서비스의 페이로드로 전달 된 키로 S3를 말함) 실행을 다시 시작하려면 결과를 서비스에서 다시 얻을 때.

내가 직면 한 도전 과제는 컨텍스트가 아니기 때문에 ContinuationPending (RuntimeException 확장)이 직렬화 할 수 없다는 것입니다.

질문 : 스크립트의 상태를 저장하고 직렬화 된 양식에서 다시 가져 오는 다른 방법이 있습니까?

자바 스크립트 :

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

답변

2

나는 마침내 해결책을 발견. 핵심은 ScriptableOutputStream (직렬화) 및 ScriptableInputStream (직렬화 해제) Continuation 및 Scope을 사용하는 것입니다.

다음은 작동 코드입니다.

자바 스크립트 :

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