Die Lombok Anwendung kann nicht gestartet werden

Wer neuere Java Features einsetzt und daher neuere Java Versionen verwendet, kommt oftmals mit neuen Fehler die mit dem Modulsystem von dem Projekt Jigsaw zusammenhängen.

Ich verwende gerne das Lombok und auch hier zeigen sich immer noch einmal hier und dort einige Fehler die auftauchen können. Sollte Euer Programm mit folgender Fehlermeldung abbrechen:

Error occurred during initialization of boot layer
java.lang.module.ResolutionException: Module lombok does not read a module that exports org.mapstruct.ap.spi

So fehlt Lombok eine Dependency. Es muss org.mapstruct:mapstruct-processor mit aufgenommen werden. Siehe issue 2125

dependencies {
    // fix for Lombok see https://github.com/rzwitserloot/lombok/issues/2125
    implementation 'org.mapstruct:mapstruct-processor:1.3.1.Final'
}

Jetzt sollte das Programm inklusive Lombok normal gestartet werden können.

Build Environment anzeigen

Welche Klassen sind im Classpath während des Buildvorgangs?

jre11 ./gradlew buildEnvironment

jre11 ist ein kurzes Shellskript welches mir die Java Umgebung in der Version 11 für das Programm zur Verfügung stellt und ist daher optional.

Welche Klassen werden in einer bestimmten Konfiguration geladen?

Gradle bindet je nach Aufgabe unterschiedliche Klassen ein. Welche sind diese? Das ist zum Beispiel die Frage die man sich stellt, wenn die Ausführung des Code Generators von Jooq unter JDK 11 nicht funktioniert.

Mit –configuration kann man den Dependency Tree auf eine Konfiguration einschränken. Hier ist es also die jooqRuntime die uns interressiert.

jre11 ./gradlew dependencies --configuration jooqRuntime

> Task :dependencies

------------------------------------------------------------
Root project
------------------------------------------------------------

jooqRuntime - The classpath used to invoke the jOOQ generator. Add your JDBC drivers or generator extensions here.
+--- org.jooq:jooq-codegen -> 3.11.5
|    +--- org.jooq:jooq:3.11.5
|    |    \--- javax.xml.bind:jaxb-api:2.2.12 -> 2.3.1
|    |         \--- javax.activation:javax.activation-api:1.2.0
|    \--- org.jooq:jooq-meta:3.11.5
|         \--- org.jooq:jooq:3.11.5 (*)
+--- org.xerial:sqlite-jdbc:3.23.1
+--- com.sun.xml.bind:jaxb-core:2.3.0.1
\--- com.sun.xml.bind:jaxb-impl:2.3.0.1

(*) - dependencies omitted (listed previously)

In dem Beipiel benötigt der Code Generator JAXB, welche ja aus dem JDK entfernt worden ist. So kann überprüft werden, ob die Klassen geladen werden.

Die Ausgabe des Logos von Jooq verhindern

Beim Starten eines Queries wird normalerweise das Logo von Jooq ausgegeben. Das ist auch nicht weiter schlimm, es ist nur beim Debuggen der Anwendung manchmal ein wenig störend, weil es viel Platz auf der Konsole einnimmt.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@  @@        @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@        @@@@@@@@@@
@@@@@@@@@@@@@@@@  @@  @@    @@@@@@@@@@
@@@@@@@@@@  @@@@  @@  @@    @@@@@@@@@@
@@@@@@@@@@        @@        @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@        @@        @@@@@@@@@@
@@@@@@@@@@    @@  @@  @@@@  @@@@@@@@@@
@@@@@@@@@@    @@  @@  @@@@  @@@@@@@@@@
@@@@@@@@@@        @@  @  @  @@@@@@@@@@
@@@@@@@@@@        @@        @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  Thank you for using jOOQ 3.11.9

Dank geht an dieser Stelle an Lukas Eder für dieses tolle Werkzeug.

Wie kann nun das Logo abgeschaltet werden? Dazu muss nur die Property org.jooq.no-logo auf true gesetzt werden. Ich löse das in dem ich eine Klasse JooqConfig mit einem Bean erstelle. Die Komponente wird so beim Component Scan gefunden und die Property gesetzt, sodass beim Starten kein Logo angezeigt wird.

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class JooqConfig {
    @Bean
    private void disableLogo() {
        System.setProperty("org.jooq.no-logo", "true");
    }
}

Credentials auslagern

