Historic Tale Construction Kit

Wer kennt es nicht, es ist Freitag Nachmittag und plötzlich wird ein historisch akurater Comic aus dem Mittelalter benötigt. Damit hier niemand im Regen stehen muss, gibt es das Historic Tale Construction Kit.

Mit dem Historic Tale Construction Kit können entsprechende Comics erstellt werden

Mit diesem ist es möglich solche Comics problemlos aus den vorgefertigten Elementen zu generieren. Ist der Comic fertiggestellt, kann er als PNG Datei exportiert werden. Ausprobiert werden kann das Ganze auf der Seite des Projektes. Der entsprechende Quelltext ist unter MIT-Lizenz lizenziert und damit freie Software. Er kann über GitHub bezogen werden.

Maps unter Java mit computeIfAbsent nutzen

Wenn eine Map unter Java etwas komplexer wird, wie z.B. folgende Map:

Map<String, List<String>> testMap = new HashMap<>();

wird das befüllen derselbigen interessant. In diesem Beispiel soll ein Key und ein neuer Value für die Liste vom Typ String hinzugefügt werden. Damit dies funktioniert muss überprüft werden ob der Key bereits existiert und wenn dies nicht der Fall ist, ein neuer Key angelegt werden. Im kompletten Beispiel sieht das Ganze so aus:

String key = "ABC";
String valueForList = "DEF";

Map<String, List<String>> testMap = new HashMap<>();

if(!testMap.containsKey(key)) {
    testMap.put(key, new ArrayList<>());
} 

testMap.get(key).add(valueForList);

Einfacher und unkomplizierter ist es die Methode computeIfAbsent zu nutzen, welche seit Java 8 in der Definition des Map-Interfaces enthalten ist. Mit der Nutzung der Methode verkürzt sich das Beispiel wie folgt:

String key = "ABC";
String valueForList = "DEF";

Map<String, List<String>> testMap = new HashMap<>();
testMap.computeIfAbsent(key, s -> new ArrayList<>()).add(valueForList);

Damit wird automatisch eine neue ArrayList angelegt, wenn der entsprechende Schlüssel noch nicht hinterlegt ist. Anschließend kann der entsprechende Wert für die Liste hinzugefügt werden.

Nginx unter macOS mittels Homebrew installieren und nutzen

Nginx wird für gewöhnlich unter Linux genutzt. Für Entwicklungszwecke kann es interessant sein Nginx unter macOS zu betreiben. Zur Installation von Nginx wird Homebrew benötigt. Homebrew ist ein Paketmanager für macOS, mit welchem viele Open-Source-Projekte unter macOS installiert werden können. Ist Homebrew installiert kann Nginx auf dem Terminal mittels:

brew install nginx

installiert werden. Standardmäßig läuft Nginx bei der Installation über Homebrew auf dem Port 8080. Hintergrund ist das der Webserver somit ohne root-Rechte bzw. ohne sudo genutzt werden kann. Wird der Port auf 80 oder generell auf einen Port kleiner 1024 gestellt, werden wieder entsprechende administrative Rechte benötigt. Soll der verwendete Port geändert werden, muss die Konfigurationsdatei angepasst werden:

nano /usr/local/etc/nginx/nginx.conf

In dieser findet sich folgender Block:

server {
  listen       8080;
  server_name  localhost;

Dort kann anschließend der Port geändert werden. Neben dem Port kann dort die Default-Location geändert werden. Dazu wird der server-Block bzw. dessen Unterblock, der location-Block angepasst:

location / {
  root /Users/seeseekey/Web;
  autoindex on;

Die root-Direktive gibt den Pfad an, welcher über den Webserver ausgeliefert wird. Die Option autoindex sorgt für das entsprechende Directory-Listing, was für Entwicklungszwecke nützlich sein kann. Gestartet und gestoppt werden kann der Service mittels:

brew services start nginx

bzw.

brew services stop nginx

Natürlich kann dies mittels restart in einem Rutsch erledigt werden:

brew services restart nginx

Anschließend kann Nginx mit der veränderten Konfiguration genutzt werden.

Java Exceptions in Strings verpacken

Wenn in einem Java-Programm etwas schiefläuft so, wird in den meisten Fällen eine Exception erzeugt und diese nach oben im Stack durchgereicht, bis sie behandelt wird. Manchmal ist es notwendig die Exception bzw. Teile davon in einen String umzuwandeln. Natürlich kann die Exception nun mühsam von Hand auseinander genommen und in einen String konvertiert werden. Sinnvoller ist es die Hilfsmethoden aus der Utility-Bibliothek Guava zu nutzen:

String stacktrace = Throwables.getStackTraceAsString(e);

Bei der Methode getStackTraceAsString wird der Stacktrace der betreffenden Exception in einen String umgewandelt. Neben dieser Methode existieren weitere Methoden rund um das Exception-Handling in der Klasse Throwables. Einfacher wird das Ganze, wenn ein Logger genutzt wird und in diesem die Exception auftauchen soll:

Logger logger = LoggerFactory.getLogger(new Exception().fillInStackTrace().getStackTrace()[0].getClassName());
logger.error("Exception: ", e);

In diesem Fall bieten die meisten Logger die Möglichkeit an, das Throwable direkt als Parameter zu übergeben. Die weitere Verarbeitung der Exception wird anschließend vom Logger erledigt.

Konvertierungen zwischen alter und neuer Datums- und Zeit-API

Seit Java 8 verfügt die Programmiersprache über eine sinnvolle Datums- und Zeit-API. In den meisten Fällen kann diese API ohne weitere Probleme genutzt werden. Problematisch wird es nur, wenn die neue API im Zusammenhang mit Legacy-Code genutzt werden soll. Meist wird dort die Klasse Date aus dem Package java.util genutzt. Damit werden Methoden benötigt, um eine Brücke von der alten zur neuen API und umgekehrt zu schlagen. Um ein Date in eine LocalDateTime umzuwandeln, kann folgende Methode genutzt werden:

public static LocalDateTime convertToLocalDateTime(Date date) {
    return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}

Soll der Wert, welcher in der LocalDateTime gespeichert ist, wieder in ein Date-Objekt konvertiert werden, kann folgende Methode genutzt werden:

public static Date convertToDate(LocalDateTime localDateTime) {
    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}

Bei diesen Konvertierungsmethoden ist zu beachten, dass die Zeitzonen bei der Konvertierung ignoriert werden. Stattdessen wird die Konvertierung mit der Standardzeitzone des Systems durchgeführt. Für die Konvertierung unter Berücksichtigung und Speicherung der Zeitzonen kann die Klasse ZonedDateTime genutzt werden. Die entsprechenden Methoden zur Konvertierung wären folgende:

public static ZonedDateTime convertToZonedDateTime(Date date, ZoneId zoneId) {
    return date.toInstant().atZone(zoneId);
}

public static Date convertToDate(ZonedDateTime zonedDateTime) {
    return Date.from(zonedDateTime.toInstant());
}

Bei der Konvertierung einer Date-Instanz in eine ZoneDateTime muss die entsprechende Zeitzone als ZoneId mitgegeben werden.