IoT-Markt im Wandel: Vom Hype zur Konsolidierung

(1) Unternehmen weltweit erkennen zunehmend die Relevanz und Möglichkeiten, die IoT bietet, um effizienter zu werden, neue Geschäftsfelder zu erschließen und monetarisierbare   Services zu entwickeln. Längst haben auch Technologieunternehmen diesen Trend erkannt und eine Vielzahl an IoT-Plattformen hervorgebracht, die es Kunden ermöglichen sollen, IoT-Projekte möglichst schnell und unkompliziert durchzuführen. Die ersten IoT-Plattformen entstanden bereits Ende der 2000er Jahre. Zu den Pionieren gehörten damals Pachube im Jahr 2007 [2], PTC ThingWorx im Jahr 2009 [3] und ThingSpeak im Jahr 2010 [4]. Den Hype erlebten IoT-Plattformen zwischen 2016 und 2018 (siehe Blogpost). Seither sind auch Weltkonzerne wie beispielsweise Amazon, Microsoft, IBM, SAP oder Google in den Markt eingetreten. In den letzten Jahren hat sich jedoch ein Trend zum „Massensterben von IoT-Plattformen“ abgezeichnet. Immer wieder verkünden Technologieunternehmen, dass sie ihre Ambitionen zurückschrauben und IoT-Plattformen einstellen werden – mitunter auch einige namenhafte Beispiele wie IBM Watson IoT, Google Cloud IoT Core und SAP Internet of Things. [5]

Doch was sind die Beweggründe für die Abkehr und das Sterben der IoT-Plattformen?

Was sind IoT-Plattformen, und welchen Mehrwert bieten sie?

IoT-Plattformen sind Softwarelösungen für die Entwicklung, Bereitstellung und Verwaltung von IoT-Anwendungen. Sie bieten eine Reihe von Funktionen, die es Unternehmen und Organisationen ermöglichen, Geräte, Maschinen und Anlagen zu verbinden, Daten zu sammeln und zu analysieren. IoT-Plattformen können dabei unterschiedlich kategorisiert werden:

 

Infrastructure as a Service (IaaS)

 

IaaS-Plattformen bieten Unternehmen die Möglichkeit, die zugrundeliegende Hardware und Infrastruktur für IoT-Anwendungen zu mieten. Dazu gehören Server, Speicher, Netzwerke und Cloud Computing-Ressourcen. IaaS verleiht somit ein Grundkonstrukt, um IoT-Softwarelösungen aufzubauen. Als Nutzer und Kunde einer IaaS-Lösung ist man selbst für die Installation, Konfiguration und Wartung der IoT-Anwendungen verantwortlich. Vorgefertigte Bausteine sind nicht gegeben. [6]

Beispiele: Amazon Webservices (AWS), Microsoft Azure oder Google Cloud Plattform.

 

Platform as a Service (PaaS)

 

PaaS-Plattformen bieten Unternehmen eine Entwicklungsplattform für IoT-Anwendungen. Dazu gehören Tools und Services für die Entwicklung, Bereitstellung und Verwaltung. Der Anbieter verwaltet die Infrastruktur und die Plattform, während Sie, als Nutzer, für die Entwicklung, Bereitstellung und Wartung Ihrer Anwendungen verantwortlich sind. PaaS-Plattformen stellen erste Building-Blocks zur Erstellung von IoT-Systemen, erfordern jedoch Custom-Code, um die Bestandteile miteinander zu verknüpfen und eine lauffähige IoT-Anwendung zu schaffen. [7]

Beispiele: Microsoft Azure IoT Hub, Google Cloud IoT Core oder IBM Watson IoT Plattform.

 

Software as a Service (SaaS)

 

SaaS-Plattformen bieten Unternehmen fertige IoT-Anwendungen, die über das Internet bereitgestellt werden. Der Anbieter verwaltet die Infrastruktur, die Plattform und die Anwendung. Als Kunde einer solchen SaaS-Lösung müssen Sie sich nur um die Konfiguration und Nutzung der Anwendung kümmern, sind jedoch auf die angebotenen Features limitiert. Jegliche Erweiterungen erfordern wie schon im PaaS-Szenario zusätzlichen Custom-Code. [7]

Beispiele: PTC ThingWorx, Software AG Cumulocity, Bosch IoT Suite oder Siemens Insight.

 

Der Großteil, der am Markt befindlichen IoT-Plattformanbieter, bieten Plattform as a Service (PaaS) in Kombination mit spezialisierten Applikationen als Software as a Service (SaaS) an. [8]

 

Was sind die Gründe für das IoT-Plattform sterben?

