Tomcat 10 bringt EE9 – und den Big Bang weg von javax.servlet.*

Bei der kleinen Docker-Bastelei im Anti-DoS-Valve-Projekt wollte ich das Projekt ‚gerade mal eben‘ auf Tomcat 10 hochziehen und bin direkt über eine wesentliche Änderung gestolpert, die mir bisher entgangen war:

Was bisher

import javax.servlet.*;

war muss nun

import jakarta.servlet.*;

sein 😮 Da sich das mit meinen Gehversuchen mit Docker überschnitt hat es einen Moment gebraucht um zu verstehen, wo eigentlich das Problem lag…

Was ist der Hintergrund

Natürlich das Urheberrecht und Oracle’s Wille die mal mit dem Kauf von SUN an Java gewonnenen Rechte auf keinen Fall Preis zu geben. Die entscheidenden Weichenstellungen sind dabei schon weit vor der Niederlage gestellt worden, die Oracle letztlich Anfang April 2021 in der Auseinandersetzung mit Google über die Java Nutzung in Android erlitten hat. Hier sind ein paar Quellen:

Der Artikel der Eclipse Foundation enthält diese Passage, die das Ende der Verwendung von javax.* ankündigt:

‘..Eclipse and Oracle have agreed that the javax package namespace cannot be evolved by the Jakarta EE community. As well, Java trademarks such as the existing specification names cannot be used by Jakarta EE specifications.’

Selbst der Name Java darf nicht mehr in den Spezifikationen wie JPA verwendet werden, die die Eclipse Foundation weiterentwickelt. Bei der Frage wie es nach EE8 weitergehen kann deutet sich die Entwicklung schon an:

‘What happens beyond Jakarta EE 8?

The guiding principle for Jakarta EE 9 will be to maximize compatibility with Jakarta EE 8 for future versions without stifling innovation.  This will most likely involve two key topics: migration of some or all of the Jakarta EE specification source to a new namespace for future evolution; means to provide backwards compatibility with javax at a binary level, allowing old applications to run on Jakarta 9 implementations with some form of build or runtime tooling.

So while there will be a point in time where future versions of specifications will have to go through a source code incompatible change with respect to the previous javax based packages, this will be a straightforward transformation.’

Eine Frage war es dann ob die Migration weg von javax.* inkrementell erfolgen würde – also nur der Teile, die Veränderungen unterliegen – oder als Big Bang gemacht wird. Die Antwort liefert der vergleichende Blick in die Javadocs der Servlet 4 und 5 APIs:

Der Post Jakarta EE 9 Delivers the Big Bang im Life at Eclipse Blog beschreibt das Vorgehen noch einmal zum Start von EE9. Die Logik dahinter – es wird ein klarer Schnitt gemacht – finde ich durchaus nachvollziehbar. Aber was macht man nun mit Anwendungen, die auf großen Codebasen sitzen und diverse externe Pakete verwenden, die alle noch nicht umgestellt sind?

Was tun mit den Altanwendungen (in Tomcat)

Alles was vor EE9 an Webanwendungen entwickelt wurde ist damit nun plötzlich eine migrationsbedürftige ‚Altanwendung‘. Aber selbst die Befürworter*innen des Big Bangs erkennen an, dass das JEE Ökosystem einfach zu groß ist, als das man innerhalb kürzester Zeit von allen Anbieter*innen von Servern, Anwendungen, Paketen ein Mitziehen erwarten könnte. Es sind also Übergangslösungen gefragt.

In des Migrationshinweisen von Tomcat 10 widmet sich ein eigener Abschnitt dem Thema und es zeigt sich, dass das Tomcat Migration Tool for Jakarta EE, welches im Kern den Eclipse Transformer enthält, hier eingebaut ist und man seine Anwendungen offenbar ohne Umbauten weiterhin deployen kann. Aber nicht mehr in der gewohnten Weise:

Bei einem Test mit einer winzigen JEE Anwendung (nur ein Servlet) in deren pom.xml die Servlet API 4 referenziert wird

                <dependency>
                        <groupId>javax.servlet</groupId>
                        <artifactId>javax.servlet-api</artifactId>
                        <version>4.0.1</version>
                        <scope>provided</scope>
                </dependency>

scheint das Deployment durch Kopieren der WAR-Datei in den <CATALINA_HOME>/webapps-Order zunächst wie gewohnt zu arbeiten, die Datei wird entpackt und die statische Startseite wird im Browser angezeigt. Der Aufruf des Servlets scheitert aber mit einer 404-Meldung, jedoch ohne eine Fehlermeldung in den Tomcats-Logs 🤔

Das Deployment funktioniert erst, wenn man wie in der Migrationshilfe beschrieben einen <CATALINA_HOME>/webapps-javaee-Order anlegt und die WAR Datei dort platziert. Dann passiert beim Start das hier:

Tomcat 10 migriert beim Start eine EE8 Anwendung nach EE9

Tomcat bemerkt die ‚Altanwendung‘ und migriert sie in die neue Welt. Das Ergebnis befindet sich dann im üblichen <CATALINA_HOME>/webapps-Order. Bei der Minianwendung hat das problemlos funktioniert. Die spannende Frage ist dann wie es sich mit komplexeren Anwendungen verhält.

Noch nicht klar geworden ist mir aber ob man bei der Weiterentwicklung von Altanwendungen nun erst einmal auf Tomcat Versionen <10 festgelegt ist, oder ob es auch da einen Weg gibt mit dem aktuellen Tomcat weiter zu machen.

Fazit

Das sich die Eclipse Foundation dazu entschieden hat die Verbindungen zu Oracle und den Teilen von Java, bei denen Oracle sehr viel Wert darauf legt die eigenen Urheberrechtsansprüche zu betonen, ist sicher ein richtiger Schritt. Aber es wird weltweit viel Arbeit machen die betroffenen Systeme auf allen Ebene darauf umzustellen.

Bis sich dieser Aufwand dann gelohnt haben wird, wird viel Zeit ins Land gehen. Und wer weiß ob es nicht Fälle gibt in denen dieser Aufwand das noch fehlende Argument liefert sich von Java im Backend abzuwenden.

Release 1.3.0 des Anti-DoS-Valves – mit Docker

Heute habe ich ein neues Release des Apache Tomcat Valves zur Begrenzung von massenhaften Zugriffen auf Tomcat Server auf Github veröffentlicht. Funktional hat sich dabei nicht viel getan, abgesehen von der Anpassung des Codes an Tomcat 10 und den dort nun anders benannten Servlet API Paketen. Aber dazu schreibe ich noch etwas in einem anderen Post. Die wesentliche Verbesserung liegt hier:

Docker Logo

Im /docker-Unterzeichnis des Projekts findet sich nun eine Docker-Konfiguration, mit der sich sehr einfach ein Tomcat 10 Server mit einkonfiguriertem Valve und einer Testmöglichkeit als Containerinstanz starten lässt. Entweder um das Ganze einmal schnell auszuprobieren, oder um bei eigenen Weiterentwicklungen ohne Basteleien und manuelles Hin- und Herschieben von JARs und Konfigurationen schnell die letzte Version des Valves direkt ausführen zu können.

Ich bin noch nicht so routiniert mit Docker, daher gehe ich hier einmal die Inhalte des /docker-Verzeichnisses durch und falls eine Leserin oder ein Leser dazu Verbesserungsvorschläge hat freue ich mich:

Dockerfile

Es ist nahezu leer:

FROM tomcat:10-jdk16-corretto

Nur das Tomcat 10 Image von Dockerhub wird referenziert. Ich hätte hier schon die angepasste server.xml oder das Valve Jar in das Image bringen können, aber gerade für Entwicklungszwecke erschien es mir zu umständlich jedes Mal ein neues Image zu bauen. Tatsächlich hätte es das Dockerfile im Moment gar nicht gebraucht, es hilft in der jetzigen Form nur die unten beschriebenen Kommandozeilen von späteren Änderungen des verwendeten Tomcat Images zu isolieren.

