Java Maps and load factors

When writing Java code be that for standalone Java, Domino agents or even XPages you often need a data structure to map keys to values. In Java this is a map (java.util.Map) and it works much like a List in LotusScript. Maps are used a lot but since Map is an interface you need an implementation whih is most often a java.util.HashMap.

The way to construct a HashMap is using one of the constructors and if you are like me a couple of months ago you just use the default constructor that is the one that doesn’t take any arguments. Now this is well and fine if you know what you’re doing. Most times the use of the default constructor is the wrong choice and can / will lead to memory being wasted and even worse is worse performance when adding more than 12 elements.

Lets take each in turn. The wasted memory comes from the classes used internally inside a HashMap to keep track of keys and values. For this post knowing that not filling the map (e.g. creating a HashMap using the default constructor and only stuffing 5 elements in it) will waste memory. A most excellent introduction is From Java Code to Java Heap. On a related note a key take-away from that article is to consider LinkedList instead of ArrayList if you not know the ultimate number of elements and hence cannot size correctly at object construction.

This memory waste can be avoided by always using the constructor that takes an initial size and hence size the Map correctly. Now it turns out that that’s only part of the story as a HashMap also has what’s called a “load factor”. The load factor is a decimal number – i.e. a percentage – specifying how much the map may be filled before an extension and hence a full rehash of the keys take place. This means that with the default load factor of 0.75 you may only put 12 elements in a HashMap before it is extended and hence you take a performance hit. Again size your map correctly from the get go taking the load factor into consideration. The last point is that the size should always a power of 2 meaning that if you specify a size of 20 it will actually be 32.