Beschäftigt man sich mit IoT-Plattformen, stellt man schnell fest, dass es einen bunten Strauß an unterschiedlichen IoT-Plattformlösungen und -anbieter gibt – mittlerweile über 500 [10]. In einem derart umkämpften Markt bringt es die Marktentwicklung mit sich, dass sich die Anbieter und der Markt konsolidieren. [9] IoT-Plattformanbieter müssen sich zunehmend auch dem Trend zu Cloud-basierten Anwendung widmen, um flexibel und skalierbar aufgestellt zu sein. On-top müssen Anbieter den hohen Sicherheits- und Datenschutzaspekten gerecht werden und robuste Sicherheitslösungen integrieren, um wettbewerbsfähig zu bleiben. [11] Darüber hinaus ist der IoT Markt sehr komplex und schwer standardisierbar. Jeder Kunde hat andere Anforderungen und Bedürfnisse an sein IoT-Projekt. Um erfolgreich zu sein, müssen Plattform-Anbieter sowohl technologisch breit aufgestellt sein, um viele verschiedene Anwendungen und Daten sinnvoll integrieren zu können als auch individuelle Beratung anbieten, um den Kunden bei der Auswahl und Implementierung der richtigen Lösungen zu unterstützen. Gerader dieser sehr individuellen Komponente kommen einige Anbieter nicht nach, da dies überaus kostspielig und wenig skalierbar ist. [12] Neben den Herausforderungen auf Seiten der IoT-Plattformanbieter, gibt es häufig Herausforderung bei der Durchführung.

 

Einer der Hauptgründe liegt hier bereits in der frühen Implementierungsphase. Proof of Concept IoT-Projekte werden häufig gestartet, um die Machbarkeit einer Idee zu testen. Viele dieser Projekte erreichen jedoch nicht die gewünschten Ergebnisse und scheitern. Häufig liegt das an technischen Herausforderungen, wie die Komplexität in der Konnektivität, fehlenden technischen Ressourcen oder unzureichenden Finanzierungen. Damit einher geht das Fehlen einer klaren Strategie und eines Verständnisses für den angestrebten Business Case. Viele Unternehmen starten IoT-Projekte, ohne eine klare Vorstellung davon zu haben, was sie erreichen wollen. Dies führt dazu, dass die Projekte ihre Geschäftsziele nicht erreichen und daher nur begrenzt erfolgreich sind.

 

Wie entwickelt sich die Zukunft?

Trotz dieser Herausforderungen ist das Internet der Dinge nicht rückläufig – im Gegenteil, der Markt wächst weiterhin stark und wird insbesondere durch KI, 5G oder Edge-Computing neu befeuert (siehe Blogpost).

Der Trend zur Konsolidierung im IoT-Plattformanbieter Markt wird sich aller Voraussicht nach fortsetzen und sich zunehmend zu einem Markt mit großen etablierten IoT-Plattformanbieter entwickeln. Aus Sicht von IoT Analytics, kann der Markt für „generische IoT-Plattformen“ gar allein durch Microsoft Azure und Amazon Webservices mit deren großen Anzahl an Add-Ons und Services abgedeckt werden. Zusätzlich, so IoT Analytics, bestehen weiterhin Chancen für Nischenanbieter, die spezifische und leichtgewichtige Lösungen bereitstellen. [11] Auf der anderen Seite müssen sich Unternehmen, die sich dem digitalen Wandeln stellen und IoT-getriebene Geschäftsmodelle entwickeln wollen, klar werden, dass Ihre Geschäftsidee nicht einfach so durch eine IoT Plattform umgesetzt werden kann. Vielmehr gilt es, den Ansatz zu überdenken und sich auf eine klare Strategie und den Mehrwert ihrer Kunden zu konzentrieren. [9]

 

Unsere Einschätzung: Was braucht eine zukunftsfähige IoT-Lösung?

Durch unsere jahrzehntelange Erfahrung im Bereich IoT kennen wir die Komplexitäten und die Herausforderungen von IoT-Projekten. Das Verwenden von IoT-Plattformen ist überaus wichtig und beschleunigt die Entwicklung von IoT-Projekten ungemein. Nichtsdestotrotz stellen die Plattformen lediglich einen Rahmen dar. Ohne eine gezielte Vision, Strategie und v.a. technischem Know-How in Unternehmen, werden IoT-Projekte scheitern.

Eine Darstellung, die aufzeigt, wie IoT Plattform Lösungen von doubleSlash mit den Devices kommunizieren
siehe https://www.doubleslash.de/leistungen/iot-partner/

Wir bei doubleSlash denken IoT-Lösungen stets ganzheitlich (vom Kundengerät bis hin zur IoT-Lösung) und setzen dabei auf am Markt etablierte Technologieführer wie z.B. Microsoft Azure, PTC ThingWorx und Amazon Webservices, sind aber auch offen für Nischenanbieter mit klaren USPs. In einer komplexen Welt, in der Zeit und Effizienz alles bedeuten, sind on-top schnelle und einfache Lösungen gefragt – hier setzt unsere doubleSlash IoT Solution an. Diese besteht aus verschiedenen Produktkomponenten, welche Plattform-agnostisch integriert und erweitert werden können. Gepaart mit der Nutzung etablierter IoT-Plattformen, können ideale Synergien geschaffen werden. Unsere doubleSlash IoT Solution bringt somit die Flexibilität, Sicherheit und Skalierbarkeit von IoT-Plattformen mit und ist zugleich unkompliziert bei Kunden integrierbar, wodurch schnell vorzeigbare Lösungen etabliert werden können – egal ob in der Cloud oder On-Premise. Darüber hinaus legen wir großen Wert auf Individualität, denn wir arbeiten stets Hand in Hand mit unseren Kunden, um unsere Produktkomponenten optimal zu erweitern und an die spezifischen Anforderungen anzupassen.

 

Co-Autor: Nico Kirtzos

 

