Repositories with Realm

Realm 0.87 (for Android) came with a very important change: It introduced detached copies of RealmObjects. You can create a detached object using Realm.copyFromRealm. Any setter operation on a detached object won’t update the database so they can be called without opening a Realm transaction. In addition the detached objects are accessible from any thread.

We refactored our app code to use repositories and setup the following rules:

  • The UI only fetches realm objects via a repository (no more Realm code in Activities).
  • Repositories always return detached objects
  • Detached objects have to be saved using the save method in the repository.

Here’s a simple example repository:

public FooRepository {
 
    private Realm realm;
    
    public FooRepository(Realm realm) {
       this.realm = realm;  
    }
 
    public Foo getFooById(String fooId) {
        Foo foo = realm
                 .where(Foo.class)
                 .equalTo("id",fooId)
                 .findFirst();
        return realm.copyFromRealm(foo);
    }
    
    public void save(Foo detachedObjectToSave) {
       // isValid() always returns false on detached objects.
       if (object.isValid()) { 
          throw new IllegalArgumentException("received realm object is not a detached object");
       }

       realm.beginTransaction();
       realm.copyToRealmOrUpdate(object);
       realm.commitTransaction();
       // please note that this also could be saved 
       // in background using Realms asynchronous transactions.
    }
}

Java 8 – Stream.iterate

Today I came to the conclusion that I have to change my fitness center. (The current one is great, but I pay for features I don’t actually use). I checked the contract to find out the period of notice: I signed the contract on 27-Feb-2012 for 52 weeks. After the first 52 weeks the contract is automatically extended by 28 weeks. The period of notice is 12 weeks before the end of each extension time. Finding out the period of notice by hand is quite cumbersome, so I’ve fired up my Java-IDE and played with the new Java 8 Stream (and Date) API. Here’s the result:

public class FCDismissal {

public static void main(String[] args) {
  LocalDate signDate = LocalDate.of(2012,02,27);
  LocalDate firstYear = signDate.plusWeeks(52);

  Optional<LocalDate> nextNoticeDate = 
  Stream.iterate(firstYear, 
                 FCDismissal::extendContract)
    .map(date -> date.minusWeeks(12))
    .filter(date -> date.isAfter(LocalDate.now()))
    .findFirst();

  nextNoticeDate.ifPresent(System.out::println);
}

static LocalDate extendContract(LocalDate date) {
  return date.plusWeeks(28);
}

}

The output of the main method is 2015-08-10, so I have to dismiss the contract before this date.

Let’s dig into the code: The iterate method creates an infinite sequential Stream with a seed and a function for the next element. In my case the seed is the date after the initial 52 weeks and a method reference to extendContract.

Each date is mapped to its corresponding period of notice.

 .map(date -> date.minusWeeks(12))

After that I filter out dates in the past using the filter method.

.filter(date -> date.isAfter(LocalDate.now()))

An infinite sequential Stream has to be bounded using a so called “Short-circuiting operation”. findFirst terminates the stream and returns an Optional, which will be printed out when present:

nextNoticeDate.ifPresent(System.out::println);

As you can see, the Java 8 Stream API allows a very powerful and efficient programming style.

Gradle direkt von Eclipse debuggen

Momentan stellen wir ein Maven-basiertes Java-Projekt auf das Buildsystem Gradle um. Wichtig dabei ist, dass von Maven bekannte Komfortfunktionen weiterhin genutzt werden können: Dazu gehört auch das schnelle Starten eines lokalen Tomcats ohne vorherige manuelle Installation. Analog zum maven-tomcat-plugin gibt es für Gradle das gradle-tomcat-plugin. Sollte man (trotz hoher Testabdeckung) in die Verlegenheit kommen, einen Debugger verwenden zu müssen, gibt es zwei Möglichkeiten:

  1. Den Debugger an die JVM anhängen, die über den Aufruf von “gradle” auf der Konsole gestartet wurde.
  2. Die JVM mit Gradle direkt aus Eclipse zu starten.

Lösung 2 ist definitiv vorzuziehen, da der Debugger wesentlich performanter agiert. Aber wie starte ich Gradle in einer eigenen JVM direkt aus Eclipse ? Ganz einfach: In dem Jar gradle-launcher-1.2.jar befindet sich die Main-Klasse org.gradle.launcher.GradleMain.

Diese Klasse können wir in Form einer eigenen Launch-Konfiguration verwenden:
Main-Klasse für Eclipse Launch-Konfiguration

Die gewünschten Gradle tasks übergeben wir in den Program arguments:
Liste mit gradle tasks

