16.12.2012

Pancakes / Wie man Eier wirklich trennt!

Sonntag morgen? Aufgewacht und Hunger auf Pancakes? Und das erste Problem naht bereits! Wie trenne ich denn nochmal Eier!

Glücklicherweise habe ich bereits diverse unzählige Internetvideos zum Eiertrennen gesehen und bewertet. Der Suchbegriff "eier trennen"  ergibt bei Youtube alleine bereits knapp 650 Treffer. Die Methode, die mich aber am meisten fasziniert, ist das Eier trennen mit Hilfe einer leeren PET Flasche.
Mit Sicherheit ist mein Video bei weitem nicht so lang, aber dafür auch weniger hübsch. Der Trick selbst ist trotz allem ausreichend dokumentiert ;-)

Erster Schritt - das Eiertrennen (sogar in HD).


Die Eigelbe (aus den Eiweiss wird Eischnee geschlagen) werden im Anschluss mit Zucker und Zitrone zusammen schaumig gerührt.


Im Anschluss werden Mehl und Milch, sowie eine Prise Salz mit in die Schüssel gegeben und zu einem glatten Teig verrührt. Im Anschluss wird der Eischnee vorsichtig untergehoben, so dass eine fluffige Masse entsteht.


Danach kann der Teig kurz ruhen und der Quark mit frischen Heidelbeeren aus der Dose kann vorbereitet werden. Schmeckt zu den süßen Pancakes als Konstrast wirklich gut.


Dann geht es ans Ausbacken!


Sieht doch in Summe lecker aus, oder nicht?


Sollte das jemandem zu süß sein (einen freundlichen Gruß an Schatzi), dann kann man dazu noch ein paar Baconstreifen reichen, die im Anschluss geknabbert werden...


Einen guten Start in den Tag ;-)

Frühstück für Champions

Nicht näher spezifizierten Informationsquellen ist es mir gelungen "DAS Rezept" für einen erfolgreichen Tag in den Start herauszufinden!

Na gut, die Realität ist eher, dass ich die Idee bereits beim Stepford Husband gesehen hatte und unbedingt ausprobieren wollte. Und heute bestand ausnahmsweise die passende Möglichkeit.

Grundlage für einen guten Start in den Tag sind ausreichend Ballaststoffe, die sich in diesem Fall in einem gesunden Weizen-Mischprodukt mit pseudo-gesundem Namen befinden.

Die Rede ist von Vollkorntoast. Und da ich mit über 30 Jahre nun schon kaum noch richtig kauen kann, musste natürlich auch die Kruste entfernt werden.


Die entstandenen Vierecke können danach in einfache, leicht gefettete, ofenfeste Formen gepresst werden. Besser wäre sicherlich eine Muffin-Backform, wie sie auch im Original verwendet wird, aber leider war keine zur Hand.


Eventuell entstehende Lücken werden professionell mit der abgeschnittenen Rinde aufgefüllt, so das der Inhalt später nicht ausfließen kann.

Was ist sonst noch Bestandteil eines echten Frühstücks jeden Essens? Richtig, Bacon. Knusprig gebraten findet dieser ebenfalls seinen Weg in die Formen.


Für den Vitaminhaushalt gesellen sich noch ein paar geschmorte, rote Zwiebeln hinzu.


Alles fertig? Dann fehlt ja nur noch das Eiweiss für einen erfolgreichen Muskelaufbau! Dieses wird roh in die Formen gegeben und nur mit ein wenig Salz und Pfeffer gewürzt.


Danach gehen die Portionen in den Backofen bis der gewünschte Gargrad erreicht ist.


Lecker und genau das passende für einen Samstagmorgen!

28.11.2012

JPA 2.0 - Simple Collection Mapping

Mit JPA 2.0 wurde die Arbeit mit Collections von einfachen Datentypen deutlich vereinfacht. War in der vorangegangenen Version noch eine explizit definierte "Wrapper-Entität" notwendig, ist es nun deutlich einfacher.

Collections, und auch Maps, von einfachen Datentypen können direkt und somit ohne weitere Entitäten gemappt werden. Nahezu alle Konfigurationsmöglichkeiten bleiben dabei erhalten. Ein paar Feinheiten und Besonderheiten sind allerdings zu beachten.

Für die Beispiele wird die JPA Spec (JSR-317) zu Grunde gelegt.


java.util.List<T> / java.util.Set<T>

In JSR-317 ist definiert, dass alle Collections von einfachen Datentypen, wie auch von sogenannten Embeddables, durch eine einfache Annotation gemappt werden können. Ein einfaches Beispiel ist für diesen Fall schnell erstellt.


