Seit gestern können Entwickler die Developer-Preview des aktuellen Apple Betriebssystems OS X 10.10 aka Yosemite herunterladen. Leider kann man unter Yosemite kein Java SDK installieren. Der Oracle Installer prüft die Versionsnummer nicht korrekt.
Um das JDK trotzdem installieren zu können, muss man temporär – für die Dauer des JDK-Setups – die Versionsnummer von OS X ändern, z.B. von 10.10 auf 10.8.3:

sudo nano -W /System/Library/CoreServices/SystemVersion.plist

Bitte vergesst nicht, anschließend die Datei wieder in den Ursprungszustand zurück zu versetzen.

Maven, JRebel und IntelliJ

In meinem letzten Beitrag habe ich beschrieben, wie man als Java-Entwickler mit Hilfe von JRebel viel Zeit beim Bauen und beim Re-Deployment von Web-Anwendungen sparen kann. Dieser Artikel soll die Konfiguration des JRebel Maven-Plugins in der Entwicklungsumgebung IntelliJ anhand eines Beispiels erläutern.

JRebel Maven-Plugin

Um die Konfigurationsdatei rebel.xml von Maven generieren zu lassen, muss das Plugin entsprechend eingebunden werden. Im Konfigurationsabschnitt wird angegeben, wie das Maven-Plugin die JRebel-Konfigurations-Datei generieren soll, bzw. welche Pfade JRebel zur Laufzeit auf Änderungen überwachen soll.

<build>
    <plugins>
        <plugin>
            <groupId>org.zeroturnaround</groupId>
            <artifactId>jrebel-maven-plugin</artifactId>
            <version>1.1.3</version>
            <executions>
                <execution>
                    <id>generate-rebel-xml</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <alwaysGenerate>true</alwaysGenerate>
                <showGenerated>true</showGenerated>
            </configuration>
        </plugin>
        ...
    </plugins>
    ...
</build>

Durch die Einstellung showGenerated kann man bei der Ausführung des Plugins den Inhalt der generierten Konfigurationsdatei (rebel.xml) sehen und auf Probleme hin überprüfen.

Einhängen in den Start der Anwendung

Da IntelliJ (im Gegensatz zu Netbeans) die Anwendung nicht mit Maven selbst baut, sondern die Klassen selbst kompiliert und lediglich die Informationen zum Projekt aus dem Projekt-Deskriptor (pom.xml) zieht, wird das JRebel-Plugin normalerweise nicht ausgeführt und muss manuell in den Start der Anwendung eingebunden werden. Dies macht man, indem man das JRebel-Plugin im MavenProjects-Tool-Window auswählt und im Kontext-Menü den Punkt Execute Before Run/Debug wählt:

JRebel Plugin in Build-Prozess einhängen
JRebel vor dem Start des Application Servers ausführen

Anpassen der Run-Konfiguration

Damit zunächst die Klassen kompiliert werden, platziert man anschließend die Ausführung des Maven-Plugins in der Run-Konfiguration des Application-Servers zwischen Make und Build Artifact:

Platzieren der Plugin-Ausführung
Platzieren der Plugin-Ausführung

Fazit

Mit dieser Konfiguration kompiliert IntelliJ zunächst alle Klassen nach target/classes, generiert im selben Ordner die JRebel-Konfiguartionsdatei (rebel.xml), und kopiert den gesamten Inhalt des Ordners später in das WebArchive (WAR) der Anwendung. Die Anwendung kann jetzt mit Hilfe des JRebel IDE-Plugins für IntelliJ gestartet werden:

Inhalt des Exploded Web-Archivs
Inhalt des Exploded Web-Archivs
Veröffentlicht unter Java.

Habt ihr euch jemals gefragt, wieviel Zeit ihr beim Entwickeln von Java-Anwendungen mit dem Bauen oder Re-Deployment der Anwendung vergeudet? Das JVM-Plugin JRebel der Firma Zeroturnaround hat sich zur Aufgabe gemacht diese “Wartezeiten” zu eliminieren.

JRebel ist leider nicht gratis, eine Lizenz kostet pro Entwickler und Jahr 265 USD. Ihr könnt JRebel für 14 Tage kostenlos testen, um herauszufinden, ob sich die Investition für euch rentiert. Um euch die Entscheidung zu erleichtern zählt JRebel mit, wieviel Zeit es euch schon gespart hat.

Wie JRebel funktioniert

JRebel ist als Java-Agent umgesetzt.

An agent is deployed as a JAR file. An attribute in the JAR file manifest specifies the agent class which will be loaded to start the agent. For implementations that support a command-line interface, an agent is started by specifying an option on the command-line. Implementations may also support a mechanism to start agents some time after the VM has started. For example, an implementation may provide a mechanism that allows a tool to attach to a running application, and initiate the loading of the tool’s agent into the running application. Quelle: java.lang.instrument

Im Gegensatz zum JVM-Hotswap unterstützt JRebel unter anderem:

  • Hinzufügen und Entfernen von
    • Methoden
    • Konstruktoren
    • Feldern
    • Klassen
    • Annotationen
    • ENUM-Werten
  • Änderung von
    • Statischen Feldern
    • Interfaces