Quellen:

  1. https://www.statista.com/outlook/tmo/internet-of-things/worldwide
  2. https://haque.co.uk/work/pachube/
  3. https://www.zippia.com/xively-careers-2110420/history/
  4. https://www.engineeringspot.de/2014/01/kaufrausch-siemens-autodesk-und-ptc-verstaerken-sich/
  5. https://brandfetch.com/thingspeak.com
  6. https://www.planetanalog.com/thingspeak-open-source-platform-for-connected-products-and-services/
  7. https://bytebeam.io/blog/what-to-expect-of-iot-in-2023-after-the-death-of-ibm-google-and-sap-iot-platforms/
  8. https://aws.amazon.com/de/types-of-cloud-computing/
  9. https://www.iotforall.com/saas-or-paas-selecting-an-iot-platform
  10. https://www.sic-software.com/iot-plattform-auswaehlen/
  11. https://www.iot-now.com/2022/08/05/122841-why-iot-projects-fail/
  12. https://www.bechtle.com/it-loesungen/iot-loesungen/iot-plattformen#:~:text=Mittlerweile%20gibt%20es%20mehr%20als,und%20Programmieren%20entfallen%20dabei%20komplett
  13. https://www.computerwoche.de/a/ist-der-internet-of-things-hype-schon-vorbei,3613359

It’s #FrontendFriday – Build Skripte ausführen in Flutter™️

Build-, Validierungs- und andere Custom-Skripte befinden sich meist in einer zentralen Konfigurationsdatei. Im Fall von Flutter ist das die Datei pubspec.yaml. Das Problem hierbei ist, dass das Framework von Haus aus keine Möglichkeit bietet eigene Skripte auszuführen. Glücklicherweise stellt die Flutter Community gleich mehrere Packages zur Lösung bereit. Eines dieser Packages ist derry.

Installation

Voraussetzung für die Installation von derry ist eine eingerichtete und funktionsfähige Flutter SDK. Anschließend lässt sich das Package (siehe pub.dev) über folgenden Befehl installieren:

dart pub global activate derry

Setup & Nutzung

Nach der Installation von derry gibt es 2 Möglichkeiten Skripte für Flutter zu schreiben.

  • direkt in der pubspec.yaml Datei
  • ausgelagert in eine separate Datei

Gerade bei einem Projekt mit mehreren Skripten, bietet es sich an, diese in eine eigene Datei auszulagern. Dadurch bleibt der Umfang der Konfigurationsdatei geringer und die Skripte sind schneller zu finden.

Der folgende Screenshot zeigt beispielhaft die Verzeichnisstruktur eines Flutter-Projekts. In Rot markiert sind einerseits die Konfigurationsdatei pubspec.yaml und eine zweite Yaml-Datei für Skripte – in diesem Fall derry.yaml genannt.

Das Bild zeigt einen Screenshot einer Projektstruktur von Flutter. Markiert sind zwei Dateien: derry.yaml und pubspec.yaml. Die Dateien befinden sich auf der obersten Ebene des Projektverzeichnisses.
eigene Darstellung

Der folgende Codeausschnitt ist ein Beispiel, wie Flutter Skripte aussehen können und zeigt den Inhalt der Datei derry.yaml:

localization:
 - dart run easy_localization:generate -S assets/i18n -O lib/common/localization -o locale_keys.g.dart -f json -u true
clean_install:
 - flutter clean
 - flutter pub get
 - flutter upgrade -f
build_android:
 - derry clean_install
 - flutter build apk -t lib/main.dart
build_ios:
 - derry clean_install
 - flutter build ios
build_release:
 - derry build_android
 - derry build_ios

Nicht eingerückte Begriffe repräsentieren die Skriptnamen. Die Stichpunkte darunter sind die einzelnen Befehle, die derry nacheinander für den jeweiligen Namen ausführt.

Damit derry die definierten Skripte nutzen kann, muss die Datei in pubspec.yaml referenziert werden:

# ... content of pubspec.yaml 

scripts: derry.yaml

Anstelle des Dateinamens (hier derry.yaml) könnte man, alternativ zur separaten Datei, die einzelnen Skripte direkt einfügen:

# ... content of pubspec.yaml

scripts:
  clean_install:
    - flutter clean
    - flutter pub get
    - flutter upgrade -f

Mit diesem Setup kann man die Skripte nach der Syntax derry <script_name> ausführen.
Beispiele:

dart localization
dart build_android
dart clean_install

 

Subscription-Modelle in der Industrie: Strategien für den Unternehmenserfolg

Mittlerweile tendiert der Markt jedoch immer mehr zu individualisierten Produkten und Dienstleistungen, die speziell auf die Bedürfnisse der Kunden zugeschnitten sind. Neben der Individualisierung ist auch der Aufbau von langfristigen Kundenbeziehungen und die Maximierung des Customer Lifetime Values von besonderem Interesse. Der Verkauf von Produkten und Dienstleistungen im Subscription-Modell stellt eine geeignete Möglichkeit dar, den Customer Lifetime Value zu maximieren. Durch die zunehmende Individualisierung von Angeboten in der Industrie wird jedoch das effektive Management von verschiedenen Subscriptions immer wichtiger. Bestehende Systeme stoßen hierbei an ihre Grenzen, weshalb spezialisierte Subscription-Management-Systeme zum Einsatz kommen. Diese Systeme sind entweder direkt einsatzbereit oder lassen sich individuell auf die Anforderungen und Bedürfnisse der jeweiligen Unternehmen zuschneiden. Im Folgenden erläutern wir, was dies konkret bedeutet.

 

 

