Sonntag, 28. Oktober 2012

Grails Maven Integration

Es gibt verschieden Wege Grails in Maven zu integrieren, z.B. um den Nexus zu benutzen. Da wäre das Grails Plugin Maven Publisher (Link). Dieses ist für Grails 1.X geeignet, wird aber nicht mehr unterstützt. Damit fällt es aus. Ersetzt wurde das Grails Plugin Maven Publisher durch das Release Plugin (Link), welches für Grails 2.X verfügbar ist. Das funktioniert bei aktuellen Grails Projekten, leider wird das Passwort für den Nexus innerhalb des Projektes gespeichert (grails-app/conf/BuildConfig.groovy), das ist überhaupt nicht groovy, das ist fahrlässig. Damit fällt auch diese Lösung aus. Dritter Versuch, erstellen einer POM Datei aus Grails heraus. Das funktioniert nur leider kompiliert dann nichts mehr, unter Java 7 auf dem Mac (siehe Fehlerausgabe unten). Dies ist ein bekannter Bug (Link).

Fazit, drei Möglichkeiten, kein Treffer. Was macht eigentlich Ant?





[ERROR] Unresolveable build extension: Plugin org.grails:grails-maven-plugin:2.1.0 or one of its dependencies could not be resolved: Could not find artifact com.sun:tools:jar:1.6 at specified path /Library/Java/JavaVirtualMachines/jdk1.7.0_06.jdk/Contents/Home/jre/bundle/Classes/classes.jar @
[ERROR] Unknown packaging: grails-app @ line 8, column 16

at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:339)
at org.apache.maven.DefaultMaven.collectProjects(DefaultMaven.java:632)
at org.apache.maven.DefaultMaven.getProjectsForMavenReactor(DefaultMaven.java:581)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:233)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
[ERROR]  
[ERROR]   The project com.futuretv.userprofiledatasource:UserProfileDatasource:0.1 (/Users/mirkoebert/Documents/workspace-sts-2.9.0.RELEASE/UserProfileDatasource/pom.xml) has 2 errors
[ERROR]     Unresolveable build extension: Plugin org.grails:grails-maven-plugin:2.1.0 or one of its dependencies could not be resolved: Could not find artifact com.sun:tools:jar:1.6 at specified path /Library/Java/JavaVirtualMachines/jdk1.7.0_06.jdk/Contents/Home/jre/bundle/Classes/classes.jar -> [Help 2]
org.apache.maven.plugin.PluginResolutionException: Plugin org.grails:grails-maven-plugin:2.1.0 or one of its dependencies could not be resolved: Could not find artifact com.sun:tools:jar:1.6 at specified path /Library/Java/JavaVirtualMachines/jdk1.7.0_06.jdk/Contents/Home/jre/bundle/Classes/classes.jar
at org.apache.maven.plugin.internal.DefaultPluginDependenciesResolver.resolve(DefaultPluginDependenciesResolver.java:215)
at org.apache.maven.project.DefaultProjectBuildingHelper.resolveExtensionArtifacts(DefaultProjectBuildingHelper.java:377)
at org.apache.maven.project.DefaultProjectBuildingHelper.createProjectRealm(DefaultProjectBuildingHelper.java:237)

Samstag, 27. Oktober 2012

Jenkins vs Hudson

Wenn um den Einsatz eines Continuous Integration Servers geht, fallen immer zwei Namen: Hudson und Jenkins. Was man oft hört, ist eigentlich das selbe. Ja das stimmt, wenn ich einen neuen Server aufsetze, muss ich vorher für einen von beiden entscheiden. Ich habe von beiden den aktuellen Stand getestet und verglichen. Zum Einsatz kamen Hudson 3.0.0 RC und Jenkins 1.486 auf einem aktuelle Ubuntu. Prinzipiell funktionieren beide Ci Server gleich, die Arbeitsabläuft sind gleich und die Konfigrationsfenster teilweise auch. Der Hudson ist trotz seiner fortgeschrittenen Entwicklung nicht stabil genug, oft funktionieren Dinge nicht (Grails, Ant). Letzlich führten wir die Builds per Shell (grails war) aus. Insgesamt behinderte er die tägliche Arbeit stark. Jenkins dagegen arbeitet wie erwartet. Positiv fiel hier auf, dass man für viele Arbeiten weniger Clicks benötigt. Bezogen auf den aktuellen Entwicklungsstand macht der Jenkins eine deutlich bessere Figur. Es bleibt zu hoffen, das Hudson die Fehler verliert und wieder konkurrenzfähig wird. Zur Zeit fällt meine Empfehlung auf den Jenkins. Übrigens gibt zu beiden CI Servern eine App für iOS. Die Apps werden ich später einem Test unterziehen.

