RESTless getting data from XPages to IBM Connections and back again

Recently I was working on getting data from IBM Connections in and out of an XPages application using the IBM Connections API. The API was great to work with: it is pretty good documented and easy to understand. It uses Atom feeds and RESTful calls to communicate.

I needed to implement the data read/write ‘barebones style’. No HTTPClient and no Abdera. Don’t ask me why. but it’s not because I like to torture myself. In the beginning that actually worked quite well: I was able to implement and parse the GET, PUT and DELETE calls without any big problems.

Until… I tried to create a File in Connection. According to the API this can be done in two ways: either by sending multipart form-data (including the encoded file) or just the file using a POST request. Since the multipart form-data option returns a JSON object (and everywhere else I worked with XML/ Atom), I went with the option to just post the file.

To test my calls and the API I was using the Dev HTTP Client Chrome plugin (which I can highly recommend!). Using that I could simulate the request: make a POST to the correct Files URL, select a file and of we go. Response code: 201. All fine.

I then tried the same in SSJS: create a HTTPUrlConnection, set the method to POST and write the file to an output stream. Response code: 503 (“service unavailable”). No matter what I did.

So I searched. And searched. And tested. And couldn’t figure out why it failed. Until I had a bright moment: check what actually’s being sent (headers and body) and compare it with the output of the Dev HTTP Client. For the plugin that was easy: F12 in Chrome and you’ll have all the information you need. For the server-to-server call it was more difficult. I ended up installing Wireshark to inspect the network traffic.

After I found the POST request (in the enermous amount of data Wireshark generates) I noticed something strange and was sure I didn’t add: a Content-Type header with the value application/x-www-form-urlencoded. That is obviously wrong: I’m sending a binary file. It shouldn’t add that header. There was a bug in Java that describes the same behaviour, but that was supposed to be fixed in a later 1.5 version. I (now) know that the Java 1.6 version in Domino is not Oracle’s one so might that explain why this issue (or is it a feature?) still exists.

The solution was easy: override that header with the correct one. I used the URLConnection.guessContentTypeFromName() function (yes, that really exist) and added the header. Response: 201. Every time. Happy Mark and client.

Send a serverside redirect to a new window

Redirecting a user on an XPage server side can be done by calling one of the context.redirectTo() methods or by using the facesContext.getExternalContext().redirect() method. But what if you want to open that page in a new window/ tab?

The only way to open a link (AFAIK) in a new window/tab is by making a clientside JavaScript”) call. There are a couple of ways to send that call to the browser (using the onComplete event or a conditionally rendered outputScript control), but the XPages engine also has a little known method called view.postScript(“”). Anything you add there is send to the browser upon completing the eventhandler as clientside script.

Using that, opening the result of an eventhandler in a new window/ tab can then be accomplished by writing:

<xp:link escape="true" text="Start" id="link2">
  <xp:eventHandler event="onclick" submit="true"
    refreshMode="partial" refreshId="link2">
      //execute server side code here to determine a target url
      var target = "";
      view.postScript("'" + target + "')");}]]>

Showing real progress in XPages

One of the actions in an XPage application I’m building might take some while to complete. The action is triggered by a button so I added a loading indicator image that is shown on the button’s onStart event and hidden in the onComplete event. The problem with this was that it gives me no clue as to how long it will take and if it’s making any progress at all. So I searched for a way to display a real progress bar.

I investigated a solution involving a partial refresh of a part of the page while another partial refresh is running. This seemed a no-go: the 2nd partial refresh will not start/ complete until the first is finished. I also looked into threads and Eclipse jobs: but found that too complex for just a simple progressbar.

The solution I came up with includes a couple of components. In the (long-running) code I store the current progress (a number from 1 to 100) in a variable in the sessionScope. When the long-running code is started I use the onStart event to call a client-side function that uses the JavaScript setInterval() function to periodically call another XPage using a dojo.xhrGet(). That second XPage (getProgress.xsp) has only one purpose: it returns the progress from the variable in the sessionScope as JSON to the browser. This progress is then used to display a dijit.ProgressBar() with the updated progress. In the onComplete event of the long-running eventHandler I cancel the periodic checking.

Enough talk: demo or it didn’t happen.

You can download the demo database here. As far as I know the code will only work on 8.5.3. The demo page uses the built-in Dojo Claro theme. Oh,  and the messages are optional!