Thursday, March 21, 2013

Lotus Notes 9 final is available in passport advantage

I am so excited that Lotus Notes 9 is available. Now i am downloading the code and will post what has changed since the public beta later today.



The product codes for the most important downloads are:

IBM Notes, Domino Designer and Admin V9.0 for Windows XP,Vista and Windows 7 32 Bit English(CIB9AEN)

IBM Notes Client V9.0 for Windows English(CIB8LEN)

IBM Notes Client V9.0 for Mac English(CIB8PEN)

IBM Notes Client V9.0 for Linux (RPM Install) English(CIB8MEN)

IBM Notes Client V9.0 for Linux (Debian Install) English(CIB8NEN)

IBM Notes Traveler V9.0 for Windows Multilingual(CIB95ML)

IBM Domino Sever V9.0 64 bit for Windows English(CIBM1EN)

IBM Domino Sever V9.0 32 Bit for Windows English(CIBM0EN) 





Monday, March 18, 2013

Very cool! Conditional breakpoints in the SSJS Debugger

I blogged about the new SSJS Debugger in Designer 9 and how to use it to find bugs in your java script code some weeks ago. And today i want do show you how to use conditional breakpoints in the new debugger.

Every developer knows that it is very annoying when you have a problem in a loop which occurs only in a particular iteration. So you have to step through the loop many times only to get to the faulty iteration. And when you click step over one time to often you can start from the beginning. Look at the following example:

var view=session.getCurrentDatabase().getView("Employees");
var doc=view.getFirstDocument();
var money=0;
while(doc!=null){
 money=money+100/doc.getItemValueDouble("value");
 doc=view.getNextDocument(doc);
}
getComponent("result").setValue(money);

We are looping through a view and make a litte calculation. When we run this example we get a value of "inifinty". So we are pretty sure that on one iteration there is a Division by zero. But the big question is which document contains the zero value? So we can step through the whole loop to find the doc which contains a zero vale or define a conditional breakpoint.

1. Go to the source tab of your xPage.
2. Left click the breakpoint area left of the line numbers to define a breakpoint.
3. Right click the new breakpoint and select "Breakpoint Properties"

4. Define the condition when your breakpoint should stop the script execution



After the condition is set the SSJS Debugger will stop the script execution every time the code where the break point is defined is executed and the condition is true. In our example stops the execution when doc.getItemValueDouble("value") is 0. When the Execution stops you can find out with the expressions view which document is causing the error. For example you can get with doc.getUniversalID() the UNID from the document with the 0 value.

Condtional breakpoints are a very valuable tool to find bugs in complex SSJS code.

Reference to all my posts about the SSJS Debugger

Saturday, March 16, 2013

How to activate and use the expressions view in the SSJS debugger

The "expressions" view in the java debugger is one of the most valuable tool for debugging java code. With this view you can deeply inspect the values of all objects you are using in your code at runtime and you can even run methods on this object to get values not visible in the standard "variables" view. For example when you have a document object you can invoke getItemValueString on this object to get the value of a field from the document. Knowing this you will understand my disappointment when i first try the SSJS Debugger in Desinger 9, because it looks like there is no expression view in the java script debugger. But fortunately the view is only hidden and can be activated in Designer 9.

Go to the "Window->Show Eclipse View" menu and activate the "expressions" view.
After that we can use the expressions view to analyze the state of all objects available in our code when the execution is stopped at a breakpoint in the debugger.

For example we have the following serverside java script code in our xPage.

 
var view=session.getCurrentDatabase().getView("Employees");
var doc=view.getFirstDocument();
var money=0;
while(doc!=null){
 money=money+100/doc.getItemValueDouble("value");
 doc=view.getNextDocument(doc);
}
getComponent("result").setValue(money);

The following screenshot shows what is possible with the expressions view in SSJS Debugger at a brekpoint inside the loop.

You can access every field from the doc Object with getItemValueString() or every java script variable. You can get every information from the session, for example the effective username running this script. From the session you can acces databases and from the databases you cann acess views and so on and on. The possibilitys are endless.

To add, change or remove expressions in the expression view simply right click the view and select the appropriate menu action. Or use the actions in the toolbar. When you hove over a toolbar icon you get a simple description of the action.

So i hope IBM will activate the expressions view by default in future service packs of Designer 9 so that every xPage developer knows about this great tool. A right click Option "Watch this expression" in the source editor would be nice too.

Reference to all my posts about the SSJS Debugger

Tuesday, March 12, 2013

IBM announces general availability of Domino 9 on March 21th

The wait is over. IBM has announced the GA of Domino for delivery on March 21th 2013. I am really looking forward to test the final release of Domino and Notes Social Editon.

Tuesday, March 5, 2013

Messen der Netzwerklatenz bei TCP/IP Verbindungen