Die zentrale Annotation ist in diesem Fall @ElementCollection zur Definition einer Liste von Vornamen. Somit ist keine weitere Entität notwendig, die einen Wrapper um den einfachen Vornamen bildet, wie es vorher notwendig war. Entsprechende Tabellen werden automatisiert erstellt.


In diesem Fall wird die Beziehung direkt über eine Foreign-Key-Relation in der Tabelle Person_firstnames abgebildet. Auf den ersten Blick wäre eine sprechendere Tabellenbezeichnung sinnvoller. Daher wird die Entität durch eine Annotation erweitert:


@CollectionTable bietet die Standardkonfigurationsoptionen, wie:
  • name
  • schema
  • catalog
  • joinColumns
  • uniqueConstraints.
Die automatisch erstelle Tabelle wird sofort an das geänderte Mapping angepasst.


Weitere Konfigurationen sind nicht notwendig und wie zu sehen ist, wird das Mapping für einfache Datentypen deutlich einfacher.

@ElementCollection kann aber nicht nur auf einfache Datentypen, sondern auch auf Embeddables angewandt werden. Ein Embeddable ist eine Klasse, die innerhalb der beinhaltenden Entität gespeichert wird und sich die Id mit der beinhaltenden Klasse teilt. Dabei wird jedes persistente Attribut / Embeddable mit persistiert.


Mit der Erweiterung durch die Liste der favorisierten Gerichte, werden die generierten Tabellen ebenfalls umfangreicher.


Wie zu sehen ist, wird aus dem FavoriteFood keine separate Entität, sondern, wie auch bei den Vornamen, eine einfache Liste, verknüpft über eine normale Fremdschlüsselbeziehung.

In beiden Fällen, sowohl bei den einfachen Datentypen, als auch bei den Embeddables, ist allerdings wichtig, dass mit dem Interface java.util.List gearbeitet wird und nicht mit einer konkreten Implementierung. Wird nicht mit dem Interface gearbeitet, tritt bereits einer Fehler bei der Analyse durch dem OR-Mapper auf.


Ein Grund für eine konkrete Implementierung wäre als Beispiel das Sortieren. Das kann an dieser Stelle eleganter gelöst werden.


Mit Hilfe der Annotation @OrderBy kann sowohl die Spalte nach der sortiert werden soll, als auch die Reihenfolge (asc oder desc) definiert werden. @OrderBy sorgt für eine Erweiterung der Statements um eine "ORDER BY" Bedingung auf die angegebene Spalte.

Spannend ist auch die Speicherung einer Liste von Enums. Wie beim Speichern von Enum-Werten, kann auch für die gesamte Liste angegeben werden, ob der Ordinalwert oder die textuelle Darstellung gespeichert werden kann.



java.util.Map<K,V>

Für die Benutzung von Map gelten im wesentlichen die gleichen Regeln, wie auch für das Nutzen von Set oder List. Somit wird der Einsatz von Maps in Entitäten leichter als er es vormals war. Eine Map mit einfachen Werten wird, wie auch Listen oder Sets, leicht gemappt, daher steige ich auch hier direkt mit einem etwas komplexeren Beispiel ein. Die Liste der Haustiere wird ersetzt durch eine Map der Haustiere mit ihren zugehörigen Namen.


Die Tabellenstruktur wird entsprechend um eine Tabelle erweitert.


Dabei ist zu erkennen, dass die neu erstellte Tabelle Person_pets neben dem Fremdschlüssel zur Person zwei weitere Spalten beinhaltet. Die eine Spalte pets_KEY entspricht dem Schlüssel der Map (dem Namen des Haustieres) und die Spalte pets entspricht dem Wert in der Map. Sofort fällt auf, dass neben dem nicht unbedingt glücklichem Namen der Tabelle auch nicht unbedingt der Ordinalwert der Enum gespeichert werden soll. Auch dies kann durch Annotationen behoben werden.



Mit @Enumerated wird festgelegt, dass der Wert des Eintrages in der Map als textuelle Repräsentation gespeichert wird. Gleichzeitig können mit Hilfe der Annotation @MapKeyColumn die Eigenschaften der Schlüsselspalte festgelegt werden. Sollen die Eigenschaften der Wert-Spalte festgelegt werden, wird dafür die normale @Column Annotation verwendet.

Was ist aber, wenn die Schlüsselspalte der Map als Enum werden soll?



Mit der Annotation @MapKeyEnumerated kann die Art der Speicherung für den Enum-Wert in der Schlüsselspalte festgelegt werden. Somit besteht auch an dieser Stelle die Möglichkeit, dass nicht der Ordinalwert, sondern die textuelle Repräsentation gespeichert wird.