May the test with you...

Freitag, 26. Oktober 2012

Objektorientierung: Warum braucht man Getter und Setter.

Es lernt jeder, wenn man objektorientiert Programmiere, greifet man auf die Objekteigenschaften mit Hilfe von get (lesen) und set (schreiben) Methoden zu. Wenn ich mit Java programmiere kann ich mir diese Methoden automatisch erstellen lassen, wenn ich Eclipse nutze. Andere Sprachen (Groovy, PHP) bieten an dieser Stelle ein bisschen Magic an, dort braucht man diese Methoden gar nicht mehr selbst erstellen, sondern sie sind da, das ist noch bequemer. Doch einmal stellt mir ein anderer Entwickler die Frage, wozu brauchen wir Getter und Setter? Ich war sprachlos und dachte eine Weile darüber nach. Die Antwort ist, in der Regel braucht man sie nicht, weil sie keinerlei Logik enthalten. Viele Datenklassen (Domain Objekte) sind reine Datenkontainer, wozu brauch ich da noch Getter und Setter? Sie haben keinen Nutzen, sie sind überflüssig. Sie nur zu implementieren um einer Vorschrift zu genügen ist Unsinn. Ich habe jetzt aufmerksam in meinen Code geschaut und ich hatte einige wenige Getter und Setter. Sie enthielten irgend welche Logik, sonst waren meine Klassen durch den Konstruktor konfiguriert oder die Klasse war Zustandslos, als ein mehr ein Service. Fazit, ich brauche keine leeren Getter und Setter, sie bieten keinen Mehrwert, sie sind überflüssig und nutzlos. Ich werde sie auch nicht vermissen.

Donnerstag, 25. Oktober 2012

Nexus

Der Nexus ist ein Repostory für Java Bibliotheken und Artefakte. Es integriert sich perfekt in Maven. Es gibt neben der freien Version noch ein Professional Version. Ein Vorteil der Professional Version ist, dass man Maven Sites, also Projekt Sites und Reports die durch Maven erzeugt wurden, dort deployen kann. Zur Installation gibt es hier eine Anleitung. Wenn das TGZ zur Installation gewählt wurde ist dringend zu prüfen, ob der Eigentümer und die Gruppe richtig gesetzt sind (root). Dann noch schnell den Benutzer im File /etc/init.d/nexus auf root setzen. Schon läuft der Nexus unter: http://localhost:8081/nexus Benutzername: admin Passwort admin123 (bitte ändern). Jetzt einen Benutzer anlegen und ihm ausreichend Rechte geben. Dann noch Maven konfigurieren, folgende Einträge müssen ins POM:
<distributionManagement> 
    <snapshotRepository> 
        <id>snapshots</id> 
        <url>http://stage02:8081/nexus/content/repositories/snapshots</url> 
    </snapshotRepository> 
    <repository> 
        <id>release</id> 
        <url>http://stage02:8081/nexus/content/repositories/releases/</url> 
    </repository> 
</distributionManagement>
Danach muss noch die user.xml ergänzt werden:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 
                      http://maven.apache.org/xsd/settings-1.0.0.xsd"> 
  <localRepository/> 
  <interactiveMode/> 
  <usePluginRegistry/> 
  <offline/> 
  <pluginGroups/> 
      <servers> 
            <id>release</id> 
            <username>ebm</username> 
            <password>XXX</password> 
        </server> 
        <server> 
            <id>snapshots</id> 
            <username>ebm</username> 
            <password>XXX</password> 
        </server> 
    </servers> 
  <mirrors/> 
  <proxies/> 
  <profiles/> 
  <activeProfiles/> 