Falls man aber ein Tomcat Image für produktive Zwecke bauen möchte, in dem das Valve schon enthalten ist, wäre es sicher eine gute Idee die Valve Anpassungen bereits hier zu integrieren und mindestens das Jar schon in das Image aufzunehmen.

README.md

Hier sind die Kommandos enthalten, die es braucht um den Tomcat samt Valve zu starten. Interessant ist dabei eigentlich nur dieses Kommando:

docker run \
   --mount type=bind,source="%cd%"/../target/anti-dos-valve-1.3.0.jar,target=/usr/local/tomcat/lib/anti-dos-valve.jar,readonly  \
   --mount type=bind,source="%cd%"/server.xml,target=/usr/local/tomcat/conf/server.xml,readonly  \
   --mount type=bind,source="%cd%"/advdemo/,target=/usr/local/tomcat/webapps/advdemo/,readonly \
   --name AntiDoSValveDemo \
   -p 8013:8080 \
   -it antidosvalve_demo

In den drei mount-Anweisungen werden drei Dateien/Order aus dem Host-System in den Container abgebildet und überdecken dabei die schon vorhandenen Dateien im Container:

  • JAR: Das Jar, welches sich eins höher im /target-Verzeichnis befindet, wird in das /lib-Verzeichnis des Tomcats im Container gebracht und steht dem Server damit zur Verfügung. Das Jar muss natürlich vorher schon gebaut worden sein
  • server.xml: Hier wird eine angepasste Version der server.xml, die sich im Tomcat Image befindet, in den Container gesetzt. Dadurch werden die Valve Konfigurationen wirksam
  • /advdemo: Dieser Ordner enthält eine JSP – siehe unten – und wird als Webapp eingebracht, die der Tomcat klaglos ausführt

Alle mounts werden als readonly deklariert, damit in keinem Fall der Server im Container etwas zurückschreiben kann. mounts benötigen absolute Pfad, damit die Anweisung trotzdem immer funktioniert wird der aktuelle Pfad eingesetzt. Hier für Windows, für Linux sind entsprechende Anpassungen notwendig.

Es wird ein Portmapping gemacht, dabei wird nicht der sonst übliche Port 8080 verwendet, um nicht in Konflikt mit anderen auf dem Host laufenden Servern zu kommen.

Schließlich wird ein Name vergeben, unter dem sich der Container ansprechen lässt. Das verhindert, dass man einen beendeten Container einfach erneut starten kann und ihn erst entfernen muss. Ich bin mir noch nicht sicher, ob ich das wirklich praktisch finde.

server.xml

Die server.xml Datei, mit der Tomcat 10 Distribution mitgeliefert wird, um 2 Valve Konfigurationen ergänzt. Wenn man alternative Konfigurationen ausprobieren will kann kann man einfach die Datei bearbeiten und den Container neu starten.

/advdemo-Ordner

Hier ist nur eine JSP enthalten, die für die Demonstration des Marking Modes des Valves benötigt wird. Sie wird als eigene Webapp in den Tomcat gebracht und ist dann dort ausführbar.

Schnelle Iterationen

Durch die Containerlösung, die sich in Sekunden hochfährt, ist es einfach neue Versionen des Valves, der server.xml oder auch der JSP auszutesten, deutlich schneller als mir das bisher mit einer separaten Tomcat Instanz möglich war. Auch der rasche Wechsel zwischen unterschiedlichen server.xml Dateien ist einfach, man muss sich nur eine alternative Kommandozeile zurechtlegen. Und dafür ist keine ‚Magic‘ mit in Eclipse und Co. integrierten Tomcats notwendig, alles sind einfache Kommandozeilen, die sich schnell ausführen und und anpassen lassen.

Mir gefällt das gut 😀🐳

Java APIs in Android: Der Rechtsstreit ist entschieden