Wie also zu sehen ist, wird das Mapping von einfachen Collections mit JSR-317 deutlich leichter und komfortabler. Viel Erfolg beim Ausprobieren!

Die Beispiele finden sich wie immer im Repository.

22.11.2012

Criteria API - CAST ( .. AS .. )

Wer kennt es nicht? Der ewige Zwist zwischen (alt-eingessenen) DBAs und dem Programmierer an sich. Im wesentlichen zwei Spezies, die meist nur schwer miteinander zu vereinen sind.

Ich muss zugeben, dass das nicht immer stimmt, denn die Mehrzahl der Gespräche sind im wesentlichen sinnvoll. Die Probleme bestehen meist eher in dem antiquierten Datenbankmodell, was über die Jahre gewachsen und gewachsen und gewachsen ist. Da schleicht sich meist die eine oder andere Inkonsistenz ein, gerade was die Typen innerhalb einer Tabelle angeht. Da werden Zahlwerte als char-Felder mit festen Längen gespeichert, Datumsangaben mal als Timestamp, dann wieder als char und zwischendurch auch mal ganz anders.

Trifft man auf solche Probleme, sind immer spezielle Lösungen erforderlich um die eigentlichen Anforderungen umzusetzen. Am einfachsten wird das Problem anhand eines Beispiels klar. Die gegebene Tabellenstruktur ist gekennzeichnet durch das folgende SQL:



Dort ist klar zu erkennen, dass die Spalte INT_VALUE in der Datenbank als varchar(5) abgebildet wird. Die Entität selbst bildet die Spalte allerdings auf einen int-Wert ab.


Beim Mapping durch Hibernate werden noch keinerlei Probleme sichbar. Das Mapping kann ohne weitere Probleme durchgeführt werden und ein erster Test ist erfolgreich.



Auch das Auslesen ist für korrekt eingefügte Werte möglich.


Das dies funktioniert liegt allein daran, dass Hibernate bereits einen Teil der Konvertierung übernimmt und die in der Datenbank befindlichen Werte automatisch in die passenden Werte überführt. Deutlich wird dies, wenn einer der Werte nicht mehr numerisch, sondern alphanumerisch ist.


Sofort tritt eine DataException auf, die den Test fehlschlagen lässt, da der geänderte Wert "10A" nicht konvertiert werden kann.

Nun stellt sich die Frage, für welchen Fall ein CAST überhaupt benötigt wird. Die Konvertierung geschieht augenscheinlich automatisch und lieferte korrekte Ergebnisse, wenn die Daten konsistent sind und das Mapping den korrekten Datentypen besitzt. Was passiert aber, wenn die Entität nicht den fachlich korrekten Typen besitzt, sondern an die Deklaration in der Datenbank angelehnt ist?


Damit wird bereits ein einfacher Test zum Problem. Werden alle Produkte mit einem Wert zwischen 1 und 5 abgefragt, sollten 5 Produkte zurückgegeben werden.


Der Test schlägt fehl. Es werden nicht nur die Produkte mit einem Wert zwischen 1 und 5 zurückgegeben, sondern auch das Produkt mit dem Wert 10, da dieses bei einem einfachen Vergleich ebenfalls als korrektes Ergebnis erkannt wird. Das ist in diesem Fall aber gar nicht gewünscht.

Somit muss eine Alternative gefunden werden. Ein möglicher Lösungsansatz ist das Einfügen einer nativen Bedingung mit einem nativen Cast der Werte. Dafür bietet die Criteria-API die Möglichkeit eine Restriktion mit nativem SQL zu definieren.


Mit Hilfe der nativen Einschränkung kann das Statement so erweitert werden, dass ein Vergleich direkt auf numerischer Basis in der Datenbank durchgeführt wird, {alias} sorgt hier für die Angabe der richtigen Tabelle. Anschließend müssen nur noch die Parameter inkl. der zugehörigen Typen gesetzt werden und die Datenbank übernimmt die eigentliche Arbeit. Der Test ist grün.


Sicherlich wäre der elegantere Weg, dass die Entität fachlich korrekt definiert wird und eine automatische Umwandlung durch Hibernate stattfindet. Allerdings ist dies in vielen Fällen nicht möglich, da das Objektmodell nicht angepasst werden soll.

Das Beispiel findet sich wie immer im Repository.




20.11.2012

Maven - Filtering von Resourcen

Auf der Suche nach einer Möglichkeit eine Webanwendung durch den Timestamp und die POM-Version zu kennzeichnen bin ich über die Möglichkeit des Filterings gestolpert.


