From 4e3ee68630622688f205bde6ec3309104b0ddf15 Mon Sep 17 00:00:00 2001 From: Stanislav Trailov Date: Tue, 18 Nov 2025 11:14:29 +0200 Subject: [PATCH] Fix auto cleanup actions configuration value on set (#2805) Signed-off-by: strailov --- .../JpaTenantConfigurationManagement.java | 35 +++++++++++++++---- .../TenantConfigurationManagementTest.java | 28 +++++++++++++++ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java index 9a6071257..a8cb668e4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java @@ -54,6 +54,7 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.context.ApplicationContext; +import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.ConcurrencyFailureException; @@ -182,12 +183,32 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana final List configurationList = new ArrayList<>(); configurations.forEach((keyName, value) -> { final TenantConfigurationKey configurationKey = tenantConfigurationProperties.fromKeyName(keyName); - if (!configurationKey.getDataType().isAssignableFrom(value.getClass())) { - throw new TenantConfigurationValidatorException(String.format( - "Cannot parse the value %s of type %s into the type %s defined by the configuration key.", - value, value.getClass(), configurationKey.getDataType())); + + Object convertedValue = value; + final Class targetType = configurationKey.getDataType(); + if (!targetType.isAssignableFrom(value.getClass())) { + try { + // if not assignable and it is a number - try conversion + // for example tries to assign Integer to Long + if (value instanceof Number number && Number.class.isAssignableFrom(targetType)) { + log.debug("Type {} not assignable from {} . Will try conversion.", targetType, value.getClass()); + convertedValue = CONVERSION_SERVICE.convert(number, targetType); + if (convertedValue == null) { + throw new IllegalArgumentException( + String.format("Failed to convert %s. Convertor returned null as a result", value)); + } + } else { + throw new IllegalArgumentException( + String.format("Value %s is not a Number but %s and cannot perform conversion converted.", value, value.getClass())); + } + } catch (final ConversionException | IllegalArgumentException ex) { + throw new TenantConfigurationValidatorException(String.format( + "Cannot convert the value %s of type %s to the type %s defined by the configuration key.", + value, value.getClass(), targetType)); + } } - configurationKey.validate(value, applicationContext); + + configurationKey.validate(convertedValue, applicationContext); // additional validation for specific configuration keys if (POLLING_TIME.equals(configurationKey.getKeyName())) { final PollingTime pollingTime = new PollingTime(value.toString()); @@ -201,9 +222,9 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana JpaTenantConfiguration tenantConfiguration = tenantConfigurationRepository.findByKey(configurationKey.getKeyName()); if (tenantConfiguration == null) { - tenantConfiguration = new JpaTenantConfiguration(configurationKey.getKeyName(), value.toString()); + tenantConfiguration = new JpaTenantConfiguration(configurationKey.getKeyName(), convertedValue.toString()); } else { - tenantConfiguration.setValue(value.toString()); + tenantConfiguration.setValue(convertedValue.toString()); } assertValueChangeIsAllowed(keyName, tenantConfiguration); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementTest.java index b10c4a2e2..9040c0816 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TenantConfigurationManagementTest.java @@ -24,6 +24,7 @@ import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; @@ -323,6 +324,33 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple .isInstanceOf(InvalidTenantConfigurationKeyException.class); } + @Test + void storeTenantConfigNumberValue() { + final String configKey = TenantConfigurationKey.ACTION_CLEANUP_AUTO_EXPIRY; + // set auto cleanup for 1 day in Integer ms + tenantConfigurationManagement.addOrUpdateConfiguration(configKey, 86400000); + + // expect long + Long autoCleanupDaysInMs = tenantConfigurationManagement.getConfigurationValue(configKey, Long.class).getValue(); + Assertions.assertEquals(86400000, autoCleanupDaysInMs); + tenantConfigurationManagement.addOrUpdateConfiguration(configKey, 86400000); + + // 30 days 2,592,000,000 ms as Long + tenantConfigurationManagement.addOrUpdateConfiguration(configKey, 2592000000L); + autoCleanupDaysInMs = tenantConfigurationManagement.getConfigurationValue(configKey, Long.class).getValue(); + Assertions.assertEquals(2592000000L, autoCleanupDaysInMs); + } + + @Test + void throwExceptionIfTryingToConvertOtherValueThanNumber() { + final String configKey = TenantConfigurationKey.ACTION_CLEANUP_AUTO_EXPIRY; + // set auto cleanup for 1 day in String ms + assertThatThrownBy(() -> + tenantConfigurationManagement.addOrUpdateConfiguration(configKey, "86400000")) + .as("Cannot convert the value 86400000 of type String to the type Long defined by the configuration key.") + .isInstanceOf(TenantConfigurationValidatorException.class); + } + private static Duration getDurationByTimeValues(final long hours, final long minutes, final long seconds) { return Duration.ofHours(hours).plusMinutes(minutes).plusSeconds(seconds); }