Die Auseinandersetzungen zwischen Oracle und Google um Google’s Nutzung von Java APIs in Android sind offenbar vorbei: Das Oberste Gericht der USA hat entschieden, dass diese Nutzung unter den Fair Use fällt. Neben IT und Tech Seiten wie Heise und The Verge haben auch SPIEGEL und FAZ direkt darüber berichtet. Das Urteil ist spannend zu lesen:

Fast 11 Jahre vor Gericht

Zusammenfassungen der verschiedenen Etappen dieser Auseinandersetzung zwischen den beiden IT Giganten lassen sich an verschiedenen Stellen im Netz finden, für mich verbindet sich die Anfangsphase noch mit intensiven Diskussionen darüber beim schon lange eingestellten Google+. Dort haben sich naturgemäß die eher Google-freundlichen Diskutanten eingefunden, aber die Frage ob Google sich unrechtmäßig der kreativen Leistung anderer bedient hat, oder ob Oracle mit seinem Versuch Programmierschnittstellen nachträglich als urheberrechtlich geschützte Werke zu interpretieren die Softwarewelt aus ihren gewohnten Angeln hebt, war heiß umstritten. Ich war da eher auf der Seite, die Oracles Klagen strikt ablehnte. Die folgende Karikatur aus dieser Zeit zu den Organisationsstrukturen verschiedener IT Unternehmen ist mir daher direkt wieder eingefallen:

Humoristische Organisationscharts verschiedenen US IT Unternehmen: Apple, Google, Microsoft, Oracle, Facebook, Amazon
Comic von Manu Cornet

Interessante Auszüge aus dem Urteil

Das Urteil kann man hier als PDF vom Heise Verlag abrufen. Es ist durchaus lesenswert und auch ohne umfangreiche juristische Kenntnis durchaus verständlich. Ein paar Abschnitte habe ich mir rauskopiert:

‚To decide no more than is necessary to resolve this case, the Court assumes for argument’s sake that the copied lines can be copyrighted, and focuses on whether Google’s use of those lines was a “fair use.”

Das oberste Gericht hat also die für die IT Welt – insbesondere auch die Open Source Community – wesentliche Frage ob eine API überhaupt ganz grundsätzlich ein Urheberrecht haben kann, nicht entschieden. Und da hatte Oracle in früheren Instanzen einen Etappensieg errungen. Auch wenn die Oracles Niederlage nun vielleicht einen abschreckenden Effekt hat, grundsätzlich ist damit zumindest in den USA wohl mit weiteren Verfahren zu rechnen, in denen API-Nutzungen Anlass zu Gerichtsverfahren geben. Und nicht jede Beklagte ist so mächtig und wohlhabend wie Google.

‚Computer programs differ to some extent from many other copyrightable works because computer programs always serve a functional purpose.‘

Das Gericht hat sich aber Gedanken dazu gemacht, in wie weit das Urheberrecht eigentlich auf Software angewendet werden kann.

‚As a result, this code is different from many other types of code, such as the code that actually instructs the computer to execute a task. As part of an interface, the copied lines are inherently bound together with uncopyrightable ideas (the overall organization of the API) and the creation of new creative expression (the code independently written by Google). Unlike many other computer programs, the value of the copied lines is in significant part derived from the investment of users (here computer programmers) who have learned the API’s system.

Hier macht das Gericht zum ersten, aber nicht zum letzten Mal, einen interessanten Punkt: Eine API – zumindest die, um die es hier konkret geht – gewinnt dadurch an Wert, dass Programmierer*innen sie erlernen und dafür Zeit investieren. Damit wird die Wertgenerierung nicht mehr allein den Erschaffer*innen zugebilligt, sondern jede Java Entwickler*in, die diese APIs gelernt hat, vergrößert durch ihr Investment den Wert der Sprache.

‚Google copied only what was needed to allow programmers to work in a different computing environment without discarding a portion of a familiar programming language.‘

Auch hier wird wieder der Verweis auf das existierende Knowhow von Entwickler*innen gemacht und das es Googles Vorgehensweise diesen ermöglicht habe ihr Wissen nun in einem weiteren Umfeld zu nutzen. Dieses Wissen also wertvoller wurde.

