Spring: JSON aus HttpServletRequest

Vorab: Ja, es gibt @RequestBody. Und es ist hässlich. Ich habe es nicht mal eingebaut. Aber ich musste es googlen und will das nicht noch mal tun müssen:

PS zu Zeile 2 und zu Zeile 4.

Java: Anonymes Initialisieren von Listen

Listen:

Sie können “einzeilig” initialisiert werden:

Aber: Was, wenn ich sie mit anonymen Klassen initialisieren will?

Geht nicht, weil die anonyme Klasse Foo beerbt, und damit kommt Java nicht klar. Aber

geht. Hässlich, aber es geht. 🙂 Ein bisschen schöner (weil lesbarer) geht es mit Guava, aber im Grunde ist das genauso umständlich:

Weitere Vorschläge?

Java: Datei im Systemeditor öffnen

Googelt man “open file” etc., geht es meistens darum, eine Datei einzulesen. In meinem konkreten Fall wollte ich sie aber öffnen, also bsplw. ein PDF im Reader. Lösung:

Achtung: Eventuelle Handles müssen geschlossen werden, oder es gibt ein

There was an error opening this document. This file is already open or in use by another application.

Für einen OutputStream sieht das so aus:

Fat JAR mit gradle

Quelle, ergänzt um, Aufruf dann via

Spring Security: isFullyAuthenticated()

ist stellenweise verwirrend beschrieben. Hier heißt es

Returns true if the user is not an anonymous or a remember-me user

, wobei die Klammerung fehlt: “not” bezieht sich auf beides! Hier ist es IMHO auf andere Art verwirrend, aber zumindest nicht mehrdeutig:

Determines if the SecurityExpressionOperations.getAuthentication() authenticated without the use of remember me
HTH

Git und Intellij und Encoding

