XPages and Bluemix: Pushing out data changes through automated partialRefresh

In this article I will demonstrate how using targeted websockets messages we are able to refresh user data on pertinent screens within an application, and keep user’s data up to date.

Introduction

In previous articles I have discussed the creation of a nodejs websockets service within Bluemix and how we are able to send messages to specific web pages using the socket.io rooms capability. Both of those examples were proofs of concept and the messages were generated in the browser via firebug console commands. We are going to look at how we can automate these messages and begin to build a user case for using websockets within our applications.

Disclaimer: This idea for an example was the brainchild of David Leedy and in many ways it is a genius example to relate websockets to XPages functionality. And at the same time, I am absolutely disgusted that I am even talking about this because I would never dream of actually implementing this within an application. The fact that the page changes without the user’s knowledge is poor, and the fact that it refreshes the entire control when only a small piece of data changes is horrible. All that said however, this is still a demonstration of the capability and in future blog posts on the subject I will actually show example which I would be proud to actually put into one of my own applications 😉

Keeping data up to data on an XPage

Let’s say we have a sample application with a simple XPages viewPanel on it

b1

Somewhere within the application – someone else makes a change to the data

b2

The only way to see the change would be to refresh the page – and you the user would never know when.

b3

This can be pseudo-automated from a user experience perspective in a number of ways but they all involve periodic checking for updates on way or another. If you scale that over many users this is extremely inefficient.

That is where websockets comes in very nicely.

Pushing to specific rooms

In the previous article I demonstrated how to record an XPage as a “room” dynamically and in this example we will do the same thing.

  var temp = (location.href.indexOf('copper.xomino.com')>0) ? "http://localhost:3000" : 'http://xominosocket.mybluemix.net'
  var socket = io.connect(temp)

  // Send message to server that user has joined
  nickname=$('.username').text()
  var xpageName = location.href.split('.nsf/')[1]
  xpageName = xpageName.split('.xsp')[0]
  socket.emit('joinRoom', xpageName, nickname);

Automating a partialRefresh

In a similar manner to listening for a new chat message and then acting upon it, we are going to listen for a “refresh” socket event and then action it. In this case we are also going to pass in the id of the XSP control we want to refresh. For the sake of this example I am also using some CSS to make the element appear momentarily grey (see the video and all will be clear)

  // Function to add a message to the page
  var refreshControl = function(data) {
	  //Get the refreshId from the incoming data and color the control grey
	  //then get the id of the element via the is attribute
	  var temp = $('[id*='+data.refreshId+']').css({background: '#CCCCCC', color: 'white'}).attr('id')
	  //With the known id - trigger a XPages partial refresh of the control
	  XSP.partialRefreshGet(temp, {})
  };

  // When a refresh message is received from the server
  // action it by calling the refreshControl function
  socket.on('refresh', function(data) { refreshControl(data); });

Creating a new listener on the node.js server

I created a new route to post my refresh data to “xpagesRefresh”. When data is POSTed at xpagesRefresh it is parsed and send back out via websockets using the “refresh” socket event.

// Handle the form POST containing the name and , reply with the language
app.post('/xpagesRefresh', cors(corsOptions), function(req, res){
  var request_data = {};

  if (req.body){
    request_data = {
      'refreshId': req.body.refreshId,
      'nickname': req.body.nickname,
      'rt': 'text'
    };
  }

  var data = { refreshId: request_data.refreshId, nickname: request_data.nickname};
  console.log("POSTing at xpagesRrefresh")
  console.log(req.body)

  io.sockets.emit("refresh", data);
  res.send(data);
});

Automating the partial refresh via the user action

In a real application we are not going to have someone sitting on a browser pushing updates via firebug. We want to be able to create the update when the XPage is saved in the first place. To do this we transfer the code we saw in previous firebug blog example into the onComplete of a Save button. In this way when a document is updated within the application. A notification is sent out to all the people looking at the page, updating the data for them.

 

<xp:button value="Save" id="button1" rendered="#{javascript:document1.isEditable()}">
	<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
		save="true" refreshId="blank">
		<xp:this.onComplete>
		<![CDATA[
			var socketServerURL = (location.href.indexOf('copper.xomino.com')>0) ? "http://copper.xomino.com:3000" : 'http://xominosocket.mybluemix.net'

			var data = {
			  refreshId: 'wrapper',
			  nickname: 'automated'
			   };

			  console.log(data)
			  $.ajax({ url:
			          socketServerURL+"/xpagesRefresh",
			      type: "POST",
			      data: data
			  }).done(function( msg ) {
			      console.log( msg);
			  });
			]]>
			</xp:this.onComplete>
	</xp:eventHandler>
	</xp:button>

Demonstration

The video below shows how we are able to trigger a partial refresh after updating a document within the application. Note the screen flickers grey as the CSS change happens before the partial refresh. It is so quick it is almost instant.

Pushing to Bluemix

As before, pushing my new code to Bluemix is as simple as checking it in to the jazz hub repository and redeploying. In the picture below we can see that we are using marky.psclistens.com as the application domain and not copper.xomino.com. As we showed before, if not copper then use Bluemix.

b6

 

We create the capability locally, tested it, proved it and deployed it seamlessly to Bluemix with a “Commit and Push” – and that is *so* cool 🙂

Conclusion
In this article we saw how to trigger core XPages functionality automatically without the user having to interact with the application. In the next article we will look at how to improve on this, frankly horrible, user experience.

Thanks Dave 🙂

Advertisement

4 thoughts on “XPages and Bluemix: Pushing out data changes through automated partialRefresh

    • Petter – thanks for the feedback 🙂

      Yes I am well aware of the project and have talked to Mark Ambler extensively about it. I was originally going to do a series like this using Mark’s plugin but projects and vearious other things sidetracked me. I did not intentionally shy away from Mark’s project at all. It just so happened that when I started to look at Bluemix, it also struck me as an opportunity to learn more about node……aaaaand websockets seemed like a great place to start as it was on my “list of things to do”.

      Absolutely Mark’s plugin works very nicely within the construct of Domino. To create a message you just create a notes document with the payload you want sending and it takes care of it for you – very cool.

      As you may have noticed I have been rather vocal about my desire to have a websockets capability within Domino over the last two years – out of the box would be ideal !! 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s