Spring Framework 6.0 freigegeben

Jürgen Höller kündigt die neue Version Spring Framework 6 an:

Liebe Spring-Gemeinde,

ich freue mich, Ihnen mitteilen zu können, dass Spring Framework 6.0.0 ab sofort allgemein über Maven Central verfügbar ist! Dies ist der Beginn einer neuen Framework-Generation für das Jahr 2023 und darüber hinaus, die aktuelle und kommende Innovationen in OpenJDK und dem Java-Ökosystem einbezieht. Gleichzeitig haben wir es sorgfältig als unkompliziertes Upgrade von Spring Framework 5.3.x für moderne Laufzeitumgebungen konzipiert.

Als große Überarbeitung des Kern-Frameworks verfügt Spring Framework 6.0 über eine Java 17+-Baseline und einen Wechsel zu Jakarta EE 9+ (im jakarta-Namensraum), wobei der Schwerpunkt auf den kürzlich veröffentlichten Jakarta EE 10-APIs wie Servlet 6.0 und JPA 3.1 liegt. Dies ermöglicht den Zugriff auf die neuesten Webcontainer wie Tomcat 10.1 und die neuesten Persistenzanbieter wie Hibernate ORM 6.1. Bleiben Sie nicht bei Java EE 8 hängen, sondern machen Sie den Sprung zum jakarta-Namensraum, idealerweise direkt auf die Ebene von Jakarta EE 10! Das kommende Spring Boot 3.0.0 Release enthält entsprechende verwaltete Abhängigkeiten für Sie.

Was die Infrastruktur betrifft, so führt 6.0 eine Grundlage für Ahead-Of-Time-Transformationen und die entsprechende AOT-Verarbeitungsunterstützung für Spring-Anwendungskontexte ein. Dies ermöglicht eine erstklassige Unterstützung für native GraalVM-Images mit Spring Boot 3. Sie können auch die virtuellen Threads von Project Loom mit Spring-Anwendungen erforschen und in den Checkpoint-Restore-Ansatz von Project CRaC für schnellere JVM-Starts eintauchen, die beide derzeit noch in der Vorschau sind, aber voraussichtlich zu erstklassigen Features für Spring Framework 6.x-basierte Anwendungen werden.

In Spring Framework 6.0 sind viele weitere Funktionen und Verbesserungen verfügbar, z.B. ein HTTP-Schnittstellen-Client, Unterstützung für RFC 7807-Problemdetails und Micrometer-basierte Beobachtbarkeit für HTTP-Clients. Bitte besuchen Sie unsere Seite What’s New für einen umfassenden Überblick und probieren Sie 6.0.0 frühzeitig aus!

Neu: https://mas.to/@ullenboom

Erster Release Candidate von Spring Boot 3

Details unter https://spring.io/blog/2022/10/20/spring-boot-3-0-0-rc1-available-now,

Mein Spring-Boot-Buch entwickelt sich gut, es gibt keine großen Showstopper. Hibernate 6 ergibt bei einer @ManyToMany Assoziation eine komischer Ausnahme, das was bei Hibernate 5 nicht so war; zum Glück, wenn man von EAGER auf LAZY geht (ist eh Standard), ist das kein Problem mehr.

Kleine Änderungen gegenüber SB 2 betreffen @AutoConfiguration bei eigenen Autokonfigurationen, aber im Allgemeinen ist der Aufwand für eine SB 3-Migration gering, da SB 2.7 verschiedene Sachen vorbereitet hat, etwa spring.factories fällt weg oder der WebSecurityConfigurerAdapter.

Der https://github.com/spring-projects-experimental/spring-boot-migrator kann automatisch migrieren.

Meine aktuellen Spring-Kurse basieren auf SB 2, im nächsten Jahr werde ich diese zu einem großen Kurs zusammenfassen, der dann auf SB 3 basiert.

Spring Boot 2.7.0 ist final, danach kommt 3.0

Siehe https://spring.io/blog/2022/05/19/spring-boot-2-7-0-available-now

Interessant finde ich den Ort der Auto-Konfiguration, der jetzt nicht mehr spring.factories ist, sondern META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. Und bei Spring Security, dass der https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.html deprecated ist.

Alle andere Neuerungen unter https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes

Nach Spring Boot 2.7 wird es mit Spring Boot 3 weitergehen, Spring Boot 2.8 ist nicht geplant. https://spring.io/projects/spring-boot#support

Die nächsten Tage werde ich meine Spring Kurs https://www.udemy.com/course/dependency-injection-spring-boot-spring-framework/?referralCode=935D6CF5782896E9674B aktualisieren.

Get the latest version of a maven groupId:artifactId via Node.js script