Über das Filtering ist es recht leicht möglich eine bereits bestehende Properties-Datei zu erweiterten und mit den gewünschten Informationen zu versehen. Der Einfachheit halber wird an dieser Stelle nur das Filtering beschrieben, die Anwendung selbst wird als Konsolenanwendung gebaut. Der Aufbau der Anwendung ist der folgende:


Die Anwendung wird nach dem Packaging auf der Konsole gestartet. Die Anwendung selbst ist nicht mehr als das Lesen der Properties und das nachfolgende Schreiben auf der Konsole.



Ein erster Aufruf zeigt die folgende Ausgabe auf der Konsole:


Wie zu sehen ist, werden die Properties zur Laufzeit noch nicht ersetzt. Für ein Filtering der Resource-Dateien wird eine Erweiterung des POM benötigt.


Nach diesem Schritt ist es möglich, Properties zum Zeitpunkt des Packagings ersetzen zu lassen. Das gilt natürlich auf allen Einträgen im Resource-Verzeichnis. Nach dem Packaging ändert sich die Ausgabe wie folgt:


Zu sehen ist, dass die erste Property, ${pom.version}, als Standardproperty ersetzt werden konnte. Die andere Property, ${last.build}, bleibt allerdings unaufgelöst. Das liegt daran, dass diese noch nicht im POM definiert ist.


Sobald diese definiert ist, kann eine Ausgabe wie gewünscht realisiert werden.


Es gibt unterschiedliche Szenarien in denen ein Filtering zum Einsatz kommen kann. Nicht nur das Hinzufügen von Build-Informationen zu Web-Anwendungen, sondern auch das Ersetzen von speziellen Informationen für Tests, Stage-sepzifische Builds oder anderen spezielleren Einsatzzwecken.

Nice to know.

13.10.2012

Maven Build Profiles - Test unterschiedlicher JPA Provider

Für einen zukünftigen Vortrag habe ich mir mir heute die unterschiedlichen JPA Provider etwas genauer angeschaut.
Auf dem Plan standen, neben Hibernate, EclipseLink oder auch OpenJPA.


Um für die Betrachtung eine möglichst schnell zu wechselnde Laufzeitumgebung zu haben, habe ich mir die Maven Build Profiles mal wieder ins Gedächtnis gerufen. Ziel der Build Profiles ist es ja, dass man recht leicht zwischen dedizierten Umgebungen wechseln kann. Gleichzeitig kann man in den Build-Profilen aber auch selektiv Dependencies oder Properties überschreiben, setzen oder neu definieren. Also eigentlich genau das richtig für mein Unterfangen, oder?

Begonnen habe ich mit einer einfachen Entität, dem Standard-Beispiel quasi. Basis für die gesamte Betrachtung war eine einfache Person mit ein paar wenigen Attributen.


Eine einfache und leicht zu verstehende Entität. Um die Provider möglichst einfach zu testen, habe ich einen kleinen JUnit-Test erstellt. Dieser versucht eine Person zu erstellen, diese zu persistieren und schlussendlich auch wieder aus der Datenbank zu lesen.


Der Test selbst ist unspektakulär, der EntityManager wird vor jedem Test erstellt und es wird eine Transaktion geöffnet. Nach jedem Test wird der EntityManager wieder geschlossen. Interessant ist allerdings noch die Erzeugung der EntityManagerFactory. Dies wird vor dem Test selbst in der @BeforeClass Methode ausgeführt und sieht wie folgt aus:


Der Name der Persistence-Unit wird an dieser Stelle aus einer System-Property ausgelesen. Je nach Provider wird eine der drei Persistence-Units für die Erzeugung der EntityManagerFactoryherangezogen.

Damit diese Property vom Buildprozess aus gesteuert werden kann, wird das Surefire-Plugin um einen Konfigurationseintrag erweitert.


Mit Hilfe dieser Property können nun die Build Profiles elegant die Werte überschreiben und damit die zugehörige Persistence-Unit für den Test auswählen.


Durch diese Konfiguration kann für jeden Provider ein eigenständiges Profil erstellt werden, welches, von den anderen Profilen unabhängig, eigene Dependencies definiert und vollkommen autark aufgerufen werden kann. Damit ist ein Wechsel des Providers bereits während der Testphase möglich.


Ein Aufruf von mvn clean test -P EclipseLink liefert dann direkt die folgende Ausgabe.


In beiden Fällen wird die Auswahl der Persistence-Unit über die überschriebene Property getätigt. Die Dependencies und sonstigen Einstellungen werden ebenfalls aus dem aktivierten Profil entnommen.

Der Code ist wie immer im Repository verfügbar.