Subscription Modelle – nicht immer so einfach wie bei Netflix

Zunächst wollen wir uns ein einfaches Subscription-Modell anschauen. Eines der bekanntesten Subscription Angebote ist der Streaming-Service von Netflix. Hier werden ausschließlich die Dimensionen Kunde und Service betrachtet. Die Kunden haben bei Netflix lediglich die Wahl zwischen vier verschiedenen Tarifen, die sich hinsichtlich der Videoqualität, der Anzahl der Abspielgeräte und angezeigter Werbung unterscheiden. Der Service, das Streamen von Filmen und Serien, bleibt bei allen vier Tarifen immer der gleiche. Beim Preismodell von Netflix handelt es sich um ein einfaches „Tiered-Pricing“-Modell. Das bedeutet, dass es ein gestaffeltes Pricing gibt, welches für alle Kunden gleich ist. Wer mehr bezahlt, erhält beispielsweise mehr Accounts oder eine höhere Qualität.

 

Die dritte Dimension: Subscription-Modelle in der Industrie

Wenn wir nun Subscriptions in der Industrie betrachten, fällt schnell auf, dass diese wesentlich komplexer sind als das Netflix-Modell. Zu den Dimensionen Kunde und Service kommt eine dritte Dimension hinzu: eine komplexe und vernetzte Maschine. Die Erweiterung des einfachen Netflix-Modells um eine vernetzte Maschine bietet auf der einen Seite viele Möglichkeiten Subscriptions individuell auf den Kunden zuzuschneiden, bedeutet jedoch auch, viel Komplexität beim Bereitstellen und Management der Subscription. Die Herausforderungen wollen wir anhand des Beispiels einer Verpackungsmaschine erläutern.

 

Subscriptions im Anlagen- und Maschinenbau: Für die maximale Kundenzufriedenheit und Akzeptanz sind differenzierte Angebote entscheidend.

In unserem Beispiel gibt es zwei verschiedene Service-Angebote für Maschinen, die in der Medizinbranche für Verpackungen verwendet werden. Diese Angebote basieren auf der individuellen Nutzung der Maschine durch den Kunden.

Beispiel 1: Die Maschine wird bei Kunde 1 zur Verpackung von hochpreisigen Medikamenten eingesetzt. Das heißt, für Kunde 1 ist eine hohe Qualität der Endprodukte sowie wenig Stillstand der Maschine besonders wichtig.

Beispiel 2: Kunde 2 setzt die gleiche Maschine für die Verpackung von sehr niedrigpreisigen Medikamenten ein. Für Kunde 2 ist es wichtiger, hohe Durchsatzzahlen zu haben. Aufgrund des geringeren Produktpreises wäre ein Stillstand oder ein produzierter Produktausschuss nicht so gravierend wie bei Kunde 1.

Durch die unterschiedlichen Prioritäten der jeweiligen Kunden und die damit verbundene unterschiedliche Nutzung der Maschine, ergibt sich die Möglichkeit   individuelle Preismodelle anzubieten. Für Kunde 1 wäre beispielsweise ein Preismodell mit höheren Stückkosten, inkl. hoher Qualitätsprüfung der verpackten Produkte sowie ein 24/7 Support denkbar. Kunde 2 hingegen benötigt weder eine strenge Qualitätskontrolle noch einen 24/7 Support. Für ihn wäre es deswegen sinnvoller, ein Preismodell mit niedrigerer Stückkostenanzahl anzubieten und ohne inkludierte Sonderleistungen wie eine Qualitätsprüfung oder ein 24/7 Support.

An diesem Beispiel wird deutlich, dass es in der Industrie deutlich mehr Komplexitäten bei der Einführung von Subscriptions gibt, als bei Netflix. In beiden betrachteten Möglichkeiten der Monetarisierung der Verpackungsmaschine findet ein Value-based pricing statt, welches dazu beiträgt, dass eine langfristige Kundenbindung aufgebaut werden kann. Der Mehrwert, den Unternehmen für sich bemessen, ist entscheidend für maßgeschneiderte Subscriptions. Besonders bei komplexen Maschinen, die stark an die Bedürfnisse der Kunden konfigurierbar sind, kann dieser Wert sehr unterschiedlich sein.

 

Strategien bei der Auswahl eines Subscription-Management-Systems

Um solche individuellen Subscriptions und Pricing Strategien IT seitig umsetzen zu können, sind fortschrittliche Monetarisierungslösungen erforderlich. Diese müssen in der Lage sein, die Komplexität vernetzter Services zu handhaben und gleichzeitig die Flexibilität und Anpassungsfähigkeit gewährleisten, um auf individuelle Kundenbedürfnisse und Marktveränderungen reagieren zu können.  Der „Best-of-Suite“-Ansatz strebt danach, eine umfassende Lösung anzubieten, die eine Vielfalt an Funktionen in sich vereint und unterschiedliche Prozesse auf einer einzigen Plattform zusammenbringt. Obwohl diese integrierten Systeme viele der allgemeinen Anforderungen direkt erfüllen können, stoßen sie doch an ihre Grenzen. In der Praxis führt das oft dazu, dass Nutzer solcher Systeme Kompromisse akzeptieren müssen, da häufig nicht alle ihrer speziellen Bedürfnisse abgedeckt werden. Die Vorstellung nach einer idealen Lösung, die sämtliche Anforderungen lückenlos bedient, erweist sich daher meist als Wunschdenken und ist in der Realität kaum umsetzbar.

 