// npm install node-fetch
import fetch from 'node-fetch';
const groupId = "org.apache.maven.plugins";
const artifactId = "maven-compiler-plugin";
const url = `http://search.maven.org/solrsearch/select?q=g:"${groupId}"+AND+a:"${artifactId}"`;
const response = await fetch(url);
const body = await response.json();
const version = body.response.docs[0].latestVersion;
console.log(version);

 

Code Snippets in Java API Doku geplant (JEP 413)

Interessantes Feature, was die Javadoc doch dicker machen könnte. Geplant:

/**
 * The following code shows how to use {@code Optional.isPresent}:
 * {@snippet :
 * if (v.isPresent()) {
 *     System.out.println("v: " + v.get());
 * }
 * }
 */

Interessant wird das ganze durch Includes (wie bei Asciidoc):
/**
 * The following code shows how to use {@code Optional.isPresent}:
 * {@snippet file="ShowOptional.java" region="example"}
 */
Dinge können zum Beispiel fett hervorgehoben werden:
/**
 * A simple program.
 * {@snippet :
 * class HelloWorld {
 *     public static void main(String... args) {
 *         System.out.println("Hello World!");      // @highlight substring="println"
 *     }
 * }
 * }
 */
Und Texte können ersetzt werden:
/**
 * A simple program.
 * {@snippet :
 * class HelloWorld {
 *     public static void main(String... args) {
 *         System.out.println("Hello World!");  // @replace regex='".*"' replacement="..."
 *     }
 * }
 * }
 */

Ziemlich wild, würdet ihr so was nutzen für eure Javadoc? Ich nutzte bisher immer Testfälle, um eine API zu zeigen und auch zu lernen.

Zum Weiterlesen: https://openjdk.java.net/jeps/413

Spring Boot 3 in 2022 + Neues Spring Buch entsteht

Ankündigung unter https://spring.io/blog/2021/09/02/a-java-17-and-jakarta-ee-9-baseline-for-spring-framework-6:

As announced at SpringOne yesterday, Spring Framework 6 and Spring Boot 3 are planned towards a high-end baseline for their general availability in Q4 2022:

  • Java 17+ (from Java 8-17 in the Spring Framework 5.3.x line)
  • Jakarta EE 9+ (from Java EE 7-8 in the Spring Framework 5.3.x line)

This forward-looking baseline will provide significant benefits in our API design and integration efforts, shining through to your application code and future-proofing the framework as well as your applications for many years to come. However, it comes at a cost, of course: Spring Framework 6 and Spring Boot 3 based applications will require a minimum of JDK 17 at runtime, as well as a minimum of Tomcat 10 / Jetty 11 (for Jakarta EE 9 compatibility). Even more importantly, there might be some changes required in your application source code: e.g. the javax to jakarta namespace change in Jakarta EE 9 wherever you’re touching the Servlet API, JPA, Bean Validation, etc.

While this may sound aggressive at first, keep in mind that we’re talking about a Q4 2022 release: By that time, not only will JDK 17 have superseded JDK 11 as the next Long-Term Support release for more than a year, it will itself have been superseded by JDK 18 and JDK 19 as then-available feature releases, with JDK 20 approaching its feature freeze already. Same for Jakarta EE 9: We expect Jakarta EE 10 to be out by then, and yet another generation of Tomcat, Jetty and co to be supported as runtime options. Keeping up the baseline above as a minimum, this allows for picking up further Java evolution in the Spring Framework 6.x generation, with Java 17 and Jakarta EE 9 only being the start.

Der erste Milestone Spring Boot 3.0.0-M1 ist mittlerweile eingetrudelt: https://spring.io/blog/2022/01/20/spring-boot-3-0-0-m1-is-now-available

Mitte 2022 beginne ich mit einem neuen Buch. Thema: Spring Boot 3 und Spring Framework 6. Wer bereit ist, aktiv Feedback zu geben, kann sich als Probeleser*in gerne melden, dann schicke ich Kapitel für Kapitel zu. Google-E-Mail: ullenboom@

Für Spring Boot 2 und Spring Framework 5 gibt es von mir auch eine Videoserie für Dependency-Injection.

 

QueryDSL 5.0.0 verfügbar

Aus den Release-Notes: https://github.com/querydsl/querydsl/releases/tag/QUERYDSL_5_0_0:

This release of QueryDSL targets Java 8 minimally and comes with various improvements to make QueryDSL ready for the modern Java ecosystem.
This version also removes joda-time:joda-time, com.google.guava:guava and com.google.code.findbugs:jsr305 as required runtime dependencies for using QueryDSL.

QueryDSL 5.0 is the long awaited major release after the QueryDSL project was left mostly unmaintained for over two years.

