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.

Nächstes Jahr beginne ich mit einem neuen Buch; Thema: Spring Boot 3 und Spring Framework 6. Mit Rheinwerk haben wir uns überlegt, dass wir uns ein Spring Boot 2.x Buch sparen, daher wird es erst in rund 14 Monaten etwas.

Wer Probeleser*in sein möchte, bitte melden. Die ersten fertigen Kapitel gibt es vermutlich in ca. 1/2 Jahr.

Spring Boot Update 2.4.1

Details siehe https://github.com/spring-projects/spring-boot/releases/tag/v2.4.1

Dependency Upgrades:

  • Upgrade to Caffeine 2.8.8 #24443
  • Upgrade to DB2 JDBC 11.5.5.0 #24383
  • Upgrade to Dropwizard Metrics 4.1.16 #24384
  • Upgrade to Groovy 2.5.14 #24385
  • Upgrade to Hibernate 5.4.25.Final #24386
  • Upgrade to HttpCore 4.4.14 #24387
  • Upgrade to Infinispan 11.0.8.Final #24388
  • Upgrade to Jetty 9.4.35.v20201120 #24389
  • Upgrade to jOOQ 3.14.4 #24390
  • Upgrade to Kotlin 1.4.21 #24391
  • Upgrade to Kotlin Coroutines 1.4.2 #24392
  • Upgrade to MariaDB 2.7.1 #24393
  • Upgrade to Micrometer 1.6.2 #24281
  • Upgrade to Mockito 3.6.28 #24394
  • Upgrade to Netty 4.1.55.Final #24444
  • Upgrade to Netty tcNative 2.0.35.Final #24445
  • Upgrade to Nimbus JOSE JWT 9.1.3 #24395
  • Upgrade to Reactor 2020.0.2 #24275
  • Upgrade to Spring AMQP 2.3.2 #24288
  • Upgrade to Spring Batch 4.3.1 #24291
  • Upgrade to Spring Data 2020.0.2 #24284
  • Upgrade to Spring Framework 5.3.2 #24278
  • Upgrade to Spring HATEOAS 1.2.2 #24285
  • Upgrade to Spring Integration 5.4.2 #24442
  • Upgrade to Spring Kafka 2.6.4 #24294
  • Upgrade to Spring Security 5.4.2 #24297
  • Upgrade to SQLite JDBC 3.32.3.3 #24446
  • Upgrade to Tomcat 9.0.41 #24447
  • Upgrade to Undertow 2.2.3.Final #24397

Spring Tools 4.8.0 freigegeben

