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();

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();

Joda Time comment

Ulrich Krause has an interesting post (Joda to the rescue) and I just had to comment on as I – probably to no surprise to many – work a lot with dates for the OnTime Suite. Ulrich is using the Joda Time library to compare two dates to see if they are on the same day by first stripping the time component which isn’t easily possible using java.util.Date. My comment is to remember that the Java Date object is just a wrapper about a UTC long so math can do the trick. Below is my comment.

While Joda Time is a great library there is an easier way to accomplish what you are trying to do. Simply remove the time component by doing a simple modulus calculation. I am not trying to be smart about it but we do this quite a lot at OnTime 🙂 Code could look like so:

Date d = new Date();
long lngTime = d.getTime();
lngTime -= lngTime % TimeUnit.DAYS.toMillis(1);
Date dNoTime = new Date(lngTime);

The latter date object creation isn’t actually necessary for the comparison. An utility function could be like so:

private boolean isSameDay(Date d1, Date d2) {
  long lngTime1 = d1.getTime();
  lngTime1 -= lngTime1 % TimeUnit.DAYS.toMillis(1);

  long lngTime2 = d2.getTime();
  lngTime2 -= lngTime2 % TimeUnit.DAYS.toMillis(1);

  return lngTime1 == lngTime2;
}

Hope it helps and it helps remove the dependency on Joda Time if that’s all you’re using it for.

Authenticating a web service request

In my current project I needed to place an authenticated web services request from Lotus Domino to an Oracle SOA endpoint. Turned out to be extremely easy using the Lotus Domino web services consumer feature as I just used the setCredentials(String, String) method which then adds the necessary Authorization header to the HTTP call. Below is an example.

MyEchoServiceLocator l = new MyEchoServiceLocator();
MyEcho u = l.getDomino();
u.setCredentials("Domino Admin", "password");
String result = u.echo("HelloWorld");
System.out.println("Result: " + result);

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!

SOAP Headers in Lotus Domino web service consumers and providers

In a current project we’re using the web service consumer and web server provider capability of Lotus Domino quite heavily. During the development the need to process the SOAP request headers which are provided in a section above the SOAP body. Problem is that these are not exposed through the proxy classes generated for you when you import the WSDL. Searching Google I came across the blog of Elena Neroslavskaya and more importantly the post that helped me out. Using the MessageContext class described in that blog post helped me crack the nut and now I can both iterate through the SOAP headers sent to me in the request and send SOAP headers back in the response. Sweet!

Below are two code snippets – one for iterating through request headers and one for sending headers back. Home it may help someone out there.

Iterate received headers

private void recurseHeaders(Iterator ite) {
  while (ite.hasNext()) {
    MessageElement elem = (MessageElement)ite.next();
    String nsUri = elem.getNamespaceURI();
    String name = elem.getName();
    String value = elem.getValue();
    System.out.println("SOAP Header - ns , name , value ");
    this.recurseHeaders(elem.getChildElements());
  }
}

public com.example.FooResponseType foo(
  com.example.FooRequestType req) throws Exception {

  MessageContext mc = MessageContext.getCurrentContext();
  SOAPEnvelope envelope = mc.getRequestMessage()
    .getSOAPEnvelope();
  this.recurseHeaders(
    envelope.getHeader().getChildElements());
}

Send back headers

import lotus.domino.axis.message.SOAPHeaderElement;
import lotus.domino.axis.message.MessageElement;

MessageElement elemGuid =
  new MessageElement("http://lekkimworld.com", "Guid");
elemGuid.addTextNode("GuidXYZ");

MessageElement elemUser =
  new MessageElement("http://lekkimworld.com", "User");
elemUser.addTextNode("UserXYZ");

SOAPHeaderElement elemHeader =
  new SOAPHeaderElement("http://lekkimworld.com", "TopElem");
elemHeader.addChild(elemGuid);
elemHeader.addChild(elemUser);

mc.getResponseMessage()
  .getSOAPEnvelope().addHeader(elemHeader);

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

prettyPrint();