‚Google copied approximately 11,500 lines of declaring code from the API, which amounts to virtually all the declaring code needed to call up hundreds of different tasks. Those 11,500 lines, however, are only 0.4 percent of the entire API at issue, which consists of 2.86 million total lines. In considering “the amount and substantiality of the portion used” in this case, the 11,500 lines of code should be viewed as one small part of the considerably greater whole. As part of an interface, the copied lines of code are inextricably bound to other lines of code that are accessed by programmers. Google copied these lines not because of their creativity or beauty but because they would allow programmers to bring their skills to a new smartphone computing environment.‘

Und noch einmal der Verweis auf die Möglichkeit für Entwickler*innen ihr Knowhow in einer neuen Umgebung zu nutzen. Verbunden mit der Entlastung von Google, die eine vergleichsbare API oder gleich eine ganze Programmiersprache auch leicht hätten selbst entwickeln können (was sie in späteren Jahre mit Dart und Go taten).

‚The fourth statutory factor focuses upon the “effect” of the copying in the “market for or value of the copyrighted work.” §107(4). Here the record showed that Google’s new smartphone platform is not a market substitute for Java SE. The record also showed that Java SE’s copyright holder would benefit from the reimplementation of its interface into a different market

Mir persönlich gefällt, dass das Gericht den positiven Einfluss von Android auf das ganze Java Ökosystem hier honoriert. Schon bei den ersten Diskussionen gab es diesen Punkt, wenn es Oracle wirklich darum gegangen wäre Java zu pushen, dann hätten sie direkt mit Google zusammenarbeiten können. Und offenbar ist im Laufe der Jahre das Argument von Oracle verloren gegangen, wonach Google mit Android das ‚florierende‘ Ökosystem von Java ME Handys vernichtet habe.

Die Entwickler*innen als eigene Partei

Abgesehen von der eigentlichen Urheberrechtsfrage, die vermutlich in anderen Gerichtsverfahren – vielleicht nicht nur in den USA – entschieden wird, finde ich den Aspekt, das wir als Entwickler*innen eine wesentliche Rolle in solchen Erwägungen spielen, sehr spannend:

Wenn wir uns auf eine Sprache / API / Technologie einlassen kostet uns dies Zeit und vielleicht auch Geld und eine Technologie kann sich kaum durchsetzen ohne eine entsprechende Menge von Menschen, die sich damit gut auskennen. Und unsere Interessen sind dabei durchaus anders als die der potentiellen Urheberrechtsinhaber*innen: Für uns ist es attraktiv die Wahl zu haben, zwischen Werkzeugen und zwischen Implementierungen einer API, und jedes neue Feld, in dem wir unsere Kompetenz einsetzen können, ist zunächst einmal gut für uns und den Wert unseres Wissens.

Man wird sehen, ob dieser Aspekt auch in zukünftigen Gerichtsverfahren eine Rolle spielen wird.

Flutter: Das neue Java

Gerade wurde Flutter 2 veröffentlicht und es gibt einiges zu berichten aus der Flutter Welt. Wenn man sich die Keynote der Flutter Engage anschaut hat mich aber insbesondere der Teil, der die verschiedenen neuen Zielplattformen vorstellt, irgendwie an das Java Marketing vor mehr als 20 Jahren erinnert: 

Write once, run anywhere

So war der Slogan, den SUN 1995 prägte, um das Versprechen auszudrücken mit einem Programm viele Plattformen bedienen zu können. Was sich auf der Serverseite letztlich verwirklicht hat. Aber auf der Clientseite dann doch nicht. Zwar gibt es bis heute Java Desktop Anwendungen, aber so richtig schön und zum jeweiligen Betriebssystemumfeld passend waren die fast nie. Wenn es Android nicht gäbe und die auf Java basierenden für Android Apps, dann würde man sich heute kaum an Java als Frontend Sprache erinnern. Und an Dinge wie Applets möchte man sich auch gar nicht mehr erinnern 😬

