javareactjscorda

Corda RPC: A hot observable returned from an RPC was never subscribed to


I build a CorDapp based on the Java Template. On top of that, I created a React front-end. Now, I want to start a flow from my front-end. To do so, I modified the template server, so that the controller starts my flow:

@GetMapping(value = "/templateendpoint", produces = "text/plain")
    private String templateendpoint() {
        proxy.startTrackedFlowDynamic(issueTokens.class, 30, "O=Bob, L=Berlin, C=DE");
        return "The flow was started";  
    }

This operation does start the flow that issues 30 tokens to Bob. I can see that the flow was successful, by querying Bob's vault. However, I get the following error on the template server:

RPCClientProxyHandler.onRemoval - A hot observable returned from an RPC was never subscribed to.
This wastes server-side resources because it was queueing observations for retrieval.
It is being closed now, but please adjust your code to call .notUsed() on the observable to close it explicitly. (Java users: subscribe to it then unsubscribe). 
If you aren't sure where the leak is coming from, set -Dnet.corda.client.rpc.trackRpcCallSites=true on the JVM command line and you will get a stack trace with this warning.

After this first transaction, I cannot start another flow. The .notUsed() method only works for Kotlin. However, I couldn't find a working way to subscribe and then unsubscribe from the observable.

Could anyone give me an example on how to implement this with the Corda flow? Moreover, what is the most practical way to pass information from the front-end to the controller class, in order to use that as flow arguments?


Solution

  • The reason that the error appears is that the Observable on the client-side gets garbage collected.

    The solution is provided has been provided in the bracket- (Java users: subscribe to it then unsubscribe)

    So in your case, you can do something like this:

    Subscription subs = updates.subscribe();
    subs.unsubscribe();
    

    Probably a more practical way is to keep the observable instance as a private attribute - such that it won't get garbage-collected. ie.

    private Observable observable;
    

    Ref: https://docs.corda.net/docs/corda-os/4.4/clientrpc.html#observables