Details siehe https://spring.io/blog/2020/09/16/spring-tools-4-8-0-released. Kurz zusammengefasst:

  • updated to Eclipse 2020-09 release
  • ships with an embedded JDK14 runtime, no need to install or configure a specific JDK to run the IDE on anymore
  • includes Eclipse Docker tooling by default now (in addition to the nice docker integration for the Spring Boot Dashboard)
  • includes Wild Web Developer tooling now (#354), including advanced support for JavaScript, TypeScript, HTML, and more
  • (Eclipse) improvement: added actions to pause an resume docker containers

Download der Spring Tools 4: https://spring.io/tools/

Spring Framework 5.2 fertig

Ankündigung im Blog https://spring.io/blog/2019/09/30/spring-framework-5-2-goes-ga:

Spring Framework 5.2 requires JDK 8 or higher and specifically supports JDK 11 as the current long-term support branch as well as JDK 13 as the latest OpenJDK release. It comes with many performance improvements (affecting startup time as well as peak performance) and further steps taken towards GraalVM native image support.

This release deeply integrates with Kotlin 1.3 and provides first-class support for Kotlin coroutines on top of Spring WebFlux. Furthermore, it comes with reactive messaging integration for the RSocket protocol as well as reactive transaction management for R2DBC, MongoDB and Neo4j (with datastore integration provided by Spring Data’s modules).

As of the upcoming Spring Boot 2.2 RC1 release, you’ll be able to consume Spring Framework 5.2 GA through start.spring.io!

Wichtige Links:

Spring Tools 4.1.1 freigegeben

Details siehe https://spring.io/blog/2019/01/25/spring-tools-4-1-1-released

Zitat:

Highlights from this release include:

  • (Spring Boot) easy navigation via symbols now available for regular Spring projects (not using Spring Boot)
  • (Spring Boot) live hover for beans and bean wirings now available for regular Spring projects (not using Spring Boot)
  • (Spring Boot) support for deprecated propertied added to property editors, including corresponding quick fixes
  • (Eclipse) boot dashboard now shows environment information including all properties and their values for running boot apps
  • (Eclipse) default distribution brings back support for local Tomcat servers and deploying war-packaged boot apps to those local servers
  • various bug fixes

Actuator in Spring Boot

Gesundheitzustand über den Actuator

Das Actuator-Modul von Spring Boot stellt HTTP-Endpunkte bereit, die Auskunft über den Zustand der Anwendung geben und es erlauben, die Anwendung zu beeinflussen.

Eigene Informationen über den „Gesundheitzustand“ lassen sich einbauen.

Die Informationen werden über REST veröffentlicht, können aber auch über JMX abgerufen werden.

Achtung: Actuator 1 und Actuator 2 unterscheiden sich deutlich!

Actuator in der POM

Einbinden wie üblich über die POM:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Da ganze funktioniert nur im Web-Modus, also muss org.springframework.boot:spring-boot-starter-web auch in der POM-Datei sein.

Starte man nun die Anwendung, kann man im Log die neuen Endpunkte sehen.

Aktivierung der Endpunkte

Damit ein Actuator Endpunkt über HTPP verfügbar ist, muss er enabled und exposed sein.

  • Die meisten Endpunkte sind standardmäßig deaktiviert.
  • Man kann nur actuator/health und actuator/health nutzen, und selbst da ist wenig Info vorhanden.

Um mehr Endpunkte freizuschalten setze man die die application.properties:

management.endpoints.web.exposure.include=*

Der Wildcard * aktiviert alle, alternativ zählt man kommasepariert auf.

Auswahl einiger Spring Boot Endpunkte

Die Endpunkte liegen alle eine Ebene unter http://localhost:8080/actuator:

/beans
Alle Spring-Beans
/env
Das Environment-Properties
/health
„health information“
/info
Applikationsinformationen
/loggers
Welche Log-Level für welche Pakete gelten
/metrics
Metriken über die aktuelle Anwendung, es muss eine weitere ID folgen, etwa metrics/http.server.requests
/threaddump
Thread-Dump

Management Endpoint URL

Natürlich lassen sich Dinge wie

  • Server-Port
  • URL-Basispfad
  • freigeschaltete Endpunkte
  • SSL-Verschlüsselung

konfigurieren.

Bin ich gesund?

Unter /health finden sich Informationen über den „Gesundheitszustand“ der Anwendung.

Der Status kann UP oder DOWN sein. Standardmäßig gibt es nur status

Authentifizierung

Bei einer nicht-authentifizierten Verbindung bekommt man nicht mehr zu sehen als den Status.

Um das zu ändern, müssen wir 1. in die POM mit aufnehmen:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Dann 2. in application.properties (zum Testen!):

management.endpoint.health.show-details=always
spring.security.user.name=user
spring.security.user.password=pass

Nach dem Neustart der Anwendung und Neuladen der Webseite erfolgt eine BASIC-Authentifizierung. Geben wir user/pass ein, sehen wir alles.

Spring Retry

Das Spring Retry Projekt

Spring Retry ist ein Zusatzprojekt (https://github.com/spring-projects/spring-retry), um Codeblöcke wiederholt auszuführen, wenn sie zu einem Fehler führen.

  • Das ist nützlich beim Ansprechen von Remote-Diensten, die temporär nicht verfügbar sein können.

Als erstes müssen zwei Dependencies in unsere POM:

<dependency>
	<groupId>org.springframework.retry</groupId>
	<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aspects</artifactId>
</dependency>

@Retryable

Schreiben wir eine Bean, die zwei Anläufe braucht, eine Operation durchzuführen.

@Component
class Achiever {

  int tries = 1;

  @Retryable   
  public int tryIt() {   

    System.out.println( "Runde " + tries );
    tries++;

    if ( tries != 3 )
      throw new IllegalStateException( "Runde nicht 3" );

    return tries;
  }
}
Retryable drückt aus, das eine Operation bei Ausnahmen automatisch neu aufgerufen werden soll.
Die Methoden können eine Rückgabe haben, oder auch keine.

@EnableRetry

Damit Spring für die annotierten Methoden einen Proxy baut, müssen wir eine @Configuration mit @EnableRetry annotieren.

Wir können nun den Achiever injizieren:

@Autowired Achiever archiever;

Und die Methode ausführen:

System.out.println( "Vor dem Aufruf" );
int i = archiever.tryIt();
System.out.println( "Nach dem Aufruf ist i=" + i );

Auf der Konsole erscheint keine Exception. Nur:

Vor dem Aufruf
Runde 1
Runde 2
Nach dem Aufruf

Der Annotationsty Retryable

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Retryable {
	String interceptor() default "";
	Class<? extends Throwable>[] value() default {};
	Class<? extends Throwable>[] include() default {};
	Class<? extends Throwable>[] exclude() default {};
	String label() default "";
	boolean stateful() default false;
	int maxAttempts() default 3;              
	String maxAttemptsExpression() default "";
	Backoff backoff() default @Backoff();
	String exceptionExpression() default "";
}
Die Anzahl der Wiederholungen ist nicht unendlich, Spring stoppt standardmäßig bei 3.

Ausblick

Die Dokumentation unter https://github.com/spring-projects/spring-retry zeit weitere Möglichkeiten auf. Ein zusätzliches Beispiel:

@Retryable
public void tryIO() throws IOException {
  throw new IOException( LocalTime.now().toString() );
}

@Recover  
public void recover( IOException e ) {
  System.err.println( "Aarrrrg: " + e );
}
Die mit @Recover annotierte Methode wird am Ende einer nicht erfolgreichen Aufrufkette aufgerufen.

Caching in Spring Boot nutzen

Optimierung durch Caching

Bei Methoden, die idempotent sind, also zu einem Parameter immer den gleichen Wert liefern, kann Spring einen Cache zur Optimierung einsetzen.

  • Im Grunde ist der Cache ein Assoziativspeicher, der die Methodenparameter als Schlüssel nutzt.

Beispiele:

  • Berechnen einer Prüfsumme
  • Dateiinhalt
  • DNS-Cache

Achtung: Gewisse Cache-Inhalte können nach einer Zeit ungültig werden.

Caching in Spring

Um das Caching zu aktivieren annotiert man

  1. eine @Configuration mit @EnableCaching
  2. eine public (!!!) Methode mit @Cacheable und vergibt einen Cache-Namen.

@Cacheable-Beispiel (1/2)

@Component
class Hash {

  @Cacheable( "md5" )
  public byte[] md5( String text ) {

    System.out.println( "hash: " + text );
    try {
      MessageDigest md = MessageDigest.getInstance( "MD5" );
      return md.digest( text.getBytes( StandardCharsets.UTF_8 ) );
    }
    catch ( NoSuchAlgorithmException e ) {
      throw new IllegalStateException( e );
    }
  }
}

@Cacheable-Beispiel (2/2)

Wir können Hash injizieren

@Autowired
Hash hash;

und nutzen

byte[] md5_1 = hash.md5( "tutego" );
byte[] md5_2 = hash.md5( "tutego" );
System.out.println( Arrays.equals( md5_1, md5_2 ) ); // true

System.out.println( hash.getClass() ); // com.tutego.boot.basic.Hash$$EnhancerBySpringCGLIB$$4548965

Ausblick (1/2)

  • Spring generiert den Schlüssel zum Cache aus den Argumente. Man kann kann eigene KeyGenerator en verwenden.
  • Mit der SpEL lassen sich von Anfrageobejkte zum Beispiel die Schlüssel erfragen, etwa so @Cacheable(cacheNames="books", key="#isbn.rawNumber") .
  • Unter Umständen sollen große Objekte nicht in den Cache, hier kann man eine Bedingung angeben: @Cacheable(cacheNames="book", condition="#name.length() < 32")
  • Ist eine Methode mit @CachePut annotiert, kann man den Cache selbst füllen, bzw. Werte überschreiben.
  • Ist eine Methode mit @CacheEvict annotiert, etwa @CacheEvict(cacheNames="books", allEntries=true) public void clear() wird der Cache gelöscht.

Ausblick (2/2)

Das Spring Framework kann automatisch diverse Caching-Implementierung nutzen.

  • Standardmäßig ist es eine ConcurrentHashMap.
  • Unterstützt werden u.a.: EhCache 2.x, Hazelcast, Infinispan, Couchbase, Redis, Caffeine.
  • Spring erkennt anhand des Eintrags im Klassenpfad, was gewünscht ist.

In der application.[properties|yml] lassen sich dann Dinge wie Lebensdauer, Größe, etc. extern konfigurieren.

JMX in Spring Boot nutzen

Die Java Management Extensions (JMX)

  • Die Java Management Extensions (JMX) ist eine Spezifikation zur Verwaltung und Überwachung von Java-Anwendungen.
  • Teile der JMX Spezifikation sind ab Java 5 in der Java SE integriert.
  • Es gibt einen JMX Agent, an dem Managed Beans angemeldet werden.
  • Von außen lassen sich diese Managed Beans erfragen.
  • JConsole ist ein GUI-Programm im JDK, das zur Verwaltung von MBeans verwendet werden kann.

JMX in Spring Boot

Spring nutzt drei Annotationen, um Managed Beans mit ihren Zuständen und Operationen beim JMX Agent zu registrieren:

@ManagedResource
Definiert mit der Typ-Annotation die Managed Bean
@ManagedAttribute
Definiert ein Attribut (Setter/Getter)
@ManagedOperation
Definiert eine Operation

Beispiel-Managed-Bean

package com.tutego.boot.actuator;

import java.util.HashMap;
import java.util.Map;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;

@Component
@ManagedResource
public class StringMapManagedBean {
  private final Map<String, String> map = new HashMap<>();

  @ManagedAttribute
  public int getSize() {
    return map.size();
  }

  @ManagedOperation
  public String get( String key ) {
    return map.get( key );
  }


  @ManagedOperation
  public String put( String key, String value ) {
    return map.put( key, value );
  }

  public void remove( String key ) {
    map.remove( key );
  }
}

Annotationstyp @ManagedResource

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface ManagedResource {

	@AliasFor("objectName")
	String value() default "";

	@AliasFor("value")
	String objectName() default "";

	String description() default "";

	int currencyTimeLimit() default -1;
	boolean log() default false;
	String logFile() default "";
	String persistPolicy() default "";
	int persistPeriod() default -1;
	String persistName() default "";
	String persistLocation() default "";
}

Springs eigene Managed Beans

Spring Boot veröffentlicht selbst diverse Managed Beans unter der Domäne org.springframework.boot.

  • org.springframework.boot:type=Endpoint,name=Health zum Beispiel für die Gesundheitsinformationen

Sie lassen sich abschalten mit management.endpoints.jmx.exposure.exclude=*.

Falls mehrere ApplicationContext exisistieren kommt es zum Namenskonflikt; der lässt sich mit management.endpoints.jmx.unique-names=true vermeiden.

Der Domain-Name lässt sich anpassen mit management.endpoints.jmx.domain.

Folien zum Einsatz von Annotationen in Spring

Habe bei SlideShare interessante Folien zum Einsatz von Annotationen in der Spring-Entwicklung gefunden. Zunächst werden allgemeine Annotationen aus dem Java SE und besonders aus dem Java EE-Umfeld vorgestellt. Dann werden JPA und REST im Kontext von Spring an Beispielen erklärt. Zum Schluss folgt noch etwa Spring MVC und wie dort Annotationen die Konfiguration vereinfachen.

SpringSource und Groovy/Grails und SpringSource mit Adobe

SpringSource (http://www.springsource.com/) macht große Schritte. Zum einen durch den Aufkauf von G2one (http://www.g2one.com/), die sich der Beratung von Weiterentwicklung von Groovy und Grails verschrieben haben:

SpringSource,
the maker of the Spring framework have just announced they are acquiring G2One, Inc.,
the Groovy/Grails company. You can learn more about this announcement here:

Nun arbeitet SpringSource auch mit Adobe zusammen und Flash näher an Spring zu setzen. Das Spring-Framework integriert dazu BlazeDS (http://opensource.adobe.com/wiki/display/blazeds/BlazeDS/), eine unter LGPL stehende Remoting- und Messaging-Technologie. Mit BlazeDS kann Flex auf Java-Methoden auf der Serverseite zugreifen, so wie es auch JavaScript über DWR (http://directwebremoting.org/) kann. Die Ankündigung zur Zusammenarbeit:

  • http://www.springsource.com/node/1077

Und überall sitzt die OSGi Service Platform drunter…

Unter http://www.earthtimes.org/articles/show/world-leading-enterprise-application-server-providers,541827.shtml und http://www.osgi.org/blog/2008/09/impressive-press-release.html führen die Autoren auf, wie beliebt mittlerweile OSGi als Basis für Java EE Container ist. Peter Kriens führt folgende Container auf:

  1. IBM Websphere. They started in 2006 and aggresively moved their code on OSGi. Obviously it helped that IBM has committed itself to OSGi since day -1.
  2. Oracle WebLogic. Formerly known as BEA weblogic. BEA was one of the first companies public touting the advantages of OSGi, clearing the road for others.
  3. Paremus Infiniflow. Paremus has pioneered the use of OSGi in highly distributed application servers allowing the system to scale to unprecendented heights.
  4. ProSyst ModuleFusion. ProSyst is the key provider of OSGi technology in the embedded worlds but originated from the development of a J2EE server. They are now back in this market with an offering based completely on OSGi.
  5. Redhat JBoss. JBoss already worked with a microkernel approach but recognized the advantages of a standard two years ago.
  6. SAP Netweaver. Well, they are not yet based on OSGi, but they clearly see their future based on the OSGi specifications and are becoming more and more active in the OSGi Alliance.
  7. SpringSource Application Platform. The company that simplified Enterprise development with their Spring Framework decided to create their own offering in the application server market completely based on the OSGi specifications.
  8. Sun Glassfish. And last, but definitely not least, Sun decided to use OSGi in the JEE reference implementation Glassfish. They clearly take OSGi extremely serious nowadays since they also hired Richard S. Hall. It is so good to see Sun back at the OSGi Alliance.

Interessant sind zwei Feststellungen:

  1. In der Regel geben die Container die OSGi-Implementierung nicht nach oben weiter, abstrahieren also von den Internas. Nur einige Produkte erlauben, auch selbst OSGi-Bundles anzumelden.
  2. Java EE und das SpringFramework sind beides Nutznießer der OSGi-Plattform. Man kann nun fragen, ob man sich überhaupt noch mit OSGi selbst beschäftigen muss, wenn etwa GlassFish oder http://www.springsource.com/products/suite/applicationplatform gute Abstraktionen bieten.