Flutter überall 

War Flutter bisher für die Android und iOS Crossplattformentwicklung geeignet kommt nun die Webplattform aus der Beta heraus und weitere Plattformen sind auch bereits bespielbar, wenn auch noch nicht völlig stabil:

Was hier noch fehlt sind eingebettete Systeme wie das von Toyota vorgestellte Infotainmentsystem in ihren Fahrzeugen.

Ob sich Flutter hier wirklich überall durchsetzen wird? Interessant ist auf jeden Fall die Unterstützung von den Ubuntu Linux Machern von Canonical, die sich hier sicher erhoffen die ewige Lücke zu den für Windows und MacOS erhältlichen Programmen schließen zu können.

Perspektiven

Für jemanden, der bisher eher aus der Webentwicklung kommt, wirft Flutter 2 die Frage auf ob hier ein Werkzeug entsteht, mit dem man ähnlich ubiquitär nutzbare Produkte entwickeln kann, wie mit einer responsiven Webseite. 

Dazu aber noch Funktionen erhält, die sich in einer App leichter entwickeln lassen. Und mit dem man in die App Stores kommen kann. Und mit dart eine moderne Programmiersprache als Unterbau bekommt, die nun auch Dinge wie null safety verspricht.

Oder muss man befürchten, dass Google dieses Vorhaben wie so viele andere Dienste und Projekte einstampft? Da sich inzwischen auf andere Firmen – selbst Microsoft – beteiligen und Google selbst wesentliche Apps wie Google Pay damit realisiert scheint diese Gefahr im Moment gering.

Ich bin jedenfalls gespannt welches Bild sich vielleicht in 10 Jahren zeigt und ob Flutter gegenüber den Javascript-basierten Cross Plattform Lösungen die Nase vorne haben wird.

Begeisterung für die Typographie

Gibt bei man Google ‚Typographie‘ ein erhält man heute diese Definition:

  1. Kunst der Gestaltung von Druck-Erzeugnissen nach ästhetischen Gesichtspunkten; Buchdruckerkunst
  2. typografische Gestaltung (eines Druck-Erzeugnisses)

Druck-Erzeugnisse? 🔣

Dabei spielt Typographie für Webseiten und Apps eine wichtige Rolle, selbst wenn man sich für das Thema nicht ganz so begeistern kann wie Oliver Schöndorfer von Zeichenschatz in der 83. Folge des programmier.bar Podcasts.

Schriftartenbeispiele von Google Fonts

Für mich eine unbedingt hörenswerte Folge, die einem als Entwickler*in wesentliche Begriffe und Konzepte von Schriftarten beibringt und das auch noch mit einer ansteckenden Begeisterung (trotz der Wiener Mundart 😏). Und einer seiner Punkte ist für mich besonders überzeugend: In einer App oder responsive Webseite bleibt oft nur noch die Typographie um sich von anderen Angeboten abzusetzen und Wiedererkennungswerte zu schaffen.

Was man im Podcast alles lernt 🔣

  • Was sind Display text, Body text und Functional text? Und nach welchen Kriterien wählt man dafür geeignete Fonts?
  • Wann ist die Frage wie gut unterscheidbar Zeichen wie Il1, ec oder agq in einem bestimmten Font sind wichtig?
  • Warum lohnt es sich auch mal jenseits von Google Fonts nach Schriftarten suchen? Oder wenn doch Google Fonts, dann vielleicht mal die Sortierung umzudrehen und nach den weniger populären Fonts schauen?
  • Was hat es mit Zwiebelfischen und Schusterjungen auf sich?
  • Was sind variable fonts und was macht sie so cool? Diese Frage kann sich auch hier beantworten: v-fonts.com/
  • Und was hat Oliver gegen Open Sans? Und hat dazu sogar ein Video in seinem YouTube Channel (unbedingt bis zum Ende sehen)?
  • Und noch einige mehr…

Für mich war der Podcast gut investierte Zeit 🔣