Neben der Möglichkeit die Credentials mit dem Gradle Plugin Credentials zu verwalten, kann man auch zum Beispiel dieses in eine weitere Datei auszulagern. Hierfür bietet sich YAML an.

Hier die jooq.yaml

---
jdbc:
  password: secret
  username: usr

In dem Buildscript jooq.gradle lesen wir die Daten aus dem YAML ein. Das SnakeYaml nutze ich hierfür um die cfg zu definieren.

...
jooq {
  def cfg = new org.yaml.snakeyaml.Yaml().load(new File("" + rootProject.projectDir + "/jooq.yml").newInputStream())
...

Weiter unten im Abschnitt xxx können jetzt die Credentials aus dem jooq.yaml angegeben werden…

...
    jdbc {
      driver = 'org.mariadb.jdbc.Driver'
      url = 'jdbc:mariadb://server:3306/database'
      username = cfg.jdbc.username
      password = cfg.jdbc.password
    }
...

Codepfade

In einem Projekt das für Eingangsdaten sehr viele unterschiedliche Parser verwenden muss, ist es nur natürlich das wenn dieses in einer Klasse geschehen würde, dass das sehr unübersichtlich wird. Daher ist es besser, wenn man die Ganzheit in kleinere separate Parserklassen splittet.

Vor Spring

Nach diesem Schema bin ich in dem Projekt auch vorgegangen und habe für jede Gruppe einen eigenen Parser geschrieben. Alle Parser implementieren das Interface Parser, sodass sich folgender Code ergab:

//
// Instantiate class and execute parse
//
try {
    Class<?> c = Class.forName("de.pfau.parser.Parser00001");

    try {
        Parser p = (Parser) c.getDeclaredConstructor().newInstance();
        autowireCapableBeanFactory.autowireBean(p);

        p.parse();
    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
        throw new Exception ...
    } 
} catch (ClassNotFoundException e) {
    log...
}

Da das Projekt noch aus einer Zeit stammt in der es noch nicht mit Spring kontakt hatte, kommt hier die newInstance() Methode zum Einsatz. Damit in den Klassen auch das Autowiring weiterhin funktioniert, muss nach der Verwendung von DI mit autowireCapableBeanFactory.autowireBean(p) Spring hierüber in Kenntnis gesetzt werden. Ansonsten haben die Autowired Felder null Werte.

Die Umsetzung mit Spring

Spring bringt hierfür Frist Class Support mit, da das grundlegend für das Dependency Injection ist.

Mit dem ClassPathScanningCandidateComponentProvider kann man den Classpath durchsuchen. Beim Instanzieren des Objektes kann ein Parameter useDefaultFilters angegeben werden. Setzt man ihn auf false, dann hat man eine leere Filterkette.

ClassPathScanningCandidateComponentProvider scanner =
        new ClassPathScanningCandidateComponentProvider(false);

Als nächstes fügen wir einen neuen Includefilter ein. Es gibt verschiedene Filter die eingefügt werden können (siehe TypeFilter). Für meine Zwecke eignet sich hier der RegexPatternTypeFilter. Als Parameter übergeben wir einen kompilierten RegEx Ausdruck, sodass Standard Java RegEx zum tragen kommt.

Die Klassen heißen alle ParserXXXXX. Wobei XXXXX für fünf stellige Dezimalzahl steht.

scanner.addIncludeFilter(new RegexPatternTypeFilter(Pattern.compile("de.pfau.parser.*Parser\\d{5}")));

Über die Methode scanner.findCandidateComponents kann man eine gefilterte Liste der Kandidaten erhalten. Der Rest ist identisch zur alten Version.

Damit das Autowiring von autowireCapableBeanFactory funktioniert, darf der Code nicht im Konstruktor ausgeführt werden. Hierzu verwende ich die @PostConstruct Annotation. Die Instanzen der Parser werden in einer HashMap gespeichert, um so später darauf zuzugreifen.

ClassPathScanningCandidateComponentProvider scanner =
        new ClassPathScanningCandidateComponentProvider(false);

scanner.addIncludeFilter(new RegexPatternTypeFilter(Pattern.compile("de.pfau.parser.*Parser\\d{5}")));

for (BeanDefinition bd : scanner.findCandidateComponents("de.pfau.parser")) {
    //
    // Instantiate parser and parse loaded document
    //
    try {
        var classname = bd.getBeanClassName();
        Class<?> c = Class.forName(classname);

        try {
            Parser p = (Parser) c.getDeclaredConstructor().newInstance();
            autowireCapableBeanFactory.autowireBean(p);
            map.put(classname, p);

            log.info("parser " + classname + " successfuly loaded");
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
            throw new Exception...
        } 
    } catch (ClassNotFoundException e) {
        log.severe("could not load class");
    }
}

Am 20.12.2018 wurde die aktuellste Version der Spring Tools Suite 4.1.0 veröffentlicht.

Changelog für Spring Tools Suite 4.1.0

Wie immer wurden Fehler behoben und Aktualisierungen eingefügt. Nennenswertes ist diesmal das Eclipse Update. Eclipse erscheint seit einiger Zeit in einem 3 monatigen Rhythmus und so war Eclipse bei der Aktualisierung auch mit dabei. Spring Tools Suite basiert jetzt auf Eclipse 2018-12.

Weitere Änderungen liste ich hier kurz auf:

Spring Boot

  • Mit diesem Release ist erstmals eine Unterstützung für die Autovervollständigung (content-assist) für Spring Data Repository definitionen mit dabei.
  • Die Live Hover Hyperlinks zu den Javatypen funktionieren auch für Projekte die Java 9 oder höher verwenden.
  • Es wurde ein Problem mit beendeten Anwendungen behoben, wenn diese mit JMX über einen SSH Tunnel verbunden sind.

Eclipse

  • Eclipse Javadoc Live Hover ist nun auch ohne eine Abhägigkeit zum spring-boot-actuator wieder verfügbar.
  • Java 11 Support ohne Update vom Eclipse Marketplace
  • Verbesserter Kompatibilitätscheck von JDK Versionen
  • Live Reueast von Reactiven WebFlux Anwendungen können nun auch im Boot Dashboard angezeigt werden.
  • Fehlerbeseitung beim kommentieren mit Hilfe des Shortcuts

Spring Tool Suite mit Gradle unter JDK 11

Im allgemeinen funktioniert die Spring Tool Suite 4 (Version 4.0.2) unter dem aktuellen Java 11 LTS. Leider ist die Erkennung Java Versionen anscheinend sehr fragil, da zum Beispiel die aktuelle Version 11.0.1 nicht erkannt wird.

Dadurch funktioniert das Gradle Tooling (Eclipse Buildship Plugin) nicht und es wird das öffnen eines Gradle Projektes mit einer Fehlermeldung der Editoren quittiert.

An internal error occurred during: "Initializing Java Tooling".
Could not determine java version from '11.0.1'.

Bestimmung der JVM

Unter Arch Linux oder Manjaro werden die verschiedenen Java Versionen parallel unterhalb /usr/lib/jvm abgelegt. Mit dem kleinen Hilfsprogramm archlinux-java kann die Default JVM angezeigt und bestimmt werden. Ist diese nun zum Beispiel auf die aktuelle Version 11 eingestellt, dann läuft auch Eclipse bzw. die RCP und somit auch die Spring Tool Suite unter der JVM. Abhilfe schafft die .ini Datei im Root-Verzeichnis. Hier lässt sich u.a. die zu verwendende JVM angegeben.

[sp@Laptop ~]$ sudo archlinux-java status
Available Java environments:
  java-11-openjdk (default)
  java-8-graal
  java-8-openjdk

Der Parameter vm bestimmt den Pfad zur JVM. Dieser muss unbedingt vor dem Parameter vm-args angegeben werden!

-vm
/usr/lib/jvm/java-8-graal/bin/java
-vmargs
-Dosgi.requiredJavaVersion=1.8

In diesem Beispiel läuft Spring Tool Suite unter der GraalVM, obwohl die Default VM auf JDK 11 zeigt.

Alles passt zusammen

Nun fügen sich alle Puzzelteile zusammen und es läßt sich unter dem aktuellen LTS von Java, dem JDK 11, ein Beispiel mit Hibernate mit SQLite Datenbank, Jooq und Spring Boot 2.1 unter der Verwendung von Gradle als Buildsystem umsetzen. Bis hierhin gab es einige Baustellen, die im Zuge der Modularisierung (Projekt Jigsaw), noch zu beseitigen waren. Jetzt ist eine Umsetzung mit den aktuellsten Versionen möglich und dieses möchte ich hier vorstellen.

Hier die benötigten Komponenten im Einzelnen:

  • Spring Boot 2.1
  • Spring Data JPA (spring-boot-starter-data-jpa)
  • Jooq 3.11.4 (im Spring Boot Starter definiert)
  • Gradle 5.0-RC4
  • sqlite-dialect (Hibernate Dialekt)
  • sqlite-jdbc (Treiber)

Die Demo

Die Anwendung erstellt zwei Invocation Objekte und persistiert sie mit JPA (Hibernate) in der Datenbank. Im Anschluss wird mit Hilfe von Jooq die Tabelle aus SQLite Datenbank wieder gelesen und in Tabellenform auf der Konsole ausgegeben. Das Ganze passiert in der Klasse InitDatabase, die das CommandLineRunner Interface implemenmtiert und somit beim Start der Anwendung ausgeführt wird. Die SQLite Datenbank legt die Daten in der Datei application.db ab. Eine initiale Version ist im Git Repository vorhanden (s.u.).

Ausführen der Anwendung

Der Build wird wie immer mit dem Dreisatz git clone, cd, ./gradlew clean build bootRun angestoßen.

git clone https://mrpeacockgit.duckdns.org:443/Public/spring-hibernate-jooq-sqlite-demo.git
cd spring-hibernate-jooq-sqlite-demo/
./gradlew clean build bootRun

Hier sehen wir den schön formatierten Output von Jooq auf der Konsole.

ACHTUNG: Es muss der Gradle Wrapper unter JDK 11 ausgeführt werden, weil Java 11 als Source- und TargetCompatibility angegeben ist. Wird Gradle z.B. unter Java 8 ausgeführt, dann bricht Gradle den Buildvorgang mit > Could not target platform: ‚Java SE 11‘ using tool chain: ‚JDK 8 (1.8)‘ ab. Hat man keine JDK 11 zur Hand, dann kann Source und Target auf Java 8 reduziert werden, da keine Sprachfeatures von Java 11 genutzt werden.

Import in Eclipse

Damit in Eclipse die Anwendung fehlerfrei ist, müssen 2 Schritte ausgeführt werden.

  • Generierung des Java Codes. Es muss die Generierung der Java Quelltexte, aus dem gegebenen Datenbankschema mit Hilfe des Jooq Code Generators, durchgeführt werden. Der Task generateSpringhibernatesqliteJooqSchemaSource wird von dem Jooq Plugin bereitgestellt.

  • Damit die statischen Importe gefunden werden, müssen sie auch im Eclipse Buildpath vorhanden sein. Dazu muss einmalig der Task eclipse ausgeführt werden.

Jetzt sollte das Projekt fehlerfrei im Eclipse sein.

Die Entität

Die Entity die hier verwendet wird, ist der Demo bedingt, sehr einfach gehalten. Wie immer verwende ich das Project Lombok, um den Code sauber von Boilerplate Code zu halten.

@Entity
@Data
public class Invocation {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private String name;
}

GenerationType

Der GenerationType muss hier auf AUTO stehen, ansonsten wird der Start der Anwendung mit einer Exception quittiert.

Caused by: org.sqlite.SQLiteException: [SQLITE_CONSTRAINT]  Abort due to constraint violation (NOT NULL constraint failed: invocation.id)

Hibernate Schema Erzeugung / Jooq Code Generation

Hier haben wir ein Henne-/Ei-Problem! Der Code Generator von Jooq benötigt eine Datenbank aus der er das Schema ausliest, um den Code zu erzeugen. Im Quelltext wird aber bereits per Import auf generierten Code zugegriffen, was zu einer Fehlermeldung beim Kompilieren während des Builds führen würde. Da die Code Generierung vor der Kompilierung erfolgt, habe ich eine leere Datenbank mit in das Git Repository aufgenommen. Somit kann die Anwendung über den Gradle Build gebaut und auch ausgeführt werden.

Problem der automatischen Schema Generierung

Anhand des oben beschriebenen Henne-/Ei-Problems, sollte eigentlich jedem schnell klar werden, dass das keine Lösung für große Anwendungen ist. Es sollte hier besser auf andere Lösungsansätze ausgewichen werden. Z.B. Flyway als Datenbankschemamigrationstool oder einfach die Verwendung von Spring Boot Bordmitteln (Spring liest schema.sql ein und verarbeitet die SQL Anweisungen).

Jooq Konfiguration

Für das Erstellen der Konfiguration Jooq Code Generator wird das Plugin von Etienne Struder verwendet. Hier in den Beispiel ist nur eine Grundkonfiguration vorgenommen worden. Alle Einstellungsmöglichkeiten die möglich sind, lassen sich über das XSD für Jooq Code Generator erfahren. Das lesen und verstehen des recht umfangreichen XSD ist nicht einfach. Man kann aber z.B. über Visual XSD sich das XSD visualisieren lassen und so den Aufbau schneller verstehen.

Autovervollständigung in Eclipse

Bei der Eingabe in Eclipse werden nicht automatisch die statischen Imports für die generierten Tabellen von Jooq angezeigt. Hier muss man in Eclipse erst den Umweg über eine nicht statischen Import nehmen, um ihn dann per STRG + 1 in einen statischen Import zu überführen.

Beispiel

In der Klasse InitDatabase die den CommadLineRunner implementiert, möchten wir alle Invocations aus der Datenbank listen.

private void listInvocations() {
        ctx.select()
            .from(INVOCATION)
            .fetch()
            .forEach(System.out::println);
    }

INVOCATION ist hier über den statischen Import

import static db.Tables.INVOCATION;

bekannt. Damit die Autovervollständigung funktioniert, muss der Import vorhanden sein. Das heißt erst nach dem man den Import eingefügt hat, lässt sich mit STRG + SPACE das Code-Fragment .from(INVOCATION) einfügen. Das ist nicht sehr effektiv, da man immer erst den Import einfügen muss.

Einstellung der Favoriten

Der Generator von Jooq ist so konfiguriert, dass die Tabelle aus der Datenbank im Java Package de.Tables.* gelistet werden. Die Quelltexte werden außerhalb von main in src/db gespeichert, so dass jederzeit durch löschen von dem Verzeichnis src/db die generierten Quelltext sauber neu erstellt werden können, ohne das alte Artefakte noch verhanden sind.

Man kann Eclipse anweisen, bestimmte static Members anzuzeigen, auch wenn das Import noch fehlt. Und genau das führt hier zum Ziel und erleichtert die Eingabe von Jooq Queries mit der hervorragenden DSL enorm.

In den Präferenzen von Eclipse wählen Sie java –> Editor –> Content Assist –> Favorites und erstellen einen neuen Typen. Hier ist es *db.Tables.**.

Jetzt kann die Eingabe vervollständigt werden, ohne das der Import zuvor vorhanden war

JDK 11

Das JDK 11 war bislang nur als Oracle JDK aus dem AUR-Repository verfügbar. Seit dem 28.10.2018 ist in den normalen Repositories von Manjaro vorhanden, das heißt mit

yaourt --noconfirm -S jre-openjdk-headless jre-openjdk jdk-openjdk openjdk-doc openjdk-src

wird das aktuelle Java 11 als LTS Version installiert.

Weitere Versionen sind mit den jeweiligen Kennzahlen in dem Paketnamen markiert (siehe Arch Wiki).

Welche Java Versionen sind installiert?

Unter Arch basierten Linuxen wird das Handling von Java über ein kleines Helferprogramm gesteuert. Das Programm archlinux-java steuert die installierten JVM auf der Maschine.

archlinux-java status

Listet die installierten Java Versionen auf und zeigt welche Version gerade aktiviert ist.

Wechsel der JVM

Mit archlinux-java set kann die default JVM gewechselt werden.

archlinux-java set java-11-openjdk # wechsel auf JDK 11

Unterschiede Java OpenJDK und Oracle JDK 11

Seit Java 11 gibt keinen funktionalen Unterschied zwischen dem OpenJDK und der Oracle JDK Version mehr. Es muss nur für den Support eine kostenpflichtige Version von Oracle bezogen werden.

Fehlerbild

Beim Starten einer Spring Boot Anwendung unter JDK11 (Java 11 Umgebung) kommt es zu einer Fehlermeldung. Es betrifft auch das letzte Release 2.0.4.RELEASE.

Caused by: java.lang.NullPointerException: null
    at javassist.util.proxy.SecurityActions.setAccessible(SecurityActions.java:103) ~[javassist-3.22.0-GA.jar:na]
    at javassist.util.proxy.DefineClassHelper.toClass3(DefineClassHelper.java:151) ~[javassist-3.22.0-GA.jar:na]
    at javassist.util.proxy.DefineClassHelper.toClass2(DefineClassHelper.java:134) ~[javassist-3.22.0-GA.jar:na]
    at javassist.util.proxy.DefineClassHelper.toClass(DefineClassHelper.java:95) ~[javassist-3.22.0-GA.jar:na]
    at javassist.util.proxy.FactoryHelper.toClass(FactoryHelper.java:131) ~[javassist-3.22.0-GA.jar:na]
    at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:530) ~[javassist-3.22.0-GA.jar:na]
    at javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:515) ~[javassist-3.22.0-GA.jar:na]
    at javassist.util.proxy.ProxyFactory.createClass1(ProxyFactory.java:451) ~[javassist-3.22.0-GA.jar:na]
    at javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:422) ~[javassist-3.22.0-GA.jar:na]
    at org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.postInstantiate(JavassistProxyFactory.java:75) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:162) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:156) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:58) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
    ... 46 common frames omitted