Best-of-Suite vs. Best-of-Breed

Im Gegensatz zum „Best-of-Suite“-Ansatz setzt der „Best-of-Breed“-Ansatz darauf, für jede spezifische Anforderung und jeden individuellen Anwendungsfall die optimal passende Softwarelösung von unterschiedlichen Anbietern zusammenzustellen. Dieser Ansatz ist besonders im industriellen Sektor bei Subscription-Modellen sinnvoll, da, wie im obigen Beispiel dargestellt, häufig komplexe Maschinen in den Order-to-Cash-Prozess eingebunden sind. Das Ergebnis ist ein Monetarisierungs-Ökosystem, das dem Composable-Commerce-Ansatz ähnelt und sowohl spezifische Vorteile als auch Herausforderungen mit sich bringt.

 

Welcher der beiden Ansätze der richtige ist, muss für jedes Unternehmen individuell betrachtet werden. In der folgenden Gegenüberstellung werden die wesentlichen Vor- und Nachteile des jeweiligen Ansatzes zusammengefasst.

 

Best of Suite Best of Breed
+ Einfache Integration und Verwaltung + Flexibilität in der Systemauswahl und -integration

 

+ einfaches Lizenzmanagement + hoher Funktionsumfang und hohe Abdeckung der Kunden und Businessspezifischen Anforderungen
+ einfachere Wartung und Betrieb + Hohe Effektivität und Effizienz

 

– Systeminterne Prozesse nicht transparent (Blackbox) – Hoher Aufwand an Integration- und Schnittstellenmanagement
– Hohe Abhängigkeiten zum Produktanbieter – Risiko, dass Inkonsistenzen und Inkompatibilitäten auftreten

 

 

Unsere Einschätzung

In einem dynamischen Markt, der von zunehmendem Wettbewerb geprägt ist, können sich Unternehmen keine Kompromisse leisten. Der „Best-of-Breed“-Ansatz, bei dem spezialisierte Lösungen gezielt kombiniert werden, schafft ein flexibles und agiles Monetarisierungs-Ökosystem, das entscheidend für die Wettbewerbsfähigkeit ist.

Eine solche Flexibilität und Kundenfokussierung ist entscheidend, um sich von der Konkurrenz abzuheben und nachhaltigen Erfolg zu sichern. Der „Best-of-Breed“-Ansatz ermöglicht Unternehmen, schnell auf Veränderungen zu reagieren und ihre Services kontinuierlich zu optimieren. Somit ist diese Strategie nicht nur eine Option, sondern eine Notwendigkeit für Unternehmen, die in der dynamischen Geschäftswelt von heute bestehen wollen.

Interessieren Sie sich für weiterführende Informationen zum Monetarisierungs-Ökosystem und möchten Sie Best Practices kennenlernen? Abonnieren Sie unseren Newsletter und erhalten Sie wertvolle Tipps und Einblicke direkt in Ihr E-Mail-Postfach.

 

Weiterführende Links & Artikel:

Die Preview-Features von Java 22

JEP-461: Stream Gatherers (Preview)

Die Menge der in der Stream-API vorhandenen Zwischenoperationen (wie z.B. filter, map, sorted, …) ist derzeit fix und nicht erweiterbar.

Seit der Einführung von Streams in Java 8, was nunmehr ganze 10 Jahre her ist, wurden viele Vorschläge für weitere Zwischenoperationen gemacht, die jede für sich zwar sinnvoll wäre, aber alle zusammen genommen die ohnehin schon große API zu unübersichtlich machen würden.

Stattdessen wird die Stream-API mittels eines Extension Points namens „Stream Gatherers“ erweiterbar gemacht. Zu diesem Zweck erhält die API die neue Zwischenoperation „gather“, der man eigene, oder von der Java-API bereitgestellte, Implementierungen des „Gatherer“-Interface mitgeben kann.

Der folgende Code zeigt die Factory-Methode für einen einfachen Gatherer, der jedes Element im Stream vervielfacht:

Die Verwendung im Stream sieht wie folgt aus:

Das Ergebnis ist eine Liste, die jedes Element aus dem ursprünglichen Stream dreimal enthält (a, a, a, b, b, b, c, c, c).

Eine Reihe von Gatherer-Implementierungen, wie beispielsweise windowFixed, windowSliding oder fold, sind über die Klasse Gatherers erhältlich.

Die Anwendung von windowSliding sieht etwa wie folgt aus:

Die Ausgabe dazu:

JEP-447: Statements before super(…) (Preview)

Bisher müssen Aufrufe von super(…) bzw. this(…) in Konstruktoren immer an erster Stelle stehen. Mit diesem JEP wird es möglich, bestimmte Statements diesen Aufrufen voranzustellen. Für solche Statements gibt es allerdings Einschränkungen, sie dürfen etwa keine Referenzen auf die zu erstellende Instanz beinhalten. Aufrufe statischer Methoden sind demnach u.a. erlaubt.

