Feb 172011
 

… oder wie man Lotus Notes in so etwas ähnliches wie einem email-Client verwandelt.

Kürzlich hat meine Firma von MS Outlook auf Lotus Notes als email-System umgestellt. Die Freude hielt sich bei den meisten von uns in Grenzen – wirkt doch selbst die neueste Version von Notes manchmal, als wären 10 Jahre Entwicklung spurlos daran vorbeigegangen: selbst Features, die bei einem email-Client heute völlig selbstverständlich sind, sind ungenügend, auf seltsame Weise implementiert oder fehlen ganz.

Eines davon ist das New-Mail-Popup. Sie wissen schon, das ist das kleine rechteckige Fenster, das beim Empfang einer neuen eMail am unteren rechten Bildschirmrand erscheint und darauf hinweist, daß da etwas eingetroffen ist – vorzugsweise gleich mit dem Titel der Nachricht und wer sie geschickt hat.
Ein Convenience-Feature, das man mit der Zeit schätzen lernt – erlaubt es einem doch, mit einem Blick wichtige Nachrichten von unwichtigen zu unterscheiden und nur für solche den Mail-Client zu öffnen, die eine sofortige Reaktion erfordern.
Wie angenehm das ist, erkennt man erst, wenn man es nicht mehr hat.

Lotus Notes notification with Growl and the Metro display CC BY
Lotus Notes hat so ein nettes Zusatzprogramm, den “Notes Minder”. Toll, dachte ich, das ist, was ich brauche. Kaum hat man das Ding konfiguriert (ja genau, man muß es separat konfigurieren), macht sich aber auch schon Enttäuschung bereit. Das versprochene ‘Popup’ ist ein modaler (!) Dialog – jede Mail verlangt also sofortige, unbedingte Aufmerksamkeit. Außerdem ist er häßlich.
Mag man den Minder nicht, bleibt nur die akustische Benachrichtigung, die Notes von Haus aus beherrscht. Aber dann heißt es bei jeder email (auch bei den völlig unwichtigen Nachrichten): Arbeit unterbrechen, Notes öffnen, Nachrichten lesen, Notes schließen und Arbeit wieder aufnehmen. Das ist wirklich suboptimal.

Ich verwende jetzt schon eine Weile Growl für Windows. Das tut eigentlich nichts anderes, als von einer Unzahl möglicher Plugins Nachrichten entgegenzunehmen und – man rät es schon – als Popup anzuzeigen, das je nach Lust und Laune konfiguriert werden kann bzgl. Aussehen, Platzierung, Verweildauer, begleitendem Sound usw. Für Outlook gibt es ein Plugin. Für Notes natürlich nicht.

Aber da ist der einzige große Vorteil von Lotus Notes: seine Programmierbarkeit. Inzwischen (Gott sei Dank!) nicht mehr nur in LotusScript, sondern auch in Java. Die so geschriebenen Agents können auch auf dem Client ausgeführt werden, was sie ideal für die gewünschten Notifications macht.

Ich habe also einen Java-Agent geschrieben, der Growl-Notifications verschickt. Hier der Quellcode – nicht sehr lang, aber für einen Notes-API-Frischling trotzdem nicht ganz einfach:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
import lotus.domino.AgentBase;
import lotus.domino.AgentContext;
import lotus.domino.Document;
import lotus.domino.DocumentCollection;
import lotus.domino.Session;
 
public class JavaAgent extends AgentBase {
    private static final String ICON = "c:\windows\formatted\pathto\icon.png";
    private static final String NOTIFICATION_TYPE = "New Document";
    private static final String APPLICATION_TAG = "Lotus Notes";
 