Bevor wir starten, müssen wir noch zwei JARs zum Classpath hinzufügen:

  • gradle-launcher-1.2.jar
  • gradle-core-1.2.jar

Classpath-Konfiguration

Nach Klicken auf Run können wir die Ausgabe von Gradle in einer Eclipse Console betrachten, und mit dem Debugging beginnen.
Ausgabe von Gradle

Nice.

JDK7 Testfahrt – Teil 2

“Catching Multiple Exception Types”

Ein praktisches Feature, um doppelte catch-Blöcke zu vermeiden. Es ist nun möglich mit einem Catch-Block mehrere Exception-Typen gleichzeitig zu fangen. Die Exception-Typen werden dabei mit dem ODER-Operator (|) getrennt. Im Catch-Block kann die gefangene Exception unter gemeinsamen Supertyp angesprochen werden.

   static class AException extends Exception {
        public void fooFromA() {}
    }
    static class BException extends AException {
        public void fooFromB() {}
    }
    static class CException extends AException {
        public void fooFromC() {}
    }

    public void x() {
        try {
            z();
        } catch (BException | CException e) {
            e.fooFromA();
            // e.fooFromB(); Compiler-Fehler
            // e.fooFromC(); Compiler-Fehler
        }
    }

    public void z() throws BException, CException {
        // heavy lifting
    }

“Improved Checking for Rethrown Exceptions”

Des Weiteren “merkt” sich der Compiler nun, welche Exception-Typen im try-Block geworfen können. So kann im Catch-Block ein Supertyp gefangen und weiter geworfen werden, auch wenn dieser Supertyp gar nicht in der throws-Deklaration vorkommt.

 public void y() throws BException, CException {
        try {
            z();
        } catch (Throwable e) {
            // e darf ohne Cast weiter geworfen werden, da
            // der Compiler sich "gemerkt hat", dass im
            // try-Block nur BException und CException
            // vorkommen können.
            throw e;
        }
    }

JDK7 Testfahrt – Teil 1

Heute habe ich mir den Snapshot Build b134 des Java7 SDKs sowie die Beta 2 von Netbeans 7 heruntergeladen, um die neuen Sprachfeatures Probe zu fahren.

Eine gute Übersicht über alle neuen Features ist hier zu finden. Bekanntermassen wurden letztes Jahr die spannendsten Features “Closures” und “Collection Literals” in das JDK8 verschoben. Nichtsdestotrotz bietet das JDK7 mit dem JSR 334 kleine, sinnvollere Spracherweiterungen.

Binary Literals

Eins davon sind die “binary literals”. In früheren JDKs konnten numerische Literale im Quelltext in dezimaler, hexadezimaler oder oktaler Schreibweise erscheinen. Der Compiler des JDK7 erlaubt nun auch eine binäre Representation:

int answer = 0b101010;

Unterstriche in numerischen Literale

Desweiteren können Zahlen zwecks besserer Lesbarkeit im Quelltext auch mit einem Unterstrich optisch gruppiert werden. Dabei ist zu beachten, dass die Unterstriche nicht am Anfang oder am Ende eines Literals stehen dürfen.

long words1 = 0xCAFE_BABE; // ok
long words2 = 0xCAFE_BABE_; // Compiler-Fehler
long words3 = 0x_CAFE_BABE; // Compiler-Fehler 

Strings im switch-Statement

Nun kann auch ein String im switch-Statement verwendet werden. Der case-Vergleich findet analog zu der java.lang.String#equals-Methode statt. Das nachfolgende Beispiel gibt “banana” auf der Konsole aus.

        final String fruit = "banana";
        switch (fruit) {
            case "Apple": 
                System.out.println("Apple");
                break;
            case "Banana":
                System.out.println("Banana");
                break;
            case "banana":
                System.out.println("banana");
                break;
        } 

Ob ein String-Vergleich immer eine gute Idee ist, sei dahin gestellt. Schliesslich funktioniert ein Switch-Case seit dem JDK5 auch mit dem Enum-Konstrukt.

So. Genug für heute. Im nächsten Blogpost drehen wir eine weitere Runde.

Statische Codeanalysen mit Maven 2

Zur Qualitätssicherung eines Softwareprojekts gehören neben Unittests auch statische Codeanalysen. Tools wie Checkstyle, Findbugs oder PMD untersuchen Java-Klassen und bewerten den Code anhand verschiedener Metriken.

Zwar können diese Checks einen manuellen Codereview nicht ersetzen, aber Standardfehler und bekannte Anti-Patterns werden zuverlässig erkannt. Für jedes der genannten Tools gibt es ein Eclipse-Plugin, das die betreffenden Codestellen markiert. Die Anzeige der Fehler ist aber nicht ausreichend: Bei schwerwiegenden Verstössen soll auch der Build scheitern, ansonsten besteht die Gefahr, dass der Code nicht korrigiert wird. Aber wie kann man das umsetzen ?