Vor dem super(…)-Aufruf ist es nun möglich, wie in der oben gezeigten Klasse eine Validierung durchzuführen. Bisher hätte man die Validierung entweder erst nach dem super-Aufruf gemacht und im Fehlerfall ggf. unnötige Arbeit ausgeführt; die Alternative wäre, val im super-Aufruf in eine Validierungsmethode zu wrappen. Demgegenüber ist der oben gezeigte Code sowohl effizient als auch leicht nachvollziehbar.

Für this(…)-Aufrufe gilt dasselbe, wie das nachfolgende Beispiel zeigt:

JEP-457: Class-File API (Preview)

Im Java-Ökosystem ist das Parsen, Generieren und Transformieren von Klassendateien gang und gäbe, z.B. in Tools oder Frameworks, die dynamisch Bytecode analysieren, modifizieren oder generieren. Dafür nutzen sie Klassendateibibliotheken wie ASM, BCEL oder Javassist. Auch das JDK selbst hat eine eigene auf ASM basierende Klassendateibibliothek.

Neue Java-Sprachfunktionen und JVM-Eigenschaften führen zu Veränderungen im Klassendateiformat. Aufgrund des halbährlichen Releasezyklus von Java ändert sich allerdings auch das Klassenformat häufig, so dass die Klassendateibibliotheken sowie darauf aufbauende Frameworks es schwer haben, mit den Änderungen Schritt zu halten.

Mit diesem JEP soll die Java-Plattform eine Standard-API für Klassendateien definieren und implementieren, die sich zusammen mit dem Format der Klassendateien weiterentwickelt. Frameworks und Tools die diese API nutzen können so schneller die jeweils neueste JDK-Version unterstützen. Ein weiteres Ziel ist es, die Abhängigkeit des JDK zu ASM loszuwerden.

Da sich dieser Blogbeitrag vor allem an Anwendungsentwickler richtet, die entsprechende Frameworks nutzen, aber nicht selbst entwickeln, verzichte ich hier auf Codebeispiele und verweise auf die Beschreibung und Beispiele im JEP-457.

JEP-463: Implicitly Declared Classes and Instance Main Methods (Second Preview)

Um Einsteigern das Lernen von Java so einfach wie möglich zu machen, sieht das einfachste Java-Programm mit diesem Preview-Feature wie folgt aus:

So kommt das erste Erfolgserlebnis schnell und unkompliziert, ohne dass man sich mit Konzepten wie Klassen, statischen Methoden oder Methodensichtbarkeit auseinandersetzen muss.

Bei der Auswahl der auszuführenden Methode geht die JVM wie folgt vor: Gibt es eine main-Methode mit Parameter String[] args, wird diese ausgeführt. Existiert eine solche Methode nicht, wird die Methode main() ohne Parameter ausgeführt, sofern vorhanden. Ob statisch oder nicht, spielt dabei keine Rolle.

JEP-464: Scoped Values (Second Preview)

Scoped Values sollen ein leichtgewichtiger Ersatz für ThreadLocal werden. ThreadLocals werden beispielsweise von Webframeworks verwendet, um Informationen einer Benutzersession bei der Abarbeitung von Serveranfragen im Rahmen eines Threads zu speichern. Insbesondere bei Virtual Threads, von denen es sehr viele geben kann im Gegensatz zu den herkömmlichen Threads, kann dieser Ansatz problematisch werden. Hätte bei einer Anzahl von Millionen Virtual Threads jeder eine eigene Kopie, würde dies einen signifikanten Speicherbedarf bedeuten.

Mit Scoped Values wird es möglich, dass mehrere Threads sich Daten wie z.B. die Benutzerinformationen teilen.

Zuerst wird im WebFramework eine ScopedValue-Instanz vom Typ UserSession instanziert (Zeile 3). Die Referenz ist statisch, so dass auch aus anderen Codeteilen darauf zugegriffen werden kann.

In der doRequest(…)-Methode wird die userSession aus dem Store geholt (Zeile 14). Dann wird sie an die where(…)-methode von ScopedValue übergeben (Zeile 16), und im Anschluss direkt run(…) aufgerufen (Zeile 17), wo die Bearbeitung an die service-Instanz weiter delegiert wird.

In der handle(…)-Methode der Klasse Service kann nun die Benutzersession via get() aus der ScopedValue-Instanz ausgelesen und genutzt werden.

Die in where(…) gesetzte User-Session(Z. 17) ist nur innerhalb des Scopes der run(…)-Methode gültig. Würde man in Zeile 18 versuchen, via USER_SESSION.get() auf die zuvor gesetzte userSession zuzugreifen, wäre das Ergebnis eine NoSuchElementException.

Zudem kann der gesetzte Wert innerhalb des Scopes nicht neu gesetzt werden, da ScopedValue keine set(…)-Methode hat. Dies vereinfacht die nebenläufige Programmierung, und trägt auch zu einer besseren Performance bei.

JEP-459: String Templates (Second Preview)

Bis auf eine technische Änderungin den Typen der Template-Expressions hat sich in der 2. Preview gegenüber er ersten nichts geändert.

