Quarkus: Der Blick über den Tellerrand

Seite 6: Externe Konfiguration

Inhaltsverzeichnis

Im Zusammenhang mit nativer Kompilierung verdient auch die externe Konfiguration eine nähere Betrachtung. Das SmallRye-Konfigurationsframework von Quarkus sieht hierfür drei Phasen vor:

  1. BUILD_TIME: Konfiguration, die nur zur Build-Zeit zur Verfügung steht.
  2. BUILD_AND_RUN_TIME_FIXED: Konfiguration, die den Build-Prozess beeinflusst, sich aber auch zur Laufzeit auslesen lässt.
  3. RUN_TIME: Konfiguration, die nur zur Laufzeit und während der statischen Initialisierung zur Verfügung steht und auch neu geladen wird.

In der Neo4j-Extension kommt vornehmlich RUN_TIME zum Einsatz, da Datenbank-URLs und Connection-Pool-Einstellungen zu konfigurieren sind, deren Werte sich von Start zu Start ändern können. Ein typisches Beispiel für eine Konfiguration zur Build-Zeit ist ein Treiber für eine relationale Datenbank. Der ist im Binary auszutauschen, bevor eine Dialect-Einstellung im ORM überhaupt erfolgen kann.

Quarkus macht es leicht, Anpassungen für die SubstrateVM bereitzustellen. Zur Build-Zeit steht das SubstrateConfigBuildItem zur Verfügung, zur Laufzeit lassen sich die SubstrateVM-eigenen Ersetzungen nutzen. Mit @TargetClass, @Substitute und @Delete stellt Graal im SubstrateVM-Modul mächtige Annotationen bereit, über die sich methodenscharf Dinge auf der GraalVM austauschen lassen. Im Beispiel der Neo4j-Erweiterung lässt sich daher das eingebettete (shaded) Netty-Modul, das der Neo4j-Treiber für die Low-Level-Verbindung einsetzt, entsprechend anpassen.

Eine wichtige, externe und binäre Abhängigkeit ist die Unterstützung des SSL-Protokolls. Dessen Bedeutung unterstreichen die Quarkus-Macher mit den Worten: "We are quickly moving to an SSL-everywhere world, so being able to use SSL is crucial." So schnell dieser Satz ausgesprochen ist, so schwierig ist seine Umsetzung. Java erfordert für SSL-Unterstützung die SunEC-Bibliothek. EC steht in diesem Fall für Elliptic-Curve-Provider. Diese Bibliothek wird mit dem JDK ausgeliefert, findet aber nicht per Default den Weg ins native Image – unter anderem, weil sie es um rund 9 MByte vergrößert.

Alle erforderlichen Schritte, um SSL-Unterstützung sowohl für Clients als auch für Server in ein Quarkus-Image zu kompilieren, lassen sich händisch erledigen – es bleibt aber ein aufwendiger Vorgang. Daher stellt Quarkus das ExtensionSslNativeSupportBuildItem zur Verfügung, das auch in der Neo4j-Extension zum Einsatz kommt. Damit lässt sich signalisieren, dass eine Erweiterung SSL benutzen möchte.

Nichtsdestotrotz muss eine Erweiterung darauf reagieren können, ob SSL verfügbar ist oder nicht. Quarkus stellt dazu statische Methoden in io.quarkus.runtime.ssl.SslContextConfiguration zur Laufzeit zur Verfügung. Zusammen mit der Utility-Klasse org.graalvm.nativeimage.ImageInfo der GraalVM lassen sich entsprechende Szenarien erkennen und behandeln. Die Neo4j-Erweiterung muss zum Beispiel den verschlüsselten Transport abschalten, wenn sie in einem nativen Image läuft, aber kein SSL zur Verfügung steht. Sie loggt aber eine – hoffentlich nicht zu übersehende – Warnung, da Neo4j dringend davon abrät, Client-Server-Kommunikation unverschlüsselt zu betreiben.

Das in der Java-Welt immer wieder diskutierte Problem der Injection über Konstruktorparameter betrachten einige als hinreichend gelöst. Das gilt zumindest so lange, wie sich außen herum ein orchestrierender Container findet.

Für Quarkus ist das CDI 2.0 – aber in einer speziellen, Build-Zeit-orientierten Form. Die Quarkus-CDI-Variante "ArC" ist jedoch nicht vollständig CDI-kompatibel. Insbesondere alle CDI-Features, die auf portablen Extensions aufbauen, sind Runtime-Konstrukte und stehen somit dem Ziel entgegen, Beans und Abhängigkeiten zwischen Beans bereits zur Build-Zeit zu analysieren und zu indizieren. Darüber hinaus unterstützt ArC auch weder Decorators noch @ConversationScoped.

Punkten kann die CDI-Umgebung jedoch damit, dass sie zum Start nur noch die serialisierten Metadaten lesen und einige interne Strukturen aufbauen muss. Zur Laufzeit schließlich benötigt die Anwendung nur noch ein Bruchteil der Logik einer vollständigen CDI-Implementierung wie Weld. Zur Build-Zeit gilt das natürlich nicht, allerdings ist das Programm wird ja auch nur einmal zu bauen.

Spring-Entwickler dürften sich darüber freuen, dass ArC keine Default-Konstruktoren vorschreibt und Bean-Abhängigkeiten daher final sein können und sich über einen Constructor statt durch "Magie" bereitstellen lassen. Quarkus-Services sind damit oftmals genauso leicht zu testen wie Spring-Services, ohne aufwendig einen Container oder Application-Service starten oder ein Werkzeug wie Arquillian nutzen zu müssen.