Bei Client Server Anwendungen wie z.B. Lotus Notes spielt nicht nur die Bandbreite sondern auch die Netzwerklatenz der Verbindung eine große Rolle. Unter Netzwerklatenz versteht man die Zeit die es braucht bis auf eine Anfrage eine Antwort vom Server zurückkommt. Wenn man weiß, dass Lotus Notes beim Öffnen eines Dokuments sämtliche Abfragen, wie DBLookups und ähnliches synchron hintereinander durchführt, spielt es schon eine große Rolle, ob jeder Netzwerkzugriff unter 1 Millisekunde oder eher im 100 Millisekundenbereich dauert. Dazu ein Beispiel: Das Öffnen von einem Notes Dokument benötigt 15 NRPC Aufrufe. Wenn nun die Netzwerklatenz 1 ms beträgt, dann ist der Overhead durch das Netzwerk nur 15 Millisekunden. Wenn man aber über einen WAN Link mit langsamer Latenz (ca. 100 ms)  arbeitet, dann ist der Overhead durch die Netzwerklatenz schon 1,5 Sekunden. Damit sollte klar sein, warum Notes ohne lokalen Repliken so bescheiden über WAN Links funktioniert.

Wie kann man nun aber die Netzwerklatenz messen. Eine ganz rudimentäre Möglichkeit bietet der Befehl "PING" den alle Betriebssysteme bereits mitbringen. Aber ping hat den Nachteil, dass es erstens nur kleine ICMP Pakete zum Messen verschickt, die unter Umständen wesentlich besser performen als große Datenpakete wie sie in Anwendungen normalerweise auftreten. Weiters kann es die Latenz nur mit einer Auflösung von 1 ms angeben.

Doch es gibt ein Ping Tool von Microsoft (Sysinternals), dass alle diese Probleme lösen kann.

Nach dem Entpacken des Download kopiert man den "PSPING.EXE" Befehl einmal auf den Client und einmal auf den Server zwischen denen man die Latenz messen will. Danach startet man auf dem Server PSPING im Sever Modus.

psping -s x.x.x.x:y

x.x.x.x ist dabei die Adresse der Netzwerkschnittstelle im Server z.B. 10.0.0.15.
y ist die Portnummer auf der PSPING auf eingehende Anfragen antworten soll.

Natürlich muss man auf dem Server auch noch den gewählten Port auf der  Windows Firewall freigeben, oder die Windows Firewall während der Messung deaktivieren.

Auf dem Client kann man dann die Messung mit folgenden Befehl starten.

psping -l 4096 -n 500 -h 20 x.x.x.x:y


Der Befehl sendet 500 4k große Datenpakete an den Server x.x.x.x:y und misst die Latenzzeit. Nach Abschluss der Messung gibt er dann die geringste, die durchschnittliche und die maximale Latenz aus. Weiters erstellt er eine Verteilung der einzelnen Messungen. Die Anzahl der Verteilungen wird über den Paramter -h gesteuert.

Hier ein Beispiel für eine schnelle LAN Verbindung:

TCP latency test connecting to x.x.x.x:y: Connected
505 iterations (warmup 5) sending 4096 bytes latency test: 100%

TCP roundtrip latency statistics (post warmup):
  Sent = 500, Size = 4096, Total Bytes: 2048000,
  Minimum = 0.26ms, Maxiumum = 7.41ms, Average = 0.34ms

Latency Count
0.26    496
0.63    2
1.01    0
1.39    1
1.76    0
2.14    0
2.51    0
2.89    0
3.27    0
3.64    0
4.02    0
4.40    0
4.77    0
5.15    0
5.52    0
5.90    0
6.28    0
6.65    0
7.03    1
7.41    0


 und das selbe über ein WAN Link:
 
TCP latency test connecting to x.x.x.x:y: Connected
505 iterations (warmup 5) sending 4096 bytes latency test: 100%

TCP roundtrip latency statistics (post warmup):
  Sent = 500, Size = 4096, Total Bytes: 2048000,
  Minimum = 42.39ms, Maxiumum = 445.09ms, Average = 50.24ms

Latency Count
42.39   457
63.59   37
84.78   2
105.98  0
127.17  0
148.36  0
169.56  0
190.75  0
211.95  0
233.14  0
254.34  0
275.53  0
296.73  2
317.92  0
339.12  0
360.31  0
381.51  0
402.70  1
423.90  1
445.09  0


Vor allem wenn man bei seinem WAN Link sehr viele Ausreißer nach oben hat, sollte man unbedingt an seinem Netzwerk arbeiten. z.B. Quality of Service einführen. Nach den Tuningmassnahmen kann man dann wieder bequem mit PSPING prüfen, ob die Massnahmen auch etwas gebracht haben.







Sunday, March 3, 2013