Ausdrücke werden mit \{ eingeleitet und mit } geschlossen. Bei STR handelt es sich um einen StringTemplate-Processor, der die Ausdrücke auswertet und das Ergebnis an die jeweilige Stelle im String-Template einfügt.

Auch Textblöcke werden unterstützt, um beispielsweise JSON oder andere mehrzeilige Strings zu erzeugen:

Sehr praktisch ist, dass doppelte Anführungszeichen in String Templates nicht escaped werden müssen. Das Ergebnis sieht wie folgt aus:

Neben STR gibt es auch FMT, einen FormatProcessor, der das Formatieren anhand der Formatter-Spezifikation erlaubt:

Doch lediglich Werte in Strings zu parsen, ging den Designern des Features nicht weit genug. Bei Erzeugung von SQL-Statements besteht beispielsweise die Gefahr der SQL-Injection:

Mit dem Wert „Smith‘ OR p.last_name <> ‚Smith“ ließe sich ein Statement erzeugen, das alle Einträge von Person zurückliefert. Daher soll der TemplateProcessor-Mechanismus in Java es ermöglichen, verschiedene Prozessoren für unterschiedliche Einsatzgebiete bereitzustellen. Deswegen ist es möglich, eigene Prozessoren zu schreiben, die valide bzw. sichere Ergebnisse produzieren. Im obigen Fall könnte z.B. ein SQL-Prozessor die Anführungszeichen in den Ausdruckswerten escapen.

Das Ergebnis muss nicht unbedingt vom Typ String sein; somit wäre auch ein Prozessor denkbar, der als Ergebnis ein SQL-Query- oder JSON-Objekt hat.

Hier ein Beispiel für einen selbstgeschriebenen Template-Prozessor, der alle Werte spiegelt:

JEP-462: Structured Concurrency (Second Preview)

Structured Concurrency leitet sich aus dem einfachen folgenden Prinzip ab:

„Wenn eine Aufgabe in nebenläufige Subtasks aufgeteilt wird, kehren alle wieder zu demselben Ort zurück, nämlich dem Codeblock des Tasks.“

Dies ist bei der bisherigen z.B. mittels ExecutorService implementierten Nebenläufigkeit nicht gegeben.

Dieser JEP soll einen Ansatz für die nebenläufige Programmierung schaffen, bei dem die natürliche Beziehung zwischen Aufgaben und Teilaufgaben erhalten bleibt, was zu besser lesbarem, wartbarem und zuverlässigem nebenläufigem Code führt. In der Structured Concurrency werden Subtasks im Rahmen eines Tasks abgearbeitet. Der übergeordnete Task wartet auf die Ergebnisse und überwacht Fehlerfälle in den einzelnen Subtasks.

Die beiden Subtasks findUser() und fetchOrder() werden hier innerhalb eines gemeinsamen Scopes abgearbeitet. Mit der join()-Anweisung in Zeile 6 wird auf die Beendung aller Subtasks gewartet und im Anschluss die Ergebnisse zusammengeführt und zurückgegeben.

Die Shutdown-Policy „ShutdownOnFailure“ (Zeile 2) bewirkt beim ersten Auftreten einer Exception in einem der Subtasks, dass die anderen noch laufenden Subtasks abgebrochen und die Exception weiter propagiert wird. Diese Policy ist relevant, wenn die Ergebnisse aller Subtasks benötigt werden.

Daneben existiert auch noch die Shutdown-Policy „ShutdownOnSuccess“. Diese bewirkt, dass das Ergebnis des ersten erfolgreichen Subtasks übernommen wird und alle anderen noch laufenden Subtasks abgebrochen werden. Diese Policy verwendet man, wenn nur das Ergebnis von irgendeinem der Subtasks benötigt wird:

In Java 22 ist die Structured Concurrency zum zweiten Mal als Preview-Feature vorhanden, ohne Änderungen gegenüber der ersten Preview, um weiteres Feedback aus der Community einzusammeln.

JEP-460: Vector-API (Seventh Incubator)

Mit der Vector API führt Java die plattformübergreifende Unterstützung zur Entwicklung datenparalleler Algorithmen ein. Anhand eines „Single Instruction Multiple Data“ (SIMD) Modells sollen die Vector-Instruktionen unterschiedlicher CPU-Architekturen unterstützt werden. Rechenoperationen (instructions) werden dabei statt auf nur einen Wert auf mehrere Werte gleichzeitig in nur einem CPU-Zyklus ausgeführt. Anwendungsfälle hierfür sind etwa die Bild- und Videoverarbeitung.

Codebeispiel:

Die Vector-API ist numehr in der siebten Incubator-Version enthalten, mit Performanceverbesserungen und Bugfixes gegenüber der Vorversion, sowie der Erweiterung, dass MemorySegments nun Arrays aller nativen Datentypen unterstützt statt nur Arrays vom Typ byte.

Java 22 – die neuen Features kurz vorgestellt

JEP-423: Region Pinning for G1

Javas Standard-Garbage-Collector G1 kann im Zusammenhang mit JNI (Java Native Interface) zu Problemen führen, wie etwas minutenlanges Blockieren einer Anwendung, Verursachung unnötiger Out-of-Memoriy-Zustände, oder vorzeitiges Beenden der JVM. Mit diesem JEP sollen diese Probleme behoben werden. Wer sich für die Hintergründe und technischen Details interessiert, kann sich das entsprechende JDK Enhancement Proposal Nr. 423 durchlesen.

