Fixing a wierd widget installation issue (Content is not allowed in prolog)

For our OnTime Group Calendar 2011 Notes user interface which is Java plugin based we have seen some strange problem reports with customers reporting that the widget installs but after installation an error message is displayed on screen (“The widgets below had issues during the installation. See the log for more details.”). The wierd thing about the reports were that the customers reported that the widget (and hence the plugins) actually installed just fine and worked after a client restart. What’s even funnier is that the same plugins installed without error if the customer used HTTP and not NRPC for their update site access protocol. In the log (Help/Support/View Trace) the below error messages was shown (my highlighting):

Could not access digest on the site: no protocol:
   0/8E4DFE3996CBDD94C1257A33003CE3A9/$file/digest.zip
[Fatal Error] :1:1: Content is not allowed in prolog.
org.eclipse.ui.WorkbenchException: Content is not allowed in prolog.
	at org.eclipse.ui.XMLMemento.createReadRoot(Unknown Source)
	at org.eclipse.ui.XMLMemento.createReadRoot(Unknown Source)
	at com.ibm.rcp.dynamic.extensions...
	at com.ibm.rcp.dynamic.extensions...
	at com.ibm.rcp.dynamic.extensions...
	at com.ibm.rcp.toolbox.internal.management...
	at com.ibm.rcp.toolbox.internal.management...
	at com.ibm.rcp.toolbox.internal.management...
	at com.ibm.rcp.toolbox.internal.management...
	at com.ibm.rcp.toolbox.internal.management...
	at org.eclipse.core.internal.jobs...
Caused by:
org.xml.sax.SAXParseException: Content is not allowed in prolog.
	at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
	at org.apache.xerces.jaxp.DocumentBuilderImpl...
	... 11 more

This really had me scratching my head.

After reseaching and Googling I found a post called “Java: “Content is not allowed in prolog” – causes of this XML processing error” which led me in right direction.

When I opened the widget XML file in an editor and switched to HEX mode I saw this:



3 invisible bytes were inserted at the start of the file. I copy/pasted the XML into a new file which solved the issues. The 3 bytes actually turn out to be what’s called a Byte order mark or BOM for short. From the wikipedia article I found out that the BOM for a UTF-8 file is those exact bytes and I did save the file as UTF-8 in my editor.

The UTF-8 representation of the BOM is the byte sequence 0xEF,0xBB,0xBF. A text editor or web browser interpreting the text as ISO-8859-1 or CP1252 will display the characters  for this.

But the bytes were not there in my editor but only in the file that I received from a customer. So how did the bytes get there?!

So after more research and playing around I found out that the BOM is added by Notepad on Windows. But of course!! A lot of customers receive the XML file and change the update site URL to point to their own servers and if they use Notepad for this the BOM is added (see “The Notepad file encoding problem, redux” for more details).

But how to fix it? Telling customers not to use Notepad to edit the XML file would be a no-go as many probably no not use another editor. And even if they did the problem would probably still arise in some situations and we would spend time diagnosing it. The solution I’ve opted for is to change the encoding of the file to ASCII and change the encoding declation in the XML file to ASCII as well. The content of the XML file is unchanged and now customers can change it using Notepad without issues.

Watch the names when doing SSO between WAS and Domino

This morning I helped a customer because they couldn’t make the beta of the OnTime Group Calendar for IBM Connections work and it turned out to be a Single-Sign-On issue. For the OnTime widgets to work we require SSO between Websphere Application Server and Domino which is trivial to set up. Simply export the SSO keys from Websphere using the Integrated Solution Console (ISC) and import them into the SSO document in Domino Directory. In Websphere Application Server terms this is called cross-cell SSO and is very easy to set up.

After doing this SSO still didn’t work and right of the bat I suspected the good ol’ “multiple O= identifier” issue. The issue is when you incorrectly configure federated repositories and a username is reported by ISC with an extra organization identifier e.g. I would be “CN=Mikkel Flindt Heisterberg,o=IntraVision,o=IntraVision” and not simply “CN=Mikkel Flindt Heisterberg,o=IntraVision” the latter of course being correct. While WAS (and IBM Connections) will work just fine with that type of configuration is can cause SSO not to work correctly or only work when the user authenticates to Domino first the problem being that the DN that WAS sticks into the LtpaToken isn’t valid in Domino.

Verifying the names is easy using “Users and Group/Manage Users” in the left hand menu in ISC.

After reconfiguring federated repositories and restarting Websphere Application Server SSO functioned and the customer was back to using the OnTime Group Calendar widgets.