Erste Schritte mit der Rest API von Lotus Domino

Im letzten Post habe ich gezeigt, wie einfach es ist die REST Api für einen Domino Server zu aktivieren. Jetzt möchte ich zeigen wie man die API ohne ein Programm zu schreiben testen kann und erste Erfahrungen mit der Syntax der RESTurls gewinnen kann.

Dafür erscheint mir die RESTClient Extension für den Firefox am besten geeignet. Diese Extension kann auf Knopfdruck zum Firefox hinzugefügt. werden.


Nach einem Neustart des Firefox ist der RESTClient im Browser verfügbar. Der Knopf für den RestClient befindet sich ganz rechts in der Adresszeile.


In der UI des RESTClient kann man dann seine Zugriffsmethode, die URL und bei Bedarf auch Daten im Body mitschicken.



Wie sehen nun aber die URLs für den Zugriff auf Domino Daten aus. Hier ein paar Beispiele:

Erstellen einer Liste sämtlicher Datenbanken auf dem Domino Server:

http://localhost:80/api/data

Zugriff auf den Inhalt einer View:

http://localhost:80/test.nsf/api/data/collections/name/Adressen

test.nsf ist der Datenbankname und Adressen der Ansichtsname der zurückgegeben werden soll.

Zugriff auf ein Dokument mit einer bestimmten UNID:

http://localhost:80/test.nsf/api/data/documents/unid/9721E84AF9E25C4AC1257AE200598E50

Nach dem man im RESTClient dann auf den "SEND" Knopf gedrückt hat, werden einem die Ergebnisse der Abfrage unten angezeigt. Im Reiter "Response Headers" sieht man die HTTP Headers. Im Response Body sieht man das zurückgegebene JSON Dokument, dass die angeforderten Daten enthält. Hier ein kleines Notesdokument mit 2 Feldern:
{
    "@href":"http:\/\/localhost:80\/test.nsf\/api\/data\/documents\/unid\/9721E84AF9E25C4AC1257AE200598E50",
    "@unid":"9721E84AF9E25C4AC1257AE200598E50",
    "@noteid":"8F6",
    "@created":"2012-12-28T16:18:11Z",
    "@modified":"2012-12-28T16:18:27Z",
    "@authors":"CN=Ralf M Petter\/O=Demo",
    "@form":"Test",
    "Name1":"Ralf",
    "Name2":"Petter"
}

Natürlich kann das REST Api des Domino Servers noch viel mehr und jede URL bietet auch noch diverse Parameter um das Ergebnis zu beeinflussen. Einen guten Überblick über die Möglichkeiten, bekommt man in der REST Referenz im IBM Developer Wiki.

Das REST Api hat meiner Meinung nach enormes Potential für Anwendungen die nur lose an Domino angekoppelt werden sollen und der RESTClient im Firefox ist ein Super Werkzeug um seine ersten Schritte in diesem neuen Umfeld zu machen.

Aktivieren des REST Api der Domino Data Services am Server

Seit 8.5.3 Upgrade Pack 1 gibt es mit dem Domino Data Services eine neue Methode um auf die Daten eines Lotus IBM Domino Server zuzugreifen. Ein Teil dieser Domino Data Services ist ein REST Api mit dem man Daten aus Domino Datenbanken über eine einfache URL als JSON Objekte zurückbekommt. Dies sieht wirklich nach einer sehr viel versprechenden Technologie aus, da man in einem Clientprogramm egal ob es sich jetzt um einen Rich client, einen Webclient oder einen Mobilen Client keine Librarys wie notes.jar installieren muss, um auf Daten von Domino Servern zugreifen zu können.

Die Voraussetzungen für die Verwendung der Domino Data Services sind ein installiertes Upgrade Pack 1 auf 8.5.3 oder natürlich noch besser ein Domino 9 Server. Ich habe alle meine Tests mit einem 9er Server durchgeführt. Die Domino Data Services sind standardmäßig nicht aktiviert und müssen über den Admninistrator freigeschalten werden.

Konfiguration ohne Internet Site Dokument

Im Server Dokument im Tab "Internet Protocols/Domino Web Engine" befindet sich ganz unten der Punkt "Domino Access Services" Bei dem Feld "Enabled Services" muss der Punkt "Data angehakt werden. Danach muss man mit "tell nhttp quit" und "load nhttp" den Http Task von Domino durchstarten und die Data Services sollten funktionieren.



Konfiguration mit Internet Site Dokument

In dem Internet Site Dokument befindet sich die Einstellung für die Domino Data Services auf dem Tab "Configuration". Bei dem Feld "Enabled Services" muss der Punkt "Data angehakt werden. Danach muss man mit "tell nhttp quit" und "load nhttp" den Http Task von Domino durchstarten und die Data Services sollten funktionieren.

