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:
@@ -25,21 +25,28 @@
|
||||
<description>SDK commons</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- CVE-2025-48976: excluded from spring-cloud-starter-openfeign, so add it explicitly, remove this if exclusion is removed -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
<version>${spring-cloud-starter-openfeign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.hateoas</groupId>
|
||||
<artifactId>spring-hateoas</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-hc5</artifactId>
|
||||
<version>${openfeign-hc5.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>tools.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk18on</artifactId>
|
||||
|
||||
@@ -11,8 +11,8 @@ package org.eclipse.hawkbit.sdk;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
|
||||
@@ -44,7 +44,6 @@ import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import feign.Contract;
|
||||
import feign.Feign;
|
||||
import feign.FeignException;
|
||||
@@ -85,6 +84,7 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
|
||||
@Slf4j
|
||||
@Builder
|
||||
@@ -264,7 +264,7 @@ public class HawkbitClient {
|
||||
private Object callMultipartFormDataRequest(
|
||||
final Method method, final Object[] args,
|
||||
final Tenant tenant, final Controller controller,
|
||||
final Class<?>[] parameterTypes, final ObjectMapper objectMapper) throws URISyntaxException, IOException {
|
||||
final Class<?>[] parameterTypes, final ObjectMapper objectMapper) throws IOException, URISyntaxException {
|
||||
final PostMapping postMapping = method.getAnnotation(PostMapping.class);
|
||||
final Annotation[][] parametersAnnotations = method.getParameterAnnotations();
|
||||
// build path - replace @PathVariables
|
||||
@@ -322,11 +322,11 @@ public class HawkbitClient {
|
||||
|
||||
return method.getReturnType() == ResponseEntity.class
|
||||
? new ResponseEntity<>(
|
||||
deserialize(
|
||||
conn.getInputStream(),
|
||||
(Class<?>) ((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0],
|
||||
objectMapper),
|
||||
HttpStatusCode.valueOf(responseCode))
|
||||
deserialize(
|
||||
conn.getInputStream(),
|
||||
(Class<?>) ((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0],
|
||||
objectMapper),
|
||||
HttpStatusCode.valueOf(responseCode))
|
||||
: deserialize(conn.getInputStream(), method.getReturnType(), objectMapper);
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ public class HawkbitClient {
|
||||
}
|
||||
}
|
||||
|
||||
private static Object deserialize(final InputStream is, final Class<?> type, final ObjectMapper objectMapper) throws IOException {
|
||||
private static Object deserialize(final InputStream is, final Class<?> type, final ObjectMapper objectMapper) {
|
||||
return type == void.class || type == Void.class ? null : objectMapper.readValue(is, type);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.sdk;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
@ConfigurationProperties(prefix = "hawkbit.server")
|
||||
@Data
|
||||
|
||||
@@ -15,8 +15,8 @@ import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import org.eclipse.hawkbit.sdk.ca.CA;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@ConfigurationProperties("hawkbit.tenant")
|
||||
@Data
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<description>Test / Example of how SDK could be used to for devices and for Mgmt API access</description>
|
||||
|
||||
<properties>
|
||||
<spring-shell.version>3.4.1</spring-shell.version>
|
||||
<spring-shell.version>4.0.0</spring-shell.version>
|
||||
<spring.app.class>org.eclipse.hawkbit.sdk.demo.multidevice.MultiDeviceApp</spring.app.class>
|
||||
<start-class>${spring.app.class}</start-class>
|
||||
</properties>
|
||||
@@ -52,6 +52,11 @@
|
||||
<artifactId>spring-shell-starter</artifactId>
|
||||
<version>${spring-shell.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell-jline</artifactId>
|
||||
<version>${spring-shell.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.amqp</groupId>
|
||||
<artifactId>spring-rabbit</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.sdk.Tenant;
|
||||
import org.eclipse.hawkbit.sdk.Tenant.Dmf;
|
||||
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
|
||||
import org.springframework.boot.amqp.autoconfigure.RabbitProperties;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,10 +24,9 @@
|
||||
<name>hawkBit :: SDK :: Parent</name>
|
||||
|
||||
<properties>
|
||||
<spring-cloud-starter-openfeign.version>4.3.1</spring-cloud-starter-openfeign.version>
|
||||
<openfeign-hc5.version>13.11</openfeign-hc5.version>
|
||||
<bouncycastle.version>1.83</bouncycastle.version>
|
||||
<java.version>${java.client.version}</java.version>
|
||||
|
||||
<bouncycastle.version>1.83</bouncycastle.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
|
||||
Reference in New Issue
Block a user