Ohne Änderung läuft die Anwendung unter JDK10 fehlerfrei.

Ursache der NullPointerException

Diese lässt sich auf einen Fehler in javassist zurückführen. Siehe issue 194 für weitere Informationen.

Fehler wurde in neuer GA gefixt

Der Fehler in javassist wurde mit 3.23.1-GA behoben. Als Workaround (dieser kann unerwünschte Seiteneffekte besitzen) kann man die Dependency in dem POM überschreiben.

Gradle

Mit Gradle muss bei der Verwendung des Spring Boot Dependencies Management Plugins im Abschnitt Dependencies javassist eingefügt werden. Das Einfügen überschreibt die impleziete Abhängigkeit von Spring-Boot-Data-JPA.

dependencies {
    // Override javassist version 3.22.0-GA from spring-boot-starter-data-jpa.
    // This fixes javassist runtime error with JDK11.
    // See https://github.com/jboss-javassist/javassist/issues/194
    compile('org.javassist:javassist:3.23.1-GA')
}

Mit gradle dependencies kann die Änderung leicht geprüft werden:

./gradlew clean dependencies | grep javassist
|    |    +--- org.javassist:javassist:3.22.0-GA -> 3.23.1-GA
\--- org.javassist:javassist:3.23.1-GA
|    |    +--- org.javassist:javassist:3.22.0-GA -> 3.23.1-GA
+--- org.javassist:javassist:3.23.1-GA
|    |    +--- org.javassist:javassist:3.22.0-GA -> 3.23.1-GA
+--- org.javassist:javassist:3.23.1-GA
|    |    +--- org.javassist:javassist:3.22.0-GA -> 3.23.1-GA
+--- org.javassist:javassist:3.23.1-GA
|    |    +--- org.javassist:javassist:3.22.0-GA -> 3.23.1-GA
+--- org.javassist:javassist:3.23.1-GA
|    |    +--- org.javassist:javassist:3.22.0-GA -> 3.23.1-GA
+--- org.javassist:javassist:3.23.1-GA
|    |    +--- org.javassist:javassist:3.22.0-GA -> 3.23.1-GA
+--- org.javassist:javassist:3.23.1-GA
|    |    +--- org.javassist:javassist:3.22.0-GA -> 3.23.1-GA
+--- org.javassist:javassist:3.23.1-GA
|    |    +--- org.javassist:javassist:3.22.0-GA -> 3.23.1-GA
+--- org.javassist:javassist:3.23.1-GA