New features

  • #2672 – Various performance and code improvements possible by targeting Java 8 source level.
  • #2672 – Added Fetchable#stream() which returns a Stream<T>.
    Make sure that the returned stream is always closed to free up resources, for example using try-with-resources.
    It does not suffice to rely on a terminating operation on the stream for this (i.e. forEach, collect).
  • #2324 – Removal of Guava as dependency.
    Almost no required transitive dependencies to get started with QueryDSL.
    And no more conflicts with Guava versions required by your other tools or own application.
  • #2025joda-time:joda-time is no longer a required dependency for querydsl-sql.
    By default, the Java 8 date/time API is used for date/time operations.
    The joda-time:joda-time types will still be registered automatically if they are on the classpath.
  • #2215 – MongoDB 4 support through the Document API
  • #2697 – Allow com.querydsl.core.alias.Alias.* to be used on a JRE by relying on ECJ as compiler
  • #2479 – Swap out JSR305 for Jetbrains Annotations.
    Because the Jetbrains Annotations, contrary to the JSR305 annotations, use a Class retention level, Jetbrains Annotations
    does not have to be available at runtime and is not a transitive dependency.
  • #658 – Added JPAExpressions#treat which can be used to generate JPA 2.1 Treated path expressions.
  • #2666 – More descriptive error message when using unsupported query features in JPA.
  • #2106 – Support NullsLast ordering in querydsl-collections.
  • #2404 – Upgrade of JTS / Geolatte in querydsl-spatial
  • #2320 – Make Spatial support available to HibernateDomainExporter and JPADomainExporter.
  • #2612 – Support jakarta.* packages for new Jakarta EE releases (available through thejakarta classifiers for Maven)
  • #1376 – Return typed expression from nullif and coalesce methods.
  • #1828 – Kotlin Codegen support
  • #2798 – Java Record support

Wie ist denn der Einsatz bei euch von QueryDSL? Eine wichtiger Baustein in eurer Unternehmensanwendung?

Inselraus: parse*(…)- und print*()-Methoden in DatatypeConverter für Hex-Ausgaben

Das javax.xml.bind-Paket bietet eine Klasse DatatypeConverter, die eigentlich für die Abbildung von XML-Typen auf Java-Typen gedacht ist, doch auch so einige nützliche Methoden bereitstellt. Wir finden in der Klasse statische parse*(String)-Methoden und print*(…)-Methoden: Die ersten konvertieren einen String in diverse Datentypen – etwa short parseShort(String) –, und die zweiten formatieren einen bestimmten Datentyp in einen String – etwa String printShort(short). Für die meisten Methoden gibt es mit String.valueOf(…) und den parse*(…)/toString(…)-Methoden in den Wrapper-Klassen bessere Alternativen, und die Umwandlung von Datumswerten und Fließkommazahlen ist nicht lokalisiert, doch hervorzuheben sind folgende zwei Methoden:

final class javax.xml.bind.DatatypeConverter

  • staticbyte[]parseHexBinary(StringlexicalXSDHexBinary)
  • staticStringprintHexBinary(byte[]val)

Mit diesen statischen Methoden können leicht Byte-Arrays in die String-Repräsentationen hexadezimal konvertiert werden. Das ist nötig, wenn etwa Bytes in einer Text-Konfigurationsdatei abgelegt werden sollen. DatatypeConverter bietet auch Methoden für eine Base64-Kodierung, allerdings sind die geschachtelten Klassen in java.util.Base64 üblicher.

Beispiel:

Konvertiere ein Byte-Array in eine String-Repräsentation, einmal im klassischen Hex-Format, einmal in Base64-Kodierung:

byte[] bytes = { 1, 2, 3, (byte) 254, (byte) 255 };
String s1 = DatatypeConverter.printHexBinary( bytes );
String s2 = DatatypeConverter.printBase64Binary( bytes );
System.out.println( s1 ); // 010203FEFF
System.out.println( s2 ); // AQID/v8=
// Arrays.equals( bytes, DatatypeConverter.parseHexBinary( s1 ) ) == true
// Arrays.equals( bytes, DatatypeConverter.parseBase64Binary( s2 ) ) == true

Inselupdate: strictfp verschwindet in Java 17

Zwischen Java 1.2 und Java 16 unterstützte der Java-Compiler das Schlüsselwort strictfp. Die Unterscheidung sollte es der Laufzeitumgebung erlauben, nicht strikt nach der IEEE-754-Spezifikation zu arbeiten und damit schneller auf der lokalen Hardware Java-Programme auszuführen. Doch seit 20 Jahren unterstützen alle Prozessoren IEEE-754, und die Unterscheidung ist irrelevant geworden – alle von der JVM ausgeführten mathematischen Operationen sind wie im IEEE-754-Standard beschrieben. Mit dem Abschied von strictfp wird auch die Klasse StrictMath irrelevant.