A most nice discussion that caused me to look deeper into this can be hear on episode 391 of the Java Posse podcast (Java Posse #391 – Newscast for August 10th 2012) from 0:58 to 1:05.

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!

https://lekkimworld.files.wordpress.com/prettyprint/prettify.js

prettyPrint();

The XPages Portable Command Guide and why it’s important


I was among the people who was fortunate enough be be sent a review copy of the new “XPages Portable Command Guide” book that has just been published. While this review has been a long time in the making I wanted to get it out there never the less. You should first read the review Tim Tripcony wrote (“XPages Portable Command Guide is a book every Domino administrator should read“) as it is spot on and very good and accurate. The thing about XPages that many developers and administrators forget – or simply doesn’t know – is that it is running on a completely rewritten HTTP stack on the Domino server. It was even refactored recently to be based on OSGi technology to make it even better and more easily extensible. The XPages runtime is more like a traditional J2EE server (like Websphere Application Server) than a traditional Domino server. This means that the runtime is very configurable but out of the box it is configured to be a jack of all trades. You can change it though and you probably should if you run business critical applications of it.

For me the most important part of the book is the part about the xsp.properties file that is the main configuration file for the XPages runtime. The file is central to how an XPages application function and it’s crucial that it is configured and tuned correctly for the needs of the application. While having to do this kind of configuration by hand is prone to errors and that IBM really should provide better tooling for it doesn’t change its central role for XPages. It is therefore very important that you as a developer or administrator know how to edit it. For the developer you need to be able to configure the application so it functions at peak efficiency and as an administrator you need to know enough to throttle your developers to not configuration the applications to as to note starve one another for resources.

The important part about XPages is that where many of the settings for traditional Domino web applications are server settings many, if not all, of the xsp.properties settings can be thought as of deployment settings as well as server settings. As Tim writes – “There are plenty of settings that can be defined in this file that only the developer should care about, but many of them you don’t want the developer to decide. Trust me, if you leave it to me, I’m typically going to max out the RAM consumption in an attempt to provide lightning fast response times. But it’s your server. You should be overriding me on that decision… as long as it’s still in keeping with the end users’ business needs, of course.”

So if you do any work with XPages I therefore highly recommend you get a copy of this book. Get it as an e-book though as it’s a reference and IMHO a paper copy doesn’t make any sense. Most of the API calls you can also find good documentation on online but the xsp.properties part is lacking online and it’s critical to know about and understand if you want to get the maximum from the XPages runtime.

The Java native2ascii tool (also important for you XPages geeks)

To prepare for our upcoming trip to Tokyo I’ve been working on a Japanese translation of our OnTime Group Calendar 2011 client for Notes based on Java plugins. The internationalization engine (i18n) was already in place so it was merely a matter of doing the translation (thanks to Google Translate and friends) and then adding language files to our API. In that process one becomes very thankful of UTF-8 and the fact that Java works natively in UTF-8.

Please note that the approach discussed in this post translates (excuse the pun) directly to making translation files for XPages as well.

Using the Japanese translation the GUI looks like the below screen shot (cropped of course).



(click the image for a large version)

The funny thing about most non-Latin languages is that even though you have the translations it’s hard to impossible to write the characters yourself. And once you have the words getting them into the language files which are mere property files. Take the weekdays in Japanese as an example:

月曜日
火曜日
水曜日
木曜日
金曜日
土曜日
日曜日

Because we’re running the OnTime Group Calendar out of Notes and because Notes is fully double-byte compatible we could actually just add the Japanese characters directly to the translation document. Instead however we opted to use the Java way that is the native2ascii tool.

The native2ascii tool is shipped with the JDK and lets you translate a file containing native characters to their UTF-8 equivalent escape sequences. So having my Japanese characters in japanese_source.txt and wanting to store the result in japanese_result.txt I simply ran the following command:

native2ascii -encoding UTF8 japanese_source.txt japanese_result.txt

The encoding parameter specifies the character encoding of the source file (here japanese_source.txt). The result is something like this:

u6708u66dcu65e5
u706bu66dcu65e5
u6c34u66dcu65e5
u6728u66dcu65e5
u91d1u66dcu65e5
u571fu66dcu65e5
u65e5u66dcu65e5

Chose escape sequences go directly into the language property file and when read into a Java property file they are automatically translated into Japanese. Sweet!

I will be giving two sessions at DNUG in November

As mentioned previously I’ll be speaking at DNUG in November in Bamberg in Germany where I will be giving my “jumpstart your plugin development”-session about all the plugin development goodness. Besides that I’m also going to join forces with Rene Winkelmeyer (of among other things File Navigator fame) in a two hour session on XPages Extensibility Library titled “XPages Extensibility under the hood”. One hour on the basics and a full hour hands-on labs. Hope to see many of you there.

A (dojo.)mixin configuration approach to XAgents in XPages

Continuing my XPages theme from yesterday I also wrote an XAgent base-class in JavaScript to make XAgents easier to do. Part of the base class is that it allows me to pass in a JSON object to configure the XAgent based on the need. Since the information I pass in should override the built-in defaults I needed a way to easily allow the user supplied values to override the defaults. The easiest way to do this would be to use the dojo.mixin.

"dojo.mixin is a simple utility function for mixing objects
together. Mixin combines two objects from right to left,
overwriting the left-most object, and returning the newly
mixed object for use."

Unfortunately Dojo isn’t available in SSJS I needed to do it myself. To my luck it was surprisingly easy as the below code illustrates.

// create function to allow mixin' two objects
var mixin = function(target, source) {
   if (!source) return;
      var name, s, i;
      for (name in source) {
      s = source[name];
      if (!(name in target) || (target[name] !== s)) {
         target[name] = s;
      }
   }
};

My XAgent base class looks something like this:

function XAGENT(args) {
   // create mixin function
   var mixin = function(target, source) {
      if (!source) return;
         var name, s, i;
         for (name in source) {
         s = source[name];
         if (!(name in target) || (target[name] !== s)) {
            target[name] = s;
         }
      }
   };

   // define default arguments
   this._args = {
      download: false,
      filename: "default.json",
      charset: "iso-8859-1",
      contentType: "application/json"
   };

   // mixin user-supplies arguments
   mixin(this._args, args);
};
XAGENT.prototype.run = function(command) {
   ...
};

What’s super neat is that now, in my run-method I can access the this._args object and all values that the user supplied have overridden the default values because we used the mixin-function. Very cool and an easy and flexible way to have default values but allowing them to be overridden by the caller. Also you know that the variables you need have been defined so no checks are necessary.

Calling my XAgent class is very easy allowing me to override the defaults. The run-method accepts a function which is called when the XAgent stuff has been set up supplying the Writer and the parameters supplied in the URL as a JSON object.

var xa = new XAGENT({
   filename: "feed.json",
   download: true
});
xa.run(function(w, params) {
   ...
});