JEP-454: Foreign Function & Memory API

Durch diese neue API soll JNI abgelöst werden. Sie dient dazu, von Java-Programmen aus mit Code und Speicherbereichen außerhalb der Java-Laufzeitumgebung zu interagieren. Durch den effizienten Aufruf fremder Funktionen (also Code außerhalb der JVM) sowie den sicheren Zugriff auf externen Speicher, der nicht von der JVM verwaltet wird, ermöglicht die API Java-Programmen den Aufruf nativer Bibliotheken und die Verarbeitung nativer Daten ohne die Fragilität und die Gefährlichkeit von JNI (Java Native Interface).

Bereits seit Java 17 ist diese API als Incubator- bzw. Preview-Feature vorhanden. Mit Java 22 wird nun die endgültige, finalisierte Version der API geliefert.

Codebeispiel 1 – Allokieren eines fremden Speicherbereichs:

Arena steuert den Lebenszyklus externer Speichersegmente und ermöglicht sowohl eine flexible Allokation als auch eine zeitnahe Freigabe.

MemorySegment ermöglicht den Zugriff auf einen zusammenhängenden Bereich des Speichers.

Der oben gezeigte Code allokiert einen Off-Heap-Speicherbereich, der groß genug ist um 10 Werte des primitiven Typs int zu speichern, und füllt ihn mit Werten von 0 bis 9. Anschließend wird der Wert am Index 3 ausgelesen und ausgegeben.

Codebeispiel 2 – Aufruf der externen C-Funktion „strlen“ zur Ermittlung der Länge eines Strings:

Über die Linker-Klasse erhält man Zugriff auf fremde Funktionen vom Java-Code aus, sowie Zugriff auf den Java-Code von den externen Funktionen aus.

MethodHandles gibt es bereits seit Java 7; sie wurde als performantere Option zu Reflection eingeführt. Nun können sie nicht mehr nur auf Java-Methoden, sondern auch auf fremde Funktionen verweisen.

Im obigen Codebeispiel wird ein Speichersegment allokiert, welches das Wort „Hello“ als C-String beinhaltet.

Über den MethodHandle „strlen“ wird via „invokeExact“ der native Funktionsaufruf getätigt.

Die Codebeispiele stammen aus dem Javadoc des Packages „java.lang.foreign“ , das eine ausführliche Beschreibung der neuen API enthält.

JEP-456: Unnamed Variables & Patterns

In Java 21 als Preview-Feature eingeführt, ist dieses Feature nun unverändert und finalisiert in Java 22 enthalten.

Nicht genutzte Komponenten in Record Patterns oder ungenutze Variablen müssen nun nicht mehr benannt werden. Stattdessen können sie den Unterstrich „_“ als Bezeichner erhalten. Dies macht den Code besser verständlich, da der Entwickler so explizit ausdrücken kann, dass ein bestimmtes Konstrukt, das im Code angegeben werden muss, nicht benötigt wird.

Möchte man in einem Record Pattern für Point nur die x-Koordinate verwenden, nicht aber die y-Koordinate, kann man dies wie folgt schreiben:

Es ist auch möglich, den Datentyp wegzulassen:

Zudem können außerhalb von Patterns auch ungenutzte Variablen entsprechend benannt werden:

Auch für Exceptions in catch-Anweisungen kann _ verwendet werden:

Dasselbe gilt für ungenutzte Parameter in Lambdas. In Zeile 6 wird beispielsweise ein CommandLineRunner definiert, der die Kommandozeilenparameter nicht benötigt:

JEP-458: Launch Multi-File Source-Code Programs

Seit JEP-330 in Java 11 ist es möglich, *.java-Dateien direkt auszuführen, sofern das komplette Programm in der Datei enthalten ist. Ein expliziter Aufruf des Compilers javac ist nicht nötig.

Ab Java 22 ist es nun möglich, *.java-Dateien auch dann auszuführen, wenn das beinhaltete Programm aus mehreren Quelldateien besteht.

Gegeben sei ein Programm, das aus den folgenden beiden Klassen besteht:

Das Programm kann nun gestartet werden mit dem Kommando

Es ist auch möglich, vorkompilierte *.class-Files sowie *.jar-Dateien mit einzubinden.

Die folgende Variante der Greeter-Klasse verwendet z.B. die StringUtils-Klasse der commons-lang3-Bibliothek:

Legt man nun die commons-lang3.jar in einem Unterverzeichnis namens „libs“ relativ zu MultiFileProgram.java ab, kann das Programm wie folgt gestartet werden:

Diese Erweiterung ist dafür gedacht, Neueinsteigern den Start mit Java zu erleichtern, bzw. den Initialaufwand für das Projektsetup so gering wie möglich zu halten. Bei einfachen Multi-Source-Programmen besteht so nicht die Notwendigkeit, sich auch noch mit der Komplexität eines Build-Tools auseinandersetzen zu müssen.

Und die Preview-Features?

Natürlich sind in Java 22 auch wieder eine ganze Reihe spannende Preview-Features enthalten. Diese behandle ich in Kürze in einem separaten Blogbeitrag.