Question

I am trying to use the extension library component Remote Service (xe:jsonRpcService). I got some hints from here and here. Basically I am trying to save a document using RPC. The problem is that the document gets saved but it does not save any fields present on the XPage. Below is the sample XPage code:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
    <xp:this.data>
        <xp:dominoDocument var="document1" formName="Test"></xp:dominoDocument>
    </xp:this.data>
    <xe:jsonRpcService id="jsonRpcService1" serviceName="service">
        <xe:this.methods>
            <xe:remoteMethod name="saveDoc">
                <xe:this.script><![CDATA[print(">> " + getComponent("inputText1").getValue());
document1.save();
return true;]]></xe:this.script>
            </xe:remoteMethod>
        </xe:this.methods>
    </xe:jsonRpcService>
    <xp:br></xp:br>
    <xp:inputText id="inputText1" defaultValue="testValue" value="#{document1.testField}"></xp:inputText>
    <xp:br></xp:br>
    <xp:button value="Save" id="button1">
        <xp:eventHandler event="onclick" submit="false">
            <xp:this.script><![CDATA[var deferred = service.saveDoc();
deferred.addCallback(
    function(result) {
        alert(result);
    }
);]]></xp:this.script>
        </xp:eventHandler>
    </xp:button>
</xp:view>

What I have done here is that, I created Remote Service (service) where I am saving the current document (document1). It saves the document but does not save the value in inputText1. Also, when I try to print the value of inputText1 it shows on console but it is not getting saved.

Is this the right way to do it? Or am I missing something here. Also what would be some scenarios where usage of xe:jsonRpcService would be justified?

Was it helpful?

Solution

There are (at least) two reasons for avoiding the use of a JSON-RPC for this type of operation:

  1. This service component is designed to be as lightweight as possible, so, unlike standard events in XPages (which automatically post the entire HTML form), it sends only the data required to call the method, and receives only the data returned by the method. In your example, the method takes no arguments, so it's literally just sending enough information for the server to know what method to call; similarly, you're just returning a boolean value, so that's literally all that will be sent back. If you use your browser's development tools (i.e. Firebug or the built-in tools in Chrome) to inspect the network traffic, you'll see this reflected in the JSON packets that are sent in each direction. As a result, the server doesn't "know" anything that you don't explicitly "tell" it. So it's faster than a typical event because you're not posting anything that isn't explicitly related to the method you're calling... but you have to intentionally send everything that the method does need in order to run.
  2. Another side effect of the component's focus on performance is that it skips the component tree serialization at the end of the JSF lifecycle. If you're keeping the current page in memory, that shouldn't be an issue, but if you're using the default option (save all pages to disk), the server will "forget" any changes that are made to the page during the method invocation. You can explicitly override this behavior on a case-by-case basis by directly telling the view root to serialize its state, but it's easy to forget that you have to do this manually, which typically causes a lot of frustration when you see indications server-side that it's doing what it's supposed to but the actual web page doesn't reflect that. It's best to just treat any RPC method as a "read-only" operation unless you're certain you'll always remember this odd side effect and understand how to circumvent it.

My advice is to think of JSON-RPC as "SOAP minus the stupid". Phrased more politely, it's conceptually identical to Web Services, but without all the complexity of Web Services. As such, these types of services are ideal for data operations that are useful within the context of the current page without being explicitly tied to the state of the current page.

Here are some examples of operations where a JSON-RPC method might be useful:

  • Informing a new user whether the user name they're choosing for their new account is already taken. Instead of binding a standard keyup event which would post the entire form, send only the value of the one field to the service, query it against the site registration records, and send back a boolean.
  • Live polling of related data that is prone to frequent updates. Suppose you're developing a CRM, and you want to display the stock price of the company whose account you're viewing. Using setInterval to periodically ask the RPC for the updated stock price, then doing manual client-side DOM manipulation if the price changes, again allows you to perform a somewhat complex operation with a minimum of network overhead.

This doesn't mean that you can't use an RPC for write operations... but for any operation that needs a complete, up-to-date context (i.e. current value of every field on the current page) to run correctly, a standard event handler is nearly always the better approach.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top