[#2845] Bump Spring boot to 4.x (#2941)

Notes:
1. (!) Eclipselink shall be migrated to 5.0 (in 4.0.8 there are incompatible classes, e.g EJBQueryImpl doesn't implement some newer methods). In the moment is with beta (5.0.0-B12) - JUST for testing!
2. (!) Ethlo plugin doesn't work with Eclipselink 5.0, it builds with Eclipselink 4.0.8 (could be a problem)
3. Dependencies - new starters, test starters changes, some dependencies refactoring
4. Auto-configs split - package changes, some properties classes changes
5. Spring nullable org.springframework.lang.Nullable/NonNull are depecated and replaced with jspcify -> org.jspecify.annotations.Nullable/NonNull (NullMarked)
6. Lombok config - adding lombok.addNullAnnotations=jspecify - to do not mess annotations
7. Distributed lock table changes - SP_LOCK table db migration
8. Spring Retry replaced with Spring Core Retry - does repace retry in hawkbit
9. Specifications -> added Update/Delete(/Predicate) Specifications and JpaSpecificationExecutor changed
10. HawkbitBaseRepositoryFactoryBean modified to register properly
11. Jackson - 2 -> 3, package migrations, finals are not deserialized by default(enable finals deserialization, consider make non-final), too ‘smart’ tries to set complex objects instead of using non args constructor (-> @JsonIgnore), some other default configs made

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2026-04-14 11:31:41 +03:00
committed by GitHub
parent 23cd368e00
commit 1be473b22c
172 changed files with 1254 additions and 1045 deletions

View File

@@ -28,8 +28,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.core.command.annotation.Command;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
/**
@@ -58,7 +58,7 @@ public class DeviceApp {
return new AuthenticationSetupHelper(tenant, hawkbitClient);
}
@ShellComponent
@Component
public static class Shell {
private final DdiTenant ddiTenant;
@@ -78,25 +78,25 @@ public class DeviceApp {
.controllerId(controllerId)
.securityToken(ObjectUtils.isEmpty(securityToken)
? (ObjectUtils.isEmpty(ddiTenant.getTenant().getGatewayToken())
? AuthenticationSetupHelper.randomToken()
: securityToken)
? AuthenticationSetupHelper.randomToken()
: securityToken)
: securityToken)
.build(),
updateHandler.orElse(null)).setOverridePollMillis(10_000);
}
@ShellMethod(key = "setup")
@Command(name = "setup")
public void setup() {
mgmtApi.setupTargetAuthentication();
mgmtApi.setupTargetSecureToken(device.getController().getControllerId(), device.getTargetSecurityToken());
}
@ShellMethod(key = "start")
@Command(name = "start")
public void start() {
device.start(Executors.newSingleThreadScheduledExecutor());
}
@ShellMethod(key = "stop")
@Command(name = "stop")
public void stop() {
device.stop();
}

View File

@@ -21,13 +21,13 @@ import org.eclipse.hawkbit.sdk.dmf.UpdateHandler;
import org.eclipse.hawkbit.sdk.dmf.amqp.Amqp;
import org.eclipse.hawkbit.sdk.dmf.amqp.AmqpProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.amqp.autoconfigure.RabbitProperties;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellOption;
import org.springframework.shell.core.command.annotation.Command;
import org.springframework.shell.core.command.annotation.Option;
import org.springframework.stereotype.Component;
/**
* Abstract class representing DDI device connecting directly to hawkVit.
@@ -51,7 +51,7 @@ public class DmfApp {
return new DmfTenant(tenant, amqp);
}
@ShellComponent
@Component
public static class Shell {
private final DmfTenant dmfTenant;
@@ -62,36 +62,36 @@ public class DmfApp {
this.updateHandler = updateHandler.orElse(null);
}
@ShellMethod(key = "start-one")
public void startOne(@ShellOption("--id") final String controllerId) {
@Command(name = "start-one")
public void startOne(@Option(longName = "--id") final String controllerId) {
dmfTenant.getController(controllerId).ifPresentOrElse(
dmfController -> dmfController.start(Executors.newSingleThreadScheduledExecutor()),
() -> dmfTenant.createController(Controller.builder().controllerId(controllerId).build(), updateHandler)
.start(Executors.newSingleThreadScheduledExecutor()));
}
@ShellMethod(key = "stop-one")
public void stopOne(@ShellOption("--id") final String controllerId) {
@Command(name = "stop-one")
public void stopOne(@Option(longName = "--id") final String controllerId) {
dmfTenant.getController(controllerId).ifPresentOrElse(
DmfController::stop,
() -> log.error("Controller with id {} not found!", controllerId));
}
@ShellMethod(key = "start")
@Command(name = "start")
public void start(
@ShellOption(value = "--prefix", defaultValue = "") final String prefix,
@ShellOption(value = "--offset", defaultValue = "0") final int offset,
@ShellOption(value = "--count") final int count) {
@Option(longName = "--prefix") final String prefix,
@Option(longName = "--offset", defaultValue = "0") final int offset,
@Option(longName = "--count") final int count) {
for (int i = 0; i < count; i++) {
startOne(toId(prefix, offset + i));
}
}
@ShellMethod(key = "stop")
@Command(name = "stop")
public void stop(
@ShellOption(value = "--prefix", defaultValue = "") final String prefix,
@ShellOption(value = "--offset", defaultValue = "0") final int offset,
@ShellOption(value = "--count") final int count) {
@Option(longName = "--prefix") final String prefix,
@Option(longName = "--offset", defaultValue = "0") final int offset,
@Option(longName = "--count") final int count) {
for (int i = 0; i < count; i++) {
stopOne(toId(prefix, offset + i));
}

View File

@@ -27,9 +27,9 @@ import org.eclipse.hawkbit.sdk.mgmt.AuthenticationSetupHelper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellOption;
import org.springframework.shell.core.command.annotation.Command;
import org.springframework.shell.core.command.annotation.Option;
import org.springframework.stereotype.Component;
/**
* Abstract class representing DDI device connecting directly to hawkVit.
@@ -59,7 +59,7 @@ public class MultiDeviceApp {
return new AuthenticationSetupHelper(defaultTenant, hawkbitClient);
}
@ShellComponent
@Component
public static class Shell {
private final DdiTenant ddiTenant;
@@ -74,14 +74,14 @@ public class MultiDeviceApp {
this.updateHandler = updateHandler.orElse(null);
}
@ShellMethod(key = "setup")
@Command(name = "setup")
public void setup() {
mgmtApi.setupTargetAuthentication();
setup = true;
}
@ShellMethod(key = "start-one")
public void startOne(@ShellOption("--id") final String controllerId) {
@Command(name = "start-one")
public void startOne(@Option(longName = "--id") final String controllerId) {
final String securityTargetToken;
if (setup) {
securityTargetToken = mgmtApi.setupTargetSecureToken(controllerId, null);
@@ -102,29 +102,29 @@ public class MultiDeviceApp {
);
}
@ShellMethod(key = "stop-one")
public void stopOne(@ShellOption("--id") final String controllerId) {
@Command(name = "stop-one")
public void stopOne(@Option(longName = "--id") final String controllerId) {
ddiTenant.getController(controllerId).ifPresentOrElse(
DdiController::stop,
() -> log.error("Controller with id {} not found!", controllerId));
}
@ShellMethod(key = "start")
@Command(name = "start")
public void start(
@ShellOption(value = "--prefix", defaultValue = "") final String prefix,
@ShellOption(value = "--offset", defaultValue = "0") final int offset,
@ShellOption(value = "--count") final int count) {
@Option(longName = "--prefix", defaultValue = "") final String prefix,
@Option(longName = "--offset", defaultValue = "0") final int offset,
@Option(longName = "--count") final int count) {
for (int i = 0; i < count; i++) {
startOne(toId(prefix, offset + i));
}
}
@ShellMethod(key = "stop")
@Command(name = "stop")
public void stop(
@ShellOption(value = "--prefix", defaultValue = "") final String prefix,
@ShellOption(value = "--offset", defaultValue = "0") final int offset,
@ShellOption(value = "--count") final int count) {
@Option(longName = "--prefix") final String prefix,
@Option(longName = "--offset", defaultValue = "0") final int offset,
@Option(longName = "--count") final int count) {
for (int i = 0; i < count; i++) {
stopOne(toId(prefix, offset + i));
}