Domanda

I am trying to update a document using rpc service.

I have an xpage with a button. I want to click that button and by using CS javascript to setInterval and update a document field every 5 seconds.

I used the remote service control and the code is this:

<xe:jsonRpcService id="jsonRpcService1" serviceName="heartBeat">
        <xe:this.methods>
            <xe:remoteMethod name="send">





                <xe:this.script><![CDATA[var db = session.getCurrentDatabase();
var heartView = db.getView("Heartbeats");

var doc:NotesDocument = heartView.getFirstDocument();
var vl = doc.getItemValueString();
if(vl==""){
    doc.replaceItemValue("dummyH","z");
}else{
    doc.replaceItemValue("dummyH",vl+"z");
}
doc.computeWithForm(false, false);
doc.save();]]></xe:this.script>
            </xe:remoteMethod>
        </xe:this.methods></xe:jsonRpcService>

The code of the button is this:

<xp:button value="Label" id="button1">
        <xp:eventHandler event="onclick" submit="false">
            <xp:this.script><![CDATA[setInterval(function(){heartBeat.send()},3000);]]></xp:this.script>
        </xp:eventHandler></xp:button>

It doesnt work. I get no error but i also get no updates in the document... What is wrong in the code?

UPDATE

if i replace rpc script with a simple print("aaaaa") it works perfectly (i also followed the suggestions of Tim in the answer below, for my client side code).

when i use again my previous code i get the following javascript error: Unable to load /Databases/Test/Mike/my1.nsf/RPCpage.xsp/mm?$$viewid=!dqducrahog! status:400

how can i access the database and documents from a remote service?

È stato utile?

Soluzione

The syntax of RPC calls is slightly unusual; your call to heartbeat.send(), for example, does not actually call the remote send method. Rather, it returns a handle on a remote method descriptor... to actually call the remote method, you need to add a callback:

var remoteMethod = heartbeat.send();
remoteMethod.addCallback(function(response){
  // handle whatever came back from the server
});

If, for instance, you designed your remote method to return whether or not the heartbeat was successful, a more complete example would look like this:

var heartbeatInterval = 3000;
var periodicHeartbeat = function() {
  var remoteMethod = heartbeat.send();
  remoteMethod.addCallback(function(response){
    if (response.stillAlive) {
      setTimeout(periodicHeartbeat, heartbeatInterval);
    }
  });
}
setTimeout(periodicHeartbeat, heartbeatInterval);

It's generally recommended to use setTimeout to initially schedule a deferred function, and then call setTimeout again from within that deferred function to schedule its own next execution, instead of using setInterval.

In this use case, however, this is particularly true because each remote method call is asynchronous, so with setInterval, you would eventually end up with request overlap, because each call requires at least a few milliseconds to complete.

Additionally, the preferred pattern of scheduling the next execution from inside the current allows you to check what the server sent back to determine whether to even bother continuing to send subsequent requests. Right now you're not returning any value from your remote method; if you change just the last line to:

return { stillAlive: doc.save() };

...then that JSON object will be automatically passed to your callback function as its first argument. Taking another look at one line from the prior example:

if (response.stillAlive) {

...so the RPC call only reschedules itself if the prior call succeeded. This probably isn't the precise behavior you want, but given that you can return data from the remote method, and the data that was returned is passed to your callback function, you can design a call and response approach that best fits your business specifications for this functionality.

Having said all that, you may want to take a look at the keepAlive component from the XPages Extension Library... it doesn't store heartbeat data in Domino documents, but if all you're trying to do is prevent idle sessions from expiring, it's a much simpler solution.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top