</settings>
Jetzt kann man alles testen: mvn deploy

Code Coverage mit Emma

Für die Berechnung der Testabdeckung des Codes gibt es eine Reihe von Werkzeugen, populär sind Cobertura als auch EclEmma. Cobertura wir gerne in Grails verwandt nur leider liefert Cobertura in Verbindung mit Java 7 keine Ergebnisse mehr. Also auf zu Emma. Emma lässt sich sehr einfach als Eclipse Plugin einsetzen, um Emma auch in Maven 3 nutzen zu können bedarf ein wenig Konfiguration.
    <build> 
        <plugins> 
            <plugin> 
                <artifactId>maven-compiler-plugin</artifactId> 
                <version>2.3.2</version> 
                <configuration> 
                    <source>1.7</source> 
                    <target>1.7</target> 
                </configuration>
            </plugin> 


            <plugin> 
                <groupId>org.jacoco</groupId> 
                <artifactId>jacoco-maven-plugin</artifactId> 
                <version>0.6.0.201210061924</version> 
                <executions> 
                    <execution> 
                        <goals> 
                            <goal>prepare-agent</goal> 
                        </goals> 
                    </execution> 
                    <execution> 
                        <id>report</id> 
                        <phase>prepare-package</phase> 
                        <goals> 
                            <goal>report</goal> 
                        </goals> 
                    </execution> 
                </executions> 
            </plugin>
EclEmma basiert auf der Bibliothek jacococ, dem entsprechend muss das Maven Plugin JACOCO benutzt werden. Mit dieser Maven Konfiguration erzeugt man dann zu Eclipse equivalente Reports.

Mittwoch, 24. Oktober 2012

Indikatoren fürs Refactoring

Refactoring ist in der Agilen Welt ein immer währender, fortlaufender Vorgang. Trotzdem gibt es in vielen Projekten Phasen des Refactorings. Woran erkennt man, das Refactoring dringend angeraten wird:
  • Zu viele globale Variablen
  • Der Programmierer sagt: "Die Methode kann ich nicht testen."
  • Das Projekt verwendet veraltete Bibliotheken oder Plugins
  • Hidden Features, niemand weiss von diesem Feature
  • Nicht benutzte Features
  • Es gibt Integrationstest an Stelle von Unit-Tests
  • Vererbung und Abstrakte Klassen (in den meisten Anwendungsfällen)
  • Verstoss gegen Clean Code wie:
    • Code Duplikate, Verstoß gegen die DRY Regel
    • Case Anweisungen mit den Werten 1, 2, 3 ... (Java)
    • Eval Anweisungen in JS
  • Methoden mit Boolean Parametern
  • Zu lange Klassen oder Methoden
  • Methoden mit drei oder mehr Parametern
  • Methoden mit Parametern die als Ausgabe die dienen

Die Liste ist nicht vollständig, bitte gebt mir Feedback zur Erweiterung der Liste.

Maven Basiskonfiguration

Mit Maven 3 hat sich einiges in den Default-Werten geändert. Trotzdem muss man das JDK und das Encoding explizit in der POM Datei angeben:

... 
        <properties> 
        <jdk.version>1.7</jdk.version> 
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
        </properties> 
    <organization> 
... 

</project>

So sehen dann die Einstellung zum JDK und zum Encoding in Eclipse aus.
Auch ja, und im PMD Plugin sollten auch die richtige JDK Version gesetzt sein:

... 
                         </plugin> 
                            <plugin> 
                                <groupId>org.apache.maven.plugins</groupId> 
                                <artifactId>maven-pmd-plugin</artifactId> 
                                <version>2.5</version> 
                                <configuration> 
                                    <linkXref>true</linkXref> 
                                    <minimumTokens>100</minimumTokens>
                                    <minimumPriority>5</minimumPriority> 
                                    <targetJdk>1.7</targetJdk> 
                                </configuration>
                            </plugin> 
                    </reportPlugins>
                </configuration>
            </plugin> 
        </plugins> 
    </build>