    public void NotesMain() {
        System.out.println("Starting notification agent");
 
        try {
            final Runtime runtime = Runtime.getRuntime();
 
            // Register application on growl. This has to be done only once,
            // but it doesn't hurt to do it every time:
            runtime.exec("growlnotify /a:"" + APPLICATION_TAG + "" /r:"" + NOTIFICATION_TYPE + "" /i:"" + ICON
                + "" "Application registered"");
 
            final Session session = getSession();
            final AgentContext agentContext = session.getAgentContext();
 
            final DocumentCollection dc = agentContext.getUnprocessedDocuments();
            Document doc = dc.getFirstDocument();
 
            // Go through each unprocessed document that's not marked as read.
            // Display a maximum number of 10 notifications:
            for (int notificationCount = 0; notificationCount < 10 && doc != null; doc = dc.getNextDocument()) {
                if (!doc.getRead()) {
                    final String subject = doc.getItemValueString("Subject");
                    String from = doc.getItemValueString("From");
 
                    if (from.startsWith("CN=")) {
                        from = from.substring(3, from.indexOf("/"));
                    }
 
                    runtime.exec("growlnotify /a:"" + APPLICATION_TAG + "" /n:"" + NOTIFICATION_TYPE + "" /t:""
                        + subject + "" /i:"" + ICON + "" "" + from + """);
                    notificationCount++;
                    doc.markRead();
                }
            }
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
}

Ich muß gestehen daß ich faul war. Ich verwende Growl Notify zumn Versenden der Benachrichtigungen (growlnotify.exe muß sich im Pfad befinden).Eine native Java Growl library wäre vermutlich sowohl eleganter als auch schneller gewesen, aber das Kommandozeilen-Utililty ist einfach verdammt bequem. Vielleicht verbessere ich das Ganze irgendwann noch…

Der Agent ist als ‘scheduled’ mit einen minütlichen Intervall konfiguriert. Ich habe zwar durchaus versucht, den “After new mail arrives” – Event-Trigger zu vewenden, aber entweder muß man den Code dafür signieren, oder der Agent muß auf dem Server laufen – auf jeden Fall hat er nicht auf neue emails reagiert. Macht auch nichts. Emails müssen zumindest eine Minute warten können.

 Posted by at 20:21
Mai 292010
 

Finally, it’s done. I’ve released the first version of the ScalaEasyMock library (the naming is not very original, I have to admit).

ScalaEasyMock is a wrapper around the EasyMock library that focuses on mock controls and EasyMock Class Extension.

It provides a convenient, easy to use DSL for mock controls that makes heavy use of Scala manifests. Additionally, it contains helper classes that make it easy to create test objects with constructor arguments and partial mocks.

The library can be found on Google code, together with some documentation I’ve written:

Tutorial – scalaeasymock – Project Hosting on Google Code.

Happy mocking!

 Posted by at 14:48
Aug 312008
 
The eMock quick fix

Screenshot 1: The new 'Create Mock' quick fix

This is a very simple plugin that supports unit testing with

EasyMock. It adds a new quick fix ‘Create mock’ (accessible throgh Ctrl-1) to the Java editor in Eclipse for any identifier that cannot be resolved (see Screenshot 1).

When clicked, this quick fix (which is very similiar to the ‘Add local variable’ quick fix builtin to Eclipse) adds a createMock(..) statement to the method body and a replay(..) statement directly after (see Screenshot 2).

The result of the quick fix.

Screenshot 2: Result of the applied quick fix

As I said: very simple. However, Some experience with EasyMock has shown me that exactly this is what costs the most time when writing Unit tests: 1. Create a local variable, 2. add a createMock(..) statement, 3. add a replay(..) statement… this can get *very* annoying if you have many indirections and must mock 5 or 6 items in  a row. This plugin should take away this need and thus increase productivity.

Download the eMock plugin. Simply drop the JAR file into eclipse/plugins folder. Please be aware that this is still an early version that works only with Eclipse 3.4 ‘Ganymede’ and above.

The plugin is published under EPL. I appreciate any feedback and bug reports.

Mai 132008
 

Are mock objects serializable? Sound’s like an idiot’s question, since no sane guy would ever consider serializing something that doesn’t really exist – that’s like trying to go to the basement of a movie mockup building.

However, as it often happens in a programmer’s life, sometimes you’re forced to behave weird. Especially with mock objects if you’re trying to feed them into a third-party library.

What I was doing is mocking parts of my application to do unit tests on a business process workflow written with Jboss’ jBPM. Specifically, I was testing a script embedded in the workflow’s XML (which prevents me from skipping the whole jBPM business and do straight tests on my Java classes).

The script calls an object that I have mocked, and I want to verify that the result gets written to the workflow’s execution context (that’s the data storage underlying it, basically a String->Object map):

There’s one big problem: jBPM is a framework with intrinsic persistence (using Hibernate) and any object written to a workflow’s execution context must be serializable (!). As I found out (the hard way, as it is often with these things): mock objects created using EasyMock (specifically, EasyMock Class Extensions) are *not* serializable, even if the class they pose as is…

When I ran straight into NotSerializableException, I tried to find ways around it. A possible tsrategy would be to add a special type converter to jBPM that allows mocks – but changing the code to be tested for testing is bad.

I thought of a lot bad solutions, I have to admit. However, the one I finally came up with is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MySerializableTest {
 
	/**
	 * The serializable class to mock.
	 */
	public static class MySerializable implements Serializable {
		private static final long serialVersionUID = -242728243854443748L;
	}
 
	/**
	 * The class that will be actually mocked. Neither the
	 * {@link MockedMySerializable#readExternal(ObjectInput)} nor
	 * {@link MockedMySerializable#writeExternal(ObjectOutput)} method will do
	 * anything - they are just there to be mocked.
	 */
	public static class MockedMySerializable extends MySerializable implements Externalizable {
 
		@Override
		public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException 
                {
			/* do nothing */
		}
 
		@Override
		public void writeExternal(ObjectOutput out) throws IOException {
			/* do nothing */
		}
	}
}

This does the trick: instead of mocking the class that implements java.io.Serializable, I create a subclass of it that implements java.io.Externalizable (for those who don’t know: that’s kind of the ‘big brother’ of Serializable which lets the user implement the actual serialization himself. Of course, I provide only a dummy implementation. Nothing will be serialized for real here, it’s just to keep the code that invokes serialization from crying.

Of course, the mock created must either be a nice mock or actually expect the writeExternal(..) method to be called. But that’s just a routine task…

Mär 092008
 

Veranstaltungskalender OlympiaparkNachdem ich gestern zum Sport in die Olympia-Schwimmhalle gehen wollte und (nun schon zum zweiten Mal) wegen einer Veranstaltung vor verschlossenen Türen stand, habe ich ein bißchen gebastelt und ein kleines Greasemonkey-Skript geschrieben, das mir den Veranstaltungskalender des Olympiaparks so extrahiert, daß ich ihn auf meiner Netvibes-Homepage direkt als Modul anzeigen kann (ja, es wäre natürlich eine Kleinigkeit, die Seite des Olympiaparks anzusurfen und nachzusehen – aber ich brauche etwas, das mir sofort ins Auge fällt, sonst funktioniert das nicht *gg*):

// ==UserScript==
// @name           olyvk
// @namespace      helloworld
// @description    Olympiapark Veranstaltungskalender
// @include        http://www.olympiapark-muenchen.de/
// ==/UserScript==

var divCalendar = document.evaluate(
    '//div[@class="calendar"]',
    document,
    null,
    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
    null).snapshotItem(0);

document.body.innerHTML = divCalendar.innerHTML;