Mit Maven 2 geht dies einfach mit einer Plugin-Konfiguration innerhalb des “build”-Elements.

Hier ein Projektbeispiel für die PMD Analyse:

  1. <build>
  2. <plugins>
  3. <plugin>
  4.    <groupId>org.apache.maven.plugins</groupId>
  5.    <artifactId>maven-pmd-plugin</artifactId>
  6.    <configuration>
  7.       <sourceEncoding>${file.encoding}</sourceEncoding>
  8.       <minimumTokens>100</minimumTokens>
  9.       <targetJdk>${java.target.version}</targetJdk>
  10.       <failOnViolation>true</failOnViolation>
  11.       <failurePriority>2</failurePriority>
  12.    </configuration>
  13.    <version>${pmd.version}</version>
  14.    <executions>
  15.       <execution>
  16.          <goals>
  17.             <goal>check</goal>
  18.             <goal>cpd-check</goal>
  19.          </goals>
  20.       </execution>
  21.    </executions>
  22. </plugin>
  23. </plugins>
  24. </build>

Mit dieser einfachen Konfiguration wird sichergestellt, dass der Code keine PMD-Verstösse der Kategorie 1 und 2 enthält. Zudem ist garantiert, dass der Build bei Copy&Paste von 100 Wörtern (bzw. Tokens) scheitert. Praktisch !

Praktisch: Maven-Help-Plugin

Apache Maven ist ein fantastisches Buildsystem, allerdings sind manche Plugins eher spartanisch dokumentiert. Für mehr Klarheit sorgt das maven-help-plugin mit seinem “describe“-goal, welches alle Goals eines Plugins inkl. der möglichen Parameter beschreibt. Beispielaufruf:

mvn help:describe -Dplugin=org.codehaus.mojo:findbugs-maven-plugin -Dfull

Ebenso hilfreich ist das “effective-pom“-goal, mit dem ein POM inkl. aller geerbten Eigenschaften ausgegeben wird. Vor allem bei grossen Projekten mit vielen Parents ist die generierte Übersicht hilfreich. Beispiel:

mvn help:effective-pom

Effective Java: Builder-Pattern

7 Jahre nach der ersten Auflage ist das Buch “Effective Java” von Joshua Bloch nun endlich in der zweiten Auflage erschienen. Der Klassiker wurde komplett runderneuert: Best-Practises für ‘neue’ Sprachelemente wie Generics und Enums kamen hinzu, veraltete Kapitel (wie der Ersatz von C-Strukturen) wurden gestrichen.

Neu ist auch das “Builder-Pattern”. Es kommt zum Einsatz, wenn ein Objekt viele optionale Variablen besitzt. Die bisherige, klassische Variante bei solchen Objekten ist das Schreiben von mehreren Konstruktoren (‘telescoping constructor’), die über unterschiedliche Anzahl von Parametern verfügen. Allerdings sinkt die Lesbarkeit bei mehr als 6 Parametern gewaltig (vor allem wenn die Parameter vom gleichen Typ sind).

Das “Builder-Pattern” verzichtet auf die ‘telescoping constructors’ und arbeitet stattdessen mit einer statischen inneren Klasse, die für das Erzeugen einer Instanz der äusseren Klasse zuständig ist. Der Konstruktor des Builder-Objekts enthält alle “Pflicht”-Variablen, die optionalen Variablen werden über (verkettbare) Methodenaufrufe hinzugefügt. Abschliessend wird die build Methode aufgerufen, die ein unveränderliches Objekt der äusseren Klasse erzeugt. Der Konstruktor der äusseren Klasse ist privat, d.h. nur ein Builder kann ein Objekt tatsächlich instanzieren:

Hier ein Beispiel:

  1. package ch.javablog.builderpattern;
  2.  
  3. import java.math.BigDecimal;
  4.  
  5. public class Product {
  6.    // all fields are final: immutable object
  7.    private final String id;
  8.    private final BigDecimal price;
  9.    private final String salesDescription;
  10.    private final Product baseProduct;
  11.    private final boolean approved;
  12.        
  13.    private Product (Builder builder) {
  14.       // private Constructor can only be called from Builder
  15.       this.id = builder.id;
  16.       this.price = builder.price;
  17.       this.salesDescription = builder.salesDescription;
  18.       this.baseProduct = builder.baseProduct;
  19.       this.approved = builder.approved;
  20.    }
  21.         
  22.    public String getId() {
  23.       return id;
  24.    }
  25.        
  26.    public BigDecimal getPrice() {
  27.       return price;
  28.    }
  29.        
  30.    public String getSalesDescription() {
  31.       return salesDescription;
  32.    }
  33.  
  34.    public Product getBaseProduct() {
  35.       return baseProduct;
  36.    }
  37.        
  38.    public boolean isApproved() {
  39.       return approved;
  40.    }
  41.        
  42.    public static class Builder {
  43.       // mandatory parameter
  44.       private final String id;
  45.       private final BigDecimal price;   
  46.      
  47.       // optional
  48.       private String salesDescription = "";
  49.       private Product baseProduct     = null;
  50.       private boolean approved  = true;
  51.                
  52.       public Builder(String id, BigDecimal price) {
  53.          this.id = id;
  54.          this.price = price;
  55.       }
  56.       public Builder salesDescription(String salesDescription) {
  57.          this.salesDescription = salesDescription;
  58.          return this;
  59.       }
  60.       public Builder baseProduct(Product baseProduct) {
  61.          this.baseProduct = baseProduct;
  62.          return this;
  63.       }
  64.       public Builder approved(boolean approved) {
  65.          this.approved = approved;
  66.          return this;
  67.       } 
  68.       public Product build() {
  69.          return new Product(this);
  70.       }
  71.    }
  72. }
  73.  
  74. public class ProductClient {
  75.    public static void main(String... args) {
  76.       BigDecimal price = BigDecimal.valueOf(36.5);
  77.       Product.Builder builder =
  78.          new Product.Builder("050-0047",price);
  79.  
  80.       // create Product using the builder
  81.       Product p = builder
  82.                .salesDescription("great product")
  83.                .approved(false)
  84.                .build();
  85.    }
  86. }

Update 13.2.2017: Das Lombok-Projekt ermöglicht mit der @Builder-Annotation eine sehr bequeme, automatisierte Erstellung von Buildern.

OVal – the object validation framework for Java 5 or later

Ich muss gestehen, ich bin ein Fan von defensiver Programmierung, d.h. ich deklariere mögliche Inkonsistenzen von Objekten durch das Werfen von RuntimeExceptions (z.B. IllegalStateException oder IllegalArgumentException). Praktisch finde ich ebenfalls das Prinzip der Unveränderlichkeit. Einmal erzeugt, soll das Objekt nicht mehr verändert werden. Somit werden Inkonsistenzen (z.B. nicht gesetzte Attribute) bereits im Vorfeld vermieden.

Allerdings verursacht diese Form der Absicherung unschönen Code-Overhead, da jeder Parameter manuell überprüft werden muss. Zudem stehen unveränderliche Objekte im Widerspruch mit der JavaBean Spezifikation

Vor kurzem habe ich einen interessanten Lösungsansatz im OVal Framework entdeckt. Hier werden die Properties und Methoden mit Annotations versehen und explizit oder implizit (via AspectJ) validiert. Beispiele gibts heute keine, stattdessen verweise ich auf die (gute) Doku.

SCJP 6 Upgrade

Letzte Woche habe ich das SCJP 6 Upgrade Exam bestanden.

Folgende Bücher habe ich während der Vorbereitungsphase durchgearbeitet:

  • Fast Track to Sun Certified Java Programmer (Scjp) 5.0 Upgrade Exam von Ka Iok Tong
  • SCJP Sun Certified Programmer for Java 5 Study Guide (Exam 310-055) von Kathy Sierra

Letzteres umfasst das komplette SCJP 5 und gibt Auskunft, welche Klassen und Methoden im Examen vorkommen können und welche nicht. Diese Hinweise vermisst man im “Fast Track to SCJP 5 Upgrade Exam” Buch. Hier wird beispielsweise die Klasse MessageFormat ausführlich beschrieben, obwohl sie für das Examen absolut irrelevant ist.

Bücher zum SCJP 6 gibt es noch keine, allerdings halten sich die Unterschiede zum SCJP 5 stark in Grenzen. Lediglich ein paar neue Klassen (NavigableMap, NavigableSet sowie Console) sind dazu gekommen.

Im Vergleich zum SCJP 1.4 sind die neuen Prüfungsthemen praxisbezogener. So wurden einige Klassen aus den Packages java.text und java.util.regex hinzugefügt. Als Konsequenz erhöht sich leider auch der Auswendiglern-Faktor (z.B. welche Konstruktor gibt es in der java.text.DateFormat Klasse ?)

Gleichzeitig wurden komplexe (aber dennoch spassige) Operatoren-Fragen wie Bitshifting oder Operatorvorrang gestrichen.