Details: https://openjdk.java.net/jeps/306

Inselraus: Vererbung und Überschattung von statischen Variablen in Schnittstellen

Die Konstanten einer Schnittstelle können einer anderen Schnittstelle vererbt werden. Dabei gibt es einige kleine Einschränkungen. Wir wollen an einem Beispiel sehen, wie sich die Vererbung auswirkt, wenn gleiche Bezeichner in den Unterschnittstellen erneut verwendet werden. Die Basis unseres Beispiels ist die Schnittstelle BaseColors mit ein paar Deklarationen von Farben. Zwei Unterschnittstellen erweitern BaseColors, und zwar CarColors und PlaneColors, die für Farbdeklarationen für Autos und Flugzeuge stehen. Eine besondere Schnittstelle FlyingCarColors erweitert die beiden Schnittstellen CarColors und PlaneColors, denn es gibt auch fliegende Autos, die eine Farbe haben können.

interface BaseColors {
  int WHITE   = 0;
  int BLACK   = 1;
  int GREY    = 2;
}
interface CarColors extends BaseColors {
  int WHITE   = 1;
  int BLACK   = 0;
}
interface PlaneColors extends BaseColors {
  int WHITE   = 0;
  int GREY    = 2;
}
interface FlyingCarColors extends CarColors, PlaneColors { }
public class Colors {
  public static void main( String[] args ) {
    System.out.println( BaseColors.GREY );      // 2
    System.out.println( CarColors.GREY );       // 2
    System.out.println( BaseColors.BLACK );     // 1
    System.out.println( CarColors.BLACK );      // 0
    System.out.println( PlaneColors.BLACK );    // 1
    System.out.println( FlyingCarColors.WHITE );
       //  field FlyingCarColors.WHITE is ambiguous
    System.out.println( FlyingCarColors.GREY );
       //  field FlyingCarColors.GREY is ambiguous
  }
}

Die erste wichtige Tatsache ist, dass unsere drei Schnittstellen ohne Fehler übersetzt werden können, aber nicht die Klasse Colors. Das Programm und der Compiler zeigen folgendes Verhalten:

  • Schnittstellen vererben ihre Eigenschaften an die Unterschnittstellen. CarColors und auch PlaneColors erben die Farben WHITE, BLACK und GREY aus BaseColors.
  • Konstanten dürfen überdeckt werden. CarColors vertauscht die Farbdeklarationen von WHITE und BLACK und gibt ihnen neue Werte. Wird jetzt der Wert BLACK verlangt, liefert die Umgebung den Wert 0, während BaseColors.BLACK 1 ergibt. Auch PlaneColors überdeckt die Konstanten WHITE und GREY, obwohl die Farben mit dem gleichen Wert belegt sind.
  • Erbt eine Schnittstelle von mehreren Oberschnittstellen, so ist es zulässig, dass die Oberschnittstellen jeweils eine gleichlautende Objektvariable haben. So erbt etwa FlyingCarColors von CarColors und PlaneColors die Einträge WHITE, BLACK und GREY.
  • Unterschnittstellen können aus zwei Oberschnittstellen die Objektvariablen gleichen Namens übernehmen, auch wenn die Konstanten einen unterschiedlichen Wert haben. Das testet der Compiler nicht. FlyingCarColors bekommt aus CarColors ein WHITE mit 1, aber aus PlaneColors das WHITE mit 0. Daher ist in dem Beispiel Colors auch der Zugriff WHITE nicht möglich und führt zu einem Compilerfehler. Bei der Benutzung muss ein unmissverständlich qualifizierter Name verwendet werden, der deutlich macht, welche Objektvariable gemeint ist, also zum Beispiel CarColors.WHITE oder PlaneColors.WHITE. Ähnliches gilt für die Farbe GREY. Obwohl Grau durch die ursprüngliche Deklaration bei BaseColors und auch bei der Überschattung in PlaneColors immer 2 ist, ist die Nutzung durch FlyingCarColors.GREY nicht zulässig. Das ist ein guter Schutz gegen Fehler, denn wenn der Compiler dies durchließe, könnte sich im Nachhinein die Belegung von GREY in BaseColors oder PlaneColors ohne Neuübersetzung aller Klassen ändern und zu Schwierigkeiten führen. Diesen Fehler – die Oberschnittstellen haben für eine Konstante unterschiedliche Werte – müsste die Laufzeitumgebung erkennen. Doch das ist nicht möglich, und in der Regel setzt der Compiler die Werte auch direkt in die Aufrufstelle ein, und ein Zugriff auf die Konstantenwerte der Schnittstelle findet nicht mehr statt.