Neulich™ hatte ich das Problem, dass ein UTF-8-enthaltender String falsch nach XML transformiert wurde. UTF-8 ist (? war es zumindest früher oft) so eine Sache in Java, man muss(te) an drölf Stellen das Encoding explizit setzen; dazu gehörten zB Stream, Writer/Reader, StringBuilder, etc pp. Das mag inzwischen anders sein, denn nach langem Debugging stellte sich raus, dass nur das File-Encoding in IntelliJ falsch gesetzt war – der Code funkionierte ohne Änderung, die Quelle des Strings war bereits fehlerhaft gespeichert. Irreführenderweise hatte der IntelliJ-Debugger den String die ganze Kette hindurch korrekt angezeigt. “Nimm IntelliJ” haben sie gesagt, “das funktioniert super” haben sie gesagt. m(

Wie dem auch sei: Da UTF-8 an der Stelle zwingend gefordert war, musste sichergestellt werden, dass kein Entwickler, aus welchen Gründen auch immer, ein anderes Encoding einschleust, bzw., wie in diesem Fall, UTF-8 durch falsch konfiguriertes Encoding kaputtspeichert. Ein Ansatz könnte sein, im Git-Repo UTF-8 zu erzwingen. Ein Ansatz dafür kann sein, das Encoding in einem Git-Hook zu prüfen. Anbieten tun sich pre-commit (der erste Hook, der greift; client-seitig; Beispiel [1] [2]) und pre-receive (der erste serverseitige Hook; Beispiel).

[Für Stash/Bitbucket Server scheint es auch Möglichkeiten zu geben; ein fertiges Plugin habe ich aber nicht gefunden.]

pre-commit hat den Vorteil, dass sich keine Commits aufstauen, bevor das Problem auffällt. Dafür müssen lokale Hooks aufwändig verteilt/aktiviert werden – bsplw. über separat eingecheckte Verzeichnisse, die gesymlinkt (aber was ist mit Windows? Was mit wirklich lokalen Hooks? Und was ist noch zu beachten?) oder kopiert werden. Für pre-receive gelten Vor- und Nachteile inversiert, außerdem benötigt man Zugriff auf den Server auf Dateisystemebene.

Lange Rede, kurzer Sinn: Aus Gründen haben wir uns für einen pre-commit entschieden. Das Skript muss dabei .git/hooks/pre-commit heißen. Ich hätte ein Verzeichnis pre-commit mit Skripten darin erwartet, aber das wirft einen

cannot spawn .git/hooks/pre-commit: No such file or directory

Und es war gar nicht so einfach, eine Datei überhaupt mit dem falschen Encoding abzuspeichern. Sublime und Notepad++ haben sich (stillschweigend, was Notepad++ angeht) geweigert. Schließlich habe ich es mit IntelliJ geschafft, was allerdings auch gewarnt hat. Keine Ahnung, wie das ursprüngliche Problem überhaupt zustande kam.

Lokale Kopie des Skripts:

[Achtung: Das Skript kann nicht mit Binaries umgehen! Und das schließt bereits .woff ein. Offenbar ist es auch nicht trivial, Binaries zu erkennen; Internet nutzt dazu die Dateigröße oder auch Fileextensions. Ersteres scheint mir unzuverlässig, man denke an kleine Grafiken. Zweiteres ist sehr aufwändig…]

Beispielhafte Ausgabe (“ISO 8859-1.txt” heißt die Datei):

Und, der Vollständigkeit halber: Die Einstellung von Intellij:

btw: In Eclipse kann man Settings als Textfile exportieren und bsplw. in einem Repo ablegen – in IntelliJ scheint das nur als .jar exportierbar zu sein, bzw. über einen “IntelliJ Configuration Server” (WTF!?) verteilbar?

Java: Aus GWT in die Browser-Konsole loggen

Möchte das nicht immer googlen:

Logger und Level sind aus java.util.logging, also alles eigentlich recht naheliegend.

UPDATE

Die andere Methode hat allerdings den Vorteil, als Error zu loggen, was sich leichter rausfiltern lässt.

org.hibernate.MappingException: No Dialect mapping for JDBC type: -9

Folgendes Setup: Play 1.2.5.3, also Hibernate 3.6.10. Damit eine native Query auf einen MS SQL Server.

Folgender Fehler:

WTF? Die Query ist da übrigens nicht erst seit gestern drin, den Fehler gibt es aber erst seit Neuestem.

stackoverflow sagt nun zuerst mal:

The type -9 is java.sql.Types.NVARCHAR

und weiterhin (das liest man auch an anderer Stelle, der Fairness halber), die Lösung wäre:

Kurze Prüfung: Das fragliche Feld ist sowieso ein varchar. Außerdem hat es natürlich normalerweise einen Grund, nvarchar zu benutzen – nvarchar ist ein varchar, das Unicode unterstützt. Das will man nicht zurück casten. Macht also doppelt keinen Sinn. Vielleicht kommt der Fehler initial daher, dass das Feld seit Kurzem mit einem per String.toUpperCase() transformiertem String befüllt wird, vielleicht hilft hier ein String.toUpperCase(Locale), damit nicht implizit ein Unicode-String daraus wird. Klingt irgendwie auch merkwürdig, aber hey: Es ist ein MS SQL-Server! 🙂

Wie auch immer, wir haben durchaus nvarchar-Felder, und wollen die auch nutzen. stackoverflow sagt nun weiterhin, man müsse den nvarchar-Typ explizit bekannt machen, wenn er das im aktuell von Hibernate verwendeten SQL-Dialekt (und das ist hier SQLServer2008Dialect) nicht ist (ist er zwar, aber wenn’s der Sache dient…):

Ausprobiert, geht nicht. Nun gibt es neben registerColumnType auch registerHibernateType (Quelle), und damit geht’s:

Fast vergessen: Das ganze wird dann natürlich auch nicht per XML, sondern per application.conf konfiguriert:

HTH

Hibernate Envers Timestamp

Ein Envers Timestamp sieht in der Datenbank bsplw so aus: 1441090155727 (und ist ein Bigint). Das wäre der 30.04.47636, 06:02:07, und ich bezweifel, dass der Datenbankeintrag aus der Zukunft kommt. Die Lösung ist so naheliegend wie einfach: Die letzten drei Stellen stehen für die Millisekunden, der “korrekte” Timestamp lautet 1441090155, und das ist der 01.09.2015, 08:49:15.