Dienstag, 25. Oktober 2011

Zeitdauern berechnen mit TimeUnit

Auf java.net ist gerade ein netter Blog-Artikel verlinkt, der das java.util.concurrent-Enum TimeUnit vorstellt. Aus diesem Anlass eine kleine Idee, wofür ich dieses Enum und seine Umwandlung-Methoden schon gut gebrauchen konnte. Wenn man Zeitdifferenzen berechnet, benötigt man häufiger Konstanten von folgender Art:
public static final long MS_PRO_TAG
= 1L * 24L * 60L * 60L * 1000L;
Das funktioniert zwar, ist aber fehleranfällig, weil man sich bei Anzahl und Wert der Faktoren leicht vertun kann. Mit folgendem Ausdruck kann eine beliebige Anzahl Tage (hier: 1) in Millisekunden umgerechnet werden:
public static final long MS_PRO_TAG
= TimeUnit.DAYS.toMillis(1L);
Ebenso lassen sich Sekunden in Stunden umrechnen etc.:
assert TimeUnit.SECONDS.toHours(7250L) == 2;
Wie der andere Blog-Autor schon schreibt: Eigentlich gehört dieses Enum ins Package java.lang (oder vielleicht noch besser nach java.util).

Donnerstag, 13. Oktober 2011

"reschedule-failed-timer" in GlassFish 3.1

In Stateless Session Beans, Singleton Beans und Message Driven Beans kann der EJB-Timer-Service genutzt werden. Ab EJB 3.1 ist es dabei sehr einfach geworden, wiederkehrende Intervall-Timer mit der @Schedule-Annotation zu definieren (eine programmatische Definition ist natürlich weiterhin möglich).

Wenn ein periodischer Timer eine Exception wirft, wird GlassFish sofort noch zweimal versuchen, die Timer-Methode auszuführen. Werden auch diese Aufrufe mit Exceptions abgebrochen, stoppt GlassFish den Timer komplett, d.h. auch nach Ablauf des nächsten Intervall-Zeitraums erfolgt kein Aufruf mehr! Ich bin mir nicht sicher, ob dieses Verhalten von der EJB-Spezifikation gedeckt ist – intuitiv dürfte man aber vermutlich erwarten, dass Intervall-Timer zuverlässig ausgeführt werden.

Seit GlassFish 3.1 gibt es eine Server-Property "reschedule-failed-timer", mit der dieses Verhalten konfiguriert werden kann. Über das Konfigurationsprogramm asadmin kann man mit

asadmin set configs.config.server-config.ejb-container.ejb-timer-service.property.reschedule-failed-timer=true

einstellen, dass auch per Exception abgebrochene Timer nach Ablauf des nächsten Intervall-Zeitraums wieder aufgerufen werden. Durch den Aufruf wird in domain.xml folgender Abschnitt eingetragen:
<ejb-container session-store="${com.sun.aas.instanceRoot}/session-store">
<ejb-timer-service>
<property name="reschedule-failed-timer" value="true"></property>
</ejb-timer-service>
</ejb-container>
Ohne das Setzen der Property bleibt ansonsten nur, den gesamten Timer-Methoden-Rumpf in try { ... } catch (Exception ...) einzufassen, damit garantiert keine Exception den Timer verlässt.

Mittwoch, 5. Oktober 2011

Oracle JDK7 für Mac OS X (Developer Preview)

Nachdem Java SE 7 schon seit einigen Monaten für Windows, Linux und Solaris verfügbar ist und eine Portierung des OpenJDK 7 für Mac OS X begonnen wurde, bietet Oracle nun eine Vorabversion des JDK 7 für Mac OS X an.

Die Installation ist denkbar einfach: Nach dem Download der DMG-Datei zieht (kopiert) man die enthaltene Paket-Datei einfach ins Verzeichnis /Library/Java/JavaVirtualMachines. Fertig! Das Verzeichnis sollte bereits existieren, wenn man das letzte Apple-Java-Update installiert hat, ansonsten muss man es von Hand anlegen.

Die neue Version wird sofort von den Java-Einstellungen erkannt, ein Neustart des Systems ist nicht notwendig. Anwendungen müssen beendet und neu gestartet werden, um das neue Java nutzen zu können.

much$ /usr/libexec/java_home --version 1.7
/Library/Java/JavaVirtualMachines/JDK 1.7.0 Developer Preview.jdk/Contents/Home

much$ /usr/libexec/java_home -v 1.7 --exec java -version
openjdk version "1.7.0-ea"
OpenJDK Runtime Environment (build 1.7.0-ea-b211)
OpenJDK 64-Bit Server VM (build 21.0-b17, mixed mode)