IBM Connections API tip – override Content-Type header

When working with the IBM Connections REST API all responses are returned with the application/atomsvc+xml Content-Type which makes it not show up natively in the browser (or at least in Firefox). A quick solution is the install the Force Content-Type extension and change the Content-Type to text/xml on the fly to make the result show up in the browser. Rules are quick and easy to define.

It’s been quiet around here – what have I been up to?

Well it has been very quiet on my front both on the blogging side and on twitter. I’ve not been lazy but just have had a lot of stuff on my plate the last couple of months. It all started with a very productive trip to Japan and following that AusLUG to catch up with friends and speak at that user group. Businesswise Japan was especially great and we have hooked up with a new OnTime partner out there. Axcel Coporation is our new spearhead into the Japanese market and they are making great progress and already have an ontimesuite.com-like website available in Japanese (ontimesuite.jp) complete with trials, support and online buying all in Japanese. Impressive.

We’ve received a lot of very nice press coverage in Japan with the latest piece coming this weekend where Mr. Muneyuki Ohkawa of IBM Lotus Japan wrote a very nice summary of OnTime Group Calendar and how he sees it in the Japanese market (Japanese: ノーツのグループカレンダー – OnTime Group Calendar, Google Translated into English: OnTime Group Calendar – Group Calendar of Notes).

Besides our Japanese venture I also spent quite a lot of time working on opening up the API for OnTime Group Calendar (more information here). Part of opening up the API has been recording videos on the usage as well as writing samples as well as completing the API Explorer I started writing in a session at BLUG. Don’t say you cannot get inspired everywhere! 🙂 The API Explorer (demo.ontimesuite.com/apiexplorer) is interesting from a number of perspectives. First of all it affords easy access to the API and easily allows you to try out the API without installing it in your own environment. It’s also written as a web application without any hardcoded piece of information. Every endpoint and every operation and argument for the operations are fully dynamic and read from a JSON file allowing up to easily extend and update the API Explorer when we need to. Very nice if I may say so myself.

As if that wasn’t enough I’ve been very busy with the next release of the plugin based UI’s for OnTime Group Calendar programming a sidebar app (Team-At-A-Glance, out in beta currently), adding private group support, adding meeting and allday appointment support to the Notes 2011 UI. I’ve also completed porting the UI’s to use the newer JSON based OnTime API. Oh and of course finalizing the Japanese support in both clients by fully supporting the Imperial Calendar system. It’s all been great fun.

For the next two weeks I’m doing an IBM Connections widget project which I’m looking very much forward to. It is going to be very cool to do some web and JavaScript development and it will give me an opportunity to use my iWidget Test Harness framework which allows me to easily develop and test iWidgets without running a full IBM Connections or Mashup server – oh yeah – wrote that too… 🙂

Now back to work – happy coding!!

IBM still in the lead

I was pleasantly surprised to again see that IDC for the third year running is ranking IBM as the leader for enterprise social software. As a IBM business partner we too are seeing the increased demand for this transformational software although implementation and realization of the potential is oftentimes hard in smaller companies without the budget to drive adoption with community managers or evangelists. It will be interesting to follow this market and see when and if competitors will catch up. For now – good job IBM!!

Controlling the feature install location

When installing plugins (that is Eclipse features) into Lotus Notes and you’re running a roaming environment you kind of have a problem. The problem is that the only part of the plugins that roam are the plugin settings (i.e. should the Sametime come of front on new IMs) but not the actual code for the plugin. That means that when a user roams to a new machine the plugin isn’t installed and hence the user will experience that the plugin will start installing and prompt for a restart. This is because plugins are installed in what’s termed the “user” location (ie. your workspace directory) and not in a shared location.

An alternative is to install the plugins in the “shared” location instead (on my laptop that would mean that features would go into C:Notes8frameworksharedeclipsefeatures instead of C:Notes8dataworkspaceapplicationseclipsefeatures). The “Controlling the feature install location” article from the Lotus Expeditor info center has a nice description on the 3 possible locations.

To do this you use what’s called the colocation affinity of a feature and specify that in the feature.xml describing the feature (the feature.xml can be found inside the jar-file that makes up a feature). To do this you have two options – 1) edit the existing feature.xml and set the “colocation-affinity”-attribute of the top level “feature”-tag or 2) set it using the GUI editor when you build your feature. Option 2 is for those doing their own plugins and option 1 for those changing the colocation affinity for a 3rd party plugin.