Ein aktueller Status von dem Projekt Lombok

Hier ein kurzer Zwischenbericht über den aktuellen Stand JDK, Eclipse (STS4 Version), Gradle mit Lombok.

JDK10

Als Vorbereitung Java 10 installieren…

yaourt --noconfirm -S jre10-openjdk-headless jre10-openjdk jdk10-openjdk openjdk10-doc openjdk10-src

08.08.2018

Eclipse STS4 in M12 ist entpackt. Ich habe die aktuellste Version von Lombok mit dem integrieren Installer installiert. Auf dem Arch Linux System wird hier der absolute Pfad eingetragen. Leider gibt es folgenden Fehler:

16.08.2018

Hurra! Es ist geschafft. Endlich läuft Eclipse mit Gradle und Lombok unter einer Java Version > 8 !!! Aktuell verwende ich das letzte Milestone-Release M14 der STS14 mit der letzten Version v1.18.2 und der letzten Gradle Version 4.9.

JDK11

16.08.2018

Achtung: es gibt kein offizielles Paket für die EA-Version. Man findet sie auch nicht so leicht im AUR, da dass Paket jdk-devel heißt. Besser wäre jdk11-ea. Dann würde mann es mit yaourt -s jdk11 auch als EA finden.

yaourt --noconfirm -S jdk-devel
sudo archlinux-java set java-11-jdk

Auch hier gibt es offenbar keine Probleme mehr…