Zusätzlich zum Agenten existieren Plugins für Netbeans, Eclipse, IntelliJ und JDeveloper. JRebel erweitert den JVM-Classloader, so dass dieser in der Lage ist, geänderte Klassen zur Laufzeit auszutasuchen, ähnlich dem Hot-Swap der Instrumenation API. Die von JRebel zu überwachenden Klassen und Ressourcen müssen in einer Datei namens jrebel.xml konfiguriert werden.

JRebel installieren

Am einfachsten kann man JRebel installieren, indem man für seine Entwicklungsumgebung das jeweilige Plugin installiert. JRebel-Plugins sind für Eclipse, Netbeans, IntelliJ und JDeveloper verfügbar.

Unter IntelliJ findet man das Plugin ebenfalls im Plugin-Repository:

jrebel_intellij
Installation des JRebel-Plugins unter IntelliJ

Wenn ihr die 14-Tage-Testversion von JRebel verwendet, könnt ihr jetzt direkt loslegen, ansonsten muss noch eure Lizenz in den Einstellungen des Plugins konfiguriert werden.

Nach der Installation des Plugins stehen euch in der Toolbar der IDE neue Buttons zur Verfügung, mit deren Hilfe ihr euer Projekt mit dem JRebel-Agent starten könnt, vorher muss aber noch das JRebel-Mapping (rebel.xml) erstellt werden.

jrebel_launch_w_rebel
JRebel Buttons in der Toolbar der IDE

Viele Wege führen zur rebel.xml

In der Datei rebel.xml wird konfiguriert, welche Klassen und Ressourcen der JRebel-Agent auf Änderungen hin überwacht. Bei normalen Java-Anwendungen muss sie direkt im Wurzelverzeichnis der Anwendung liegen. Bei Web-Anwendungen muss sie in dem Verzeichnis liegen, in dem auch die kompilierten Klassen liegen (z.B.: WEB-INF/classes).

Beispiel für die Konfiguration einer Web-Anwendung:

<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">

<classpath>
    <dir name="/Users/tim/Projekte/Software/myProject/target/classes">
    </dir>
</classpath>

<web>
    <link target="/">
        <dir name="/Users/tim/Projekte/Software/myProject/src/main/webapp">
        </dir>
    </link>
</web>

 

Ihr könnt die Datei per Hand erstellen, oder sie mit Hilfe des IDE-Plugins generieren lassen. Der Nachteil in beiden Fällen ist, dass die generierten Pfade absolut anstatt relativ anzugeben sind, und die Datei so nicht in die Versionsverwaltung eingecheckt werden sollte.

Zum Glück interpretiert JRebel variable Ausdrücke der Form ${myProject.root}, welche beim Start der Anwendung als System-Property definiert werden können (z.B.: -DmyProject.root=/Users/tim/Projekte/Software/myProject).

Wer sein Projekt mit Maven baut, kann auf ein von Zeroturnaround zur Verfügung gestelltes Maven-Plugin zurückgreifen, welches die Datei im Rahmen des Maven-Builds erzeugt, so dass sie überhaupt nicht in die Versionsverwaltung eingecheckt werden muss.

JRebel in Aktion

Wenn alles soweit konfiguriert ist, kann man sich von langen Build-Prozessen und Re-Deployments verabschieden und seine Anwendungen mit JRebel laufen lassen.

Als kleinen Test kann man eine Java-Anwendung schreiben, die eine Nachricht in einer Endlosschleife in die Konsole schreibt. Ändert ihr nun den Inhalt dieser Nachricht und kompiliert die einzelne Klasse neu, ändert sich die Ausgabe im laufenden System.

public static void main(String[] args) {
    try {
        while (true) {
            Thread.sleep(500);
            System.out.println("Hello World!");
        }
    } catch (Exception ex) {
        System.err.println("Something went wrong: " + ex.getMessage());
    }
}

Fazit

JRebel beschleunigt die Entwicklung größerer Java-Anwendungen spürbar. Durch das Wegfallen der Build-Prozesse und Re-Deployments wird man als Entwickler nicht ständig unterbrochen und kann effizient an der Umsetzung seiner Aufgaben arbeiten. Ob sich die Investition von 265 USD pro Entwickler lohnen, kann man sich selbst ausrechnen. Desto länger es dauert, eine Anwendung zu bauen und zu deployen, desto schneller hat sich JRebel bezahlt gemacht. In meinem Fall hat JRebel schon über einen Tag an Zeit eingespart.

Weitere Pluspunkte für JRebel sind die breite Unterstützung von IDEs, die Verfügbarkeit eines Maven-Plugins, das sehr aktive Forum sowie die ausführliche Dokumentation der Software.

Als Nachteil ist meiner Meinung nach lediglich die etwas umständliche Konfiguration im Rahmen eines Maven-Builds zu nennen, wenn die IDE Maven nicht selbst zum Build der Anwendung verwendet. Zu diesem Thema werde ich demnächst noch einen Beitrag verfassen.

Veröffentlicht unter Java.

Das Javamonster ist wieder online! Hier folgen demnächst natürlich weitere Beiträge. Momentan teste ich, inwiefern sich Markdown zum Verfassen der Blog-Beiträge eignet. Diesen Text habe ich mit Byword geschrieben und ihn anschließend über die Publish-Funktion des Editors veröffentlicht.

Für einen Java-Blog ist natürlich wichtig zu wissen, wie sich das Plugin bei Code-Abschnitten verhält:

System.out.println("Hello World");
return 0;

Wenn alles geklappt hat, werde ich Beiträge in Zukunft nur noch in Markdown verfassen.