Below is a screenshot of setting the colocation affinity to “com.ibm.rcp.site.anchor.shared.feature” driving the feature to the shared location using the GUI editor in Eclipse.

Please note that installing into the shared location require read/write access in the file system for that location.

The easy way to loop an XPage managed bean

I got harassed by Nathan (hmmm his blog appears to be down just now) yesterday for not contributing to the XPages dicussions out there so I thought I’d better remedy that. A quick tip is to make sure your Managed Bean implements Iterable if it contains a list of “things” and the obvious behaviour would be to loop over these things. If you implement Iterable you simple loop on the object using the “new” for-loop (when in Java) instead of first returning a List or array and then looping that with a for- or while loop.

Below is an example of a Managed Bean (just a Java-element from 8.5.3) that implements Iterable and hence it implements the iterator() method. That method should return an Iterator for the data you want to expose. Here I just return an iterator to the underlying list.

package com.example;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.Session;
import lotus.domino.View;

import com.ibm.domino.xsp.module.nsf.NotesContext;

public class PeopleLister implements Iterable {
  // declarations
  private List people = new LinkedList();

  public PeopleLister() {
    NotesContext ctx = NotesContext.getCurrent();
    Session session = ctx.getCurrentSession();
    try {
      Database db = session.getDatabase(null, "names.nsf");
      View view = db.getView("People");
      Document doc = view.getFirstDocument();
      while (null != doc) {
        this.people.add(doc.getItemValue("FullName")
          .elementAt(0).toString());
        Document docTemp = view.getNextDocument(doc);
        doc.recycle();
        doc = docTemp;
      }
    } catch (Throwable t) {

    }
  }

  public Iterator iterator() {
    return this.people.iterator();
  }

  public String toString() {
    StringBuilder b =
      new StringBuilder(this.people.size() * 25);
    for (String p : this) {
      if (b.length() > 0) b.append(',').append(' ');
      b.append(p);
    }
    return b.toString();
  }

  public String[] getList() {
    return (String[]) people
      .toArray(new String[people.size()]);
  }
}

With that in mind I can just use the bean as follows from SSJS code (e.g. a Label):

var people = new com.example.PeopleLister();
var result = "";
for (p in people) {
  if (result.length() > 0) result += ", ";
  result += p;
}
return result;

Happy coding!

http://lekkimworld.com/files/prettyprint/prettify.js

prettyPrint();

Using the IBM Connections API from other languages using custom certificates

I was reading up on some stuff in the IBM Connections REST API during the weekend and came across a post titled Using IBM Connections API in different programming languages on how to use the REST API from other languages than JavaScript from within IBM Connections. The approach there is very nice and quite valid but it fails to mention what to do if the SSL certificate of the API endpoint either isn’t trusted or isn’t certified using a “known” root certificate. In this case “known” means to the Java runtime you’re using or the runtime of any other language for that matter. Here I’m only dealing with Java though.

By default the java.net classes will not allow a SSL connections to a server using a unknown/untrusted certificate but there are ways around that. Of course the best is always to make sure that the certificate of the server may be validated by the Java keystore (including intermediate certificates) but for testing – or if you know what you’re doing – simply ignoring the certificate test can be beneficial. Below is some code showing how to configure the SSL runtime to ignore the certificate and hostname checks. The code is a static configuration method and I deem it pretty readable. The code allows *all* certificates but could pretty easily be locked down to be more restrictive if need be.

private void enableSelfSignedCerts() throws Throwable {
  TrustManager[] trustAllCerts = new TrustManager[] {
    new X509TrustManager() {
      public java.security.cert.X509Certificate[]
        getAcceptedIssuers() {
        return null;
      }
      public void checkClientTrusted(X509Certificate[] certs,
          String authType) {
      }
      public void checkServerTrusted(X509Certificate[] certs,
        String authType) {
      }
    }
 };

 SSLContext sc = SSLContext.getInstance("SSL");
 sc.init(null,
         trustAllCerts,
         new java.security.SecureRandom());
  HttpsURLConnection.
    setDefaultSSLSocketFactory(sc.getSocketFactory());

  // Create all-trusting host name verifier
  HostnameVerifier allHostsValid = new HostnameVerifier() {
    public boolean verify(String hostname,
      SSLSession session) {
      return true;
    }
  };

  // Install the all-trusting host verifier
  HttpsURLConnection
    .setDefaultHostnameVerifier(allHostsValid);
}

http://./files/prettyprint/prettify.js

prettyPrint();