Nach der Konfiguration des Servers kann man schon verschiedene Informationen wie z.b. eine Übersicht aller Datenbanken auslesen. Um aber Daten aus einzelnen Datenbanken abrufen zu könnenn müssen diese Datenbanken noch für die Verwendung von Domino Data Services konfiguriert werden. Dazu muss man in den Datenbankeinstellungen unter Erweitert ganz unten den Zugriff erlauben. Man hat dabei die Auswahl ob man nur den Zugriff auf Ansichten, oder auch den Zugriff auf Dokumente erlauben will.
Falls man diese Einstellung nicht setzt erhält man beim Zugriff die Meldung "The Domino data service is not enabled for this database"

Zusätzlich zu der generellen Erlaubnis des Zugriffs auf die Datenbank muss dann auch noch bei jeder View bzw. Folder auf den man mittels REST Api zugreifen will der Zugriff mittels den Domino Data Services freigeschalten werden. Der Punkt befindet sich wieder in den erweiterten Einstellungen der Ansicht oder des Ordners.


Falls die Ansicht nicht freigeschalten wurde, bekommt man die Fehlermeldung "The Domino data service is not enabled for this view" beim Zugriff auf die Ansicht.


Im nächsten Post möchte ich dann zeigen wie einfach es ist auf Daten in einer Datenbank über die REST API zuzugreifen.

Thursday, February 28, 2013

Performance bei der String Konkatenierung in Java

Ein immer wieder gern gemachter Fehler der zu schlechter Performance in Java Programmen führt ist, das Zusammenbauen von Strings mit dem "+" Operator. Vor allem wenn dieses in einer Schleife gemacht wird steigt der Speicherverbrauch enorm an und der Garbagge Collector läuft Amok. Ein kleines Beispiel. Wir haben eine Liste (List<Person>) mit 100 Namen und wollen diese in eine CSV Datei ausgeben. Folgender Code erledigt die Aufgabe zwar völlig richtig. Wenn man das Programm aber in einem Profiler laufen lässt sieht man, dass jede Menge Hauptspeicher verschwendet wird und das Programm die meiste Zeit mit Garbagge Collecting verbringt.

  String result = "\"Vorname\",\"Nachname\"\n";
  for (Person person : personen) {
   result = result + "\"" + person.getVorname() + "\",\"" + person.getNachname() + "\n";
  }
  System.out.println(result);

Warum ist das so? Die Erklärung liegt darin, dass ein String in Java unveränderbar ist. Das heißt es ist in Java nicht möglich, dass man einen String einfach zu einem anderen hinzufügt. Viel mehr wird bei jeder Konkatenierung ein neuer String erzeugt. Mit diesem Hintergrund sieht man sofort, dass in unserem Programm jede Menge sinnloser Strings erzeugt werden, die sofort wieder von der Garbagge Collection entsorgt werden müssen. Vor allem böse ist aber die "result=result+..." Anweisung. Den der result String wird mit jedem Schleifendurchlauf länger und länger und dadurch wird auch der Hauptspeicher der bei jedem Schleifendurchlauf für den String angefordert werden muß größer und größer. Bei 100 Namen wird das vielleicht noch nicht so viel ausmachen. Bei 1000 Namen kommen da aber gleich mal viele Garbagge Collection Zyklen zusammen und schon haben wir wieder ein Programm, dass die urban legend das Java langsam ist scheinbar bestätigt.

Doch natürlich besitzt die Javaklassenbibliothek mit der StringBuilder Klasse eine Lösung für das Problem. Mit dieser veränderlichen Klasse können fast beliebig lange Strings einfach und effizient zusammengebaut werden.

  StringBuilder result = new StringBuilder();
  result.append("\"Vorname\",\"Nachname\"\n");
  for (Person person : personen) {
   result.append("\"");
   result.append(person.getVorname());
   result.append("\",\"");
   result.append(person.getNachname());
   result.append("\n");
  }
  System.out.println(result.toString());

Mit dieser Variante haben wir die Anzahl der unnötig erstellen String Objekte dramatisch reduziert. Intern verwendet der StringBuilder ein char Array, dass immer wieder vergrössert wird. Das char Array ist standardmäßig mit 16 Zeichen intialisiert und bei jeder Erweiterung wird die Kapazität verdoppelt. Das ist in unserem Beispiel natürlich immer noch eine Verschwendung. Deshalb empfiehlt es sich den StringBuilder als Parameter eine Schätzung der maximalen Größe des StringBuilder mitzugeben. Dadurch kann man nocheinmal einen Performancegewinn erzielen.

Falls das Zusammensetzen des Strings aus mehreren Threads erfolgen soll, sollte man statt des StringBuilders die Klasse StringBuffer verwenden. Letztere ist nämlich im Gegensatz zu StringBuilder Threadsafe.
ad