diff --git a/README.md b/README.md index 2fde2b3d8..249a59b2f 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,24 @@ There are clients outside of the Eclipse IoT eco system as well, e.g.: * [rauc-hawkbit](https://github.com/rauc/rauc-hawkbit) which is a python-based hawkBit client application and library for the [RAUC](https://github.com/rauc/rauc) update framework. + +# Runtime dependencies and support + +## Java Runtime Environment: 1.8 + +## SQL database + +| Database | H2 | MySQL/MariaDB | MS SQL Server | IBM DB2 | +|---|---|---|---|---| +| DDLs maintained by project | X | X | X | X | +| Test dependencies defined | X | X | X | - | +| Versions tested | 1.4 | MySQL 5.6/5.7, AWS Aurora | MS SQL Server 2017 | DB2 Server v11.1 | +| Docker image with driver provided | X | X | - | - | +| JDBC driver | [H2 1.4](https://github.com/h2database/h2database) | [MariaDB Connector/J 2.0](https://github.com/MariaDB/mariadb-connector-j) | [MSSQL-JDBC 6.4](https://github.com/Microsoft/mssql-jdbc) | - | +| Status | Test, Dev, Trial | Production grade | Experimental | Test, Dev | + +## (Optional) RabbitMQ: 3.6,3.7 + # Getting Started We are providing a [Spring Boot](https://projects.spring.io/spring-boot/) based reference [Update Server](hawkbit-runtime/hawkbit-update-server) including embedded H2 DB for test and evaluation purposes. @@ -101,7 +119,6 @@ $ java -jar ./hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulat * Provide standard runtime by means of Spring Boot based hawkBit update server (and hopefully a docker image). * And of course tons of usability improvements and bug fixes. * Future releases - * Complete repository refactoring. * Integrate with Eclipse hono as DMF provider. * Flexible DMF messaging infrastructure (e.g. with Spring Cloud Stream). * Migrate to Spring Framework 5, Spring Boot 2 and Vaadin 8 diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancel.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancel.java index c117dea14..13caff68f 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancel.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiCancel.java @@ -29,7 +29,6 @@ public class DdiCancel { * the action */ public DdiCancel(final String id, final DdiCancelActionToStop cancelAction) { - super(); this.id = id; this.cancelAction = cancelAction; } diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java index 526227601..b20768faa 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java @@ -32,7 +32,6 @@ public class DdiControllerBase extends ResourceSupport { * configuration of the SP target */ public DdiControllerBase(final DdiConfig config) { - super(); this.config = config; } diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiProgress.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiProgress.java index cf73fc5c0..be776455c 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiProgress.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiProgress.java @@ -34,7 +34,6 @@ public class DdiProgress { */ @JsonCreator public DdiProgress(@JsonProperty("cnt") final Integer cnt, @JsonProperty("of") final Integer of) { - super(); this.cnt = cnt; this.of = of; } diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiResult.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiResult.java index 2138f12ae..d5b2d8845 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiResult.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiResult.java @@ -38,7 +38,6 @@ public class DdiResult { @JsonCreator public DdiResult(@JsonProperty("finished") final FinalResult finished, @JsonProperty("progress") final DdiProgress progress) { - super(); this.finished = finished; this.progress = progress; } diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java index 0170d67f9..6af4a7cf2 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiStatus.java @@ -46,7 +46,6 @@ public class DdiStatus { @JsonCreator public DdiStatus(@JsonProperty("execution") final ExecutionStatus execution, @JsonProperty("result") final DdiResult result, @JsonProperty("details") final List details) { - super(); this.execution = execution; this.result = result; this.details = details; diff --git a/hawkbit-ddi-resource/pom.xml b/hawkbit-ddi-resource/pom.xml index b19c22264..83c4475d6 100644 --- a/hawkbit-ddi-resource/pom.xml +++ b/hawkbit-ddi-resource/pom.xml @@ -71,16 +71,6 @@ tests test - - com.h2database - h2 - test - - - org.mariadb.jdbc - mariadb-java-client - test - javax.el javax.el-api diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java index ca1c7d896..67da0c4a7 100644 --- a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java +++ b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java @@ -304,8 +304,8 @@ public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest { assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("127.0.0.1")); assertThat(target.getCreatedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY"); assertThat(target.getCreatedAt()).isGreaterThanOrEqualTo(create); - assertThat(target.getLastModifiedBy()).isNull(); - assertThat(target.getLastModifiedAt()).isZero(); + assertThat(target.getLastModifiedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY"); + assertThat(target.getLastModifiedAt()).isGreaterThanOrEqualTo(create); } diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/pom.xml b/hawkbit-dmf/hawkbit-dmf-amqp/pom.xml index 15f30293d..8ebbd997c 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/pom.xml +++ b/hawkbit-dmf/hawkbit-dmf-amqp/pom.xml @@ -78,16 +78,6 @@ ${project.version} test - - com.h2database - h2 - test - - - org.mariadb.jdbc - mariadb-java-client - test - ru.yandex.qatools.allure allure-junit-adaptor diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java index 770c8ffcf..cc5a15266 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java @@ -32,26 +32,16 @@ public class MgmtArtifactHash { /** * Public constructor. - * - * @param sha1 - * @param md5 */ public MgmtArtifactHash(final String sha1, final String md5) { - super(); this.sha1 = sha1; this.md5 = md5; } - /** - * @return the sha1 - */ public String getSha1() { return sha1; } - /** - * @return the md5 - */ public String getMd5() { return md5; } diff --git a/hawkbit-mgmt-resource/pom.xml b/hawkbit-mgmt-resource/pom.xml index 9b1407077..1cb70aa05 100644 --- a/hawkbit-mgmt-resource/pom.xml +++ b/hawkbit-mgmt-resource/pom.xml @@ -74,16 +74,6 @@ tests test - - com.h2database - h2 - test - - - org.mariadb.jdbc - mariadb-java-client - test - javax.el javax.el-api diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java index d8358a609..6722aaa6e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java @@ -331,8 +331,7 @@ public interface DeploymentManagement { Optional findActionWithDetails(long actionId); /** - * Retrieves all active {@link Action}s of a specific target ordered by - * action ID. + * Retrieves all active {@link Action}s of a specific target. * * @param pageable * the page request parameter for paging and sorting the result @@ -347,8 +346,7 @@ public interface DeploymentManagement { Page findActiveActionsByTarget(@NotNull Pageable pageable, @NotEmpty String controllerId); /** - * Retrieves all inactive {@link Action}s of a specific target ordered by - * action ID. + * Retrieves all inactive {@link Action}s of a specific target. * * @param pageable * the page request parameter for paging and sorting the result diff --git a/hawkbit-repository/hawkbit-repository-jpa/pom.xml b/hawkbit-repository/hawkbit-repository-jpa/pom.xml index d5a8d16c8..80fa78b08 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/pom.xml +++ b/hawkbit-repository/hawkbit-repository-jpa/pom.xml @@ -87,16 +87,6 @@ ${project.version} test - - com.h2database - h2 - test - - - org.mariadb.jdbc - mariadb-java-client - test - javax.el javax.el-api diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java index 2c0a9efa8..36fd11eae 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java @@ -154,7 +154,7 @@ public interface ActionRepository extends BaseEntityRepository, * the {@link DistributionSet} on which will be filtered * @return the found {@link Action}s */ - @Query("Select a from JpaAction a where a.target = :target and a.distributionSet = :ds order by a.id") + @Query("Select a from JpaAction a where a.target = :target and a.distributionSet = :ds") Page findByTargetAndDistributionSet(final Pageable pageable, @Param("target") final JpaTarget target, @Param("ds") JpaDistributionSet ds); @@ -174,16 +174,18 @@ public interface ActionRepository extends BaseEntityRepository, * ordered by action ID. Loads also the lazy * {@link Action#getDistributionSet()} field. * - * @param target + * @param pageable + * page parameters + * @param controllerId * to search for * @param active * {@code true} for all actions which are currently active, * {@code false} for inactive - * @return a list of actions ordered by action ID + * @return a list of actions */ @EntityGraph(value = "Action.ds", type = EntityGraphType.LOAD) - @Query("Select a from JpaAction a where a.target.controllerId = :target and a.active= :active order by a.id") - Page findByActiveAndTarget(Pageable pageable, @Param("target") String target, + @Query("Select a from JpaAction a where a.target.controllerId = :controllerId and a.active = :active") + Page findByActiveAndTarget(Pageable pageable, @Param("controllerId") String controllerId, @Param("active") boolean active); /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java index ae69c0259..efa2847f6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java @@ -456,8 +456,8 @@ public class JpaControllerManagement implements ControllerManagement { } final Query updateQuery = entityManager.createNativeQuery( - "UPDATE sp_target t SET t.last_target_query = #last_target_query WHERE t.controller_id IN (" - + formatQueryInStatementParams(paramMapping.keySet()) + ") AND t.tenant = #tenant"); + "UPDATE sp_target SET last_target_query = #last_target_query WHERE controller_id IN (" + + formatQueryInStatementParams(paramMapping.keySet()) + ") AND tenant = #tenant"); paramMapping.entrySet().forEach(entry -> updateQuery.setParameter(entry.getKey(), entry.getValue())); updateQuery.setParameter("last_target_query", currentTimeMillis); @@ -635,7 +635,7 @@ public class JpaControllerManagement implements ControllerManagement { final Long statusCount = actionStatusRepository.countByAction(action); if (statusCount >= quotaManagement.getMaxStatusEntriesPerAction()) { - throw new QuotaExceededException(ActionStatus.class, statusCount, + throw new QuotaExceededException(ActionStatus.class, statusCount + 1, quotaManagement.getMaxStatusEntriesPerAction()); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java index 28029690c..d8b8af3f2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java @@ -72,6 +72,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.PlatformTransactionManager; @@ -115,6 +116,7 @@ public class JpaDeploymentManagement implements DeploymentManagement { private final OfflineDsAssignmentStrategy offlineDsAssignmentStrategy; private final TenantConfigurationManagement tenantConfigurationManagement; private final SystemSecurityContext systemSecurityContext; + private final Database database; JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository, final DistributionSetRepository distributionSetRepository, final TargetRepository targetRepository, @@ -123,7 +125,7 @@ public class JpaDeploymentManagement implements DeploymentManagement { final ApplicationContext applicationContext, final AfterTransactionCommitExecutor afterCommit, final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager, final TenantConfigurationManagement tenantConfigurationManagement, - final SystemSecurityContext systemSecurityContext) { + final SystemSecurityContext systemSecurityContext, final Database database) { this.entityManager = entityManager; this.actionRepository = actionRepository; this.distributionSetRepository = distributionSetRepository; @@ -142,6 +144,7 @@ public class JpaDeploymentManagement implements DeploymentManagement { applicationContext, actionRepository, actionStatusRepository); this.tenantConfigurationManagement = tenantConfigurationManagement; this.systemSecurityContext = systemSecurityContext; + this.database = database; } @Override @@ -521,7 +524,8 @@ public class JpaDeploymentManagement implements DeploymentManagement { } private Specification createSpecificationFor(final String controllerId, final String rsqlParam) { - final Specification spec = RSQLUtility.parse(rsqlParam, ActionFields.class, virtualPropertyReplacer); + final Specification spec = RSQLUtility.parse(rsqlParam, ActionFields.class, virtualPropertyReplacer, + database); return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb), cb.equal(root.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java index ecc103bff..1cd4e2406 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java @@ -56,7 +56,6 @@ import org.eclipse.hawkbit.repository.model.MetaData; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.tenancy.TenantAware; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEventPublisher; import org.springframework.dao.ConcurrencyFailureException; @@ -65,6 +64,7 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; @@ -82,53 +82,70 @@ import com.google.common.collect.Lists; @Validated public class JpaDistributionSetManagement implements DistributionSetManagement { - @Autowired - private EntityManager entityManager; + private final EntityManager entityManager; - @Autowired - private DistributionSetRepository distributionSetRepository; + private final DistributionSetRepository distributionSetRepository; - @Autowired - private DistributionSetTagManagement distributionSetTagManagement; + private final DistributionSetTagManagement distributionSetTagManagement; - @Autowired - private SystemManagement systemManagement; + private final SystemManagement systemManagement; - @Autowired - private DistributionSetTypeManagement distributionSetTypeManagement; + private final DistributionSetTypeManagement distributionSetTypeManagement; - @Autowired - private DistributionSetMetadataRepository distributionSetMetadataRepository; + private final DistributionSetMetadataRepository distributionSetMetadataRepository; - @Autowired - private TargetFilterQueryRepository targetFilterQueryRepository; + private final TargetFilterQueryRepository targetFilterQueryRepository; - @Autowired - private ActionRepository actionRepository; + private final ActionRepository actionRepository; - @Autowired - private NoCountPagingRepository criteriaNoCountDao; + private final NoCountPagingRepository criteriaNoCountDao; - @Autowired - private ApplicationEventPublisher eventPublisher; + private final ApplicationEventPublisher eventPublisher; - @Autowired - private ApplicationContext applicationContext; + private final ApplicationContext applicationContext; - @Autowired - private TenantAware tenantAware; + private final TenantAware tenantAware; - @Autowired - private VirtualPropertyReplacer virtualPropertyReplacer; + private final VirtualPropertyReplacer virtualPropertyReplacer; - @Autowired - private SoftwareModuleRepository softwareModuleRepository; + private final SoftwareModuleRepository softwareModuleRepository; - @Autowired - private DistributionSetTagRepository distributionSetTagRepository; + private final DistributionSetTagRepository distributionSetTagRepository; - @Autowired - private AfterTransactionCommitExecutor afterCommit; + private final AfterTransactionCommitExecutor afterCommit; + + private final Database database; + + JpaDistributionSetManagement(final EntityManager entityManager, + final DistributionSetRepository distributionSetRepository, + final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement, + final DistributionSetTypeManagement distributionSetTypeManagement, + final DistributionSetMetadataRepository distributionSetMetadataRepository, + final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository, + final NoCountPagingRepository criteriaNoCountDao, final ApplicationEventPublisher eventPublisher, + final ApplicationContext applicationContext, final TenantAware tenantAware, + final VirtualPropertyReplacer virtualPropertyReplacer, + final SoftwareModuleRepository softwareModuleRepository, + final DistributionSetTagRepository distributionSetTagRepository, + final AfterTransactionCommitExecutor afterCommit, final Database database) { + this.entityManager = entityManager; + this.distributionSetRepository = distributionSetRepository; + this.distributionSetTagManagement = distributionSetTagManagement; + this.systemManagement = systemManagement; + this.distributionSetTypeManagement = distributionSetTypeManagement; + this.distributionSetMetadataRepository = distributionSetMetadataRepository; + this.targetFilterQueryRepository = targetFilterQueryRepository; + this.actionRepository = actionRepository; + this.criteriaNoCountDao = criteriaNoCountDao; + this.eventPublisher = eventPublisher; + this.applicationContext = applicationContext; + this.tenantAware = tenantAware; + this.virtualPropertyReplacer = virtualPropertyReplacer; + this.softwareModuleRepository = softwareModuleRepository; + this.distributionSetTagRepository = distributionSetTagRepository; + this.afterCommit = afterCommit; + this.database = database; + } @Override public Optional getWithDetails(final long distid) { @@ -538,7 +555,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { throwExceptionIfDistributionSetDoesNotExist(distributionSetId); final Specification spec = RSQLUtility.parse(rsqlParam, - DistributionSetMetadataFields.class, virtualPropertyReplacer); + DistributionSetMetadataFields.class, virtualPropertyReplacer, database); return convertMdPage( distributionSetMetadataRepository @@ -746,7 +763,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId); final Specification spec = RSQLUtility.parse(rsqlParam, DistributionSetFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return convertDsPage(findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isDeleted(false))), pageable); @@ -761,7 +778,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { final Specification spec = RSQLUtility.parse(rsqlParam, DistributionSetFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return convertDsPage( findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.isDeleted(false))), diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTagManagement.java index 12178a69c..2b7cb8fe0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTagManagement.java @@ -35,6 +35,7 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; @@ -56,13 +57,17 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage private final NoCountPagingRepository criteriaNoCountDao; + private final Database database; + JpaDistributionSetTagManagement(final DistributionSetTagRepository distributionSetTagRepository, final DistributionSetRepository distributionSetRepository, - final VirtualPropertyReplacer virtualPropertyReplacer, final NoCountPagingRepository criteriaNoCountDao) { + final VirtualPropertyReplacer virtualPropertyReplacer, final NoCountPagingRepository criteriaNoCountDao, + final Database database) { this.distributionSetTagRepository = distributionSetTagRepository; this.distributionSetRepository = distributionSetRepository; this.virtualPropertyReplacer = virtualPropertyReplacer; this.criteriaNoCountDao = criteriaNoCountDao; + this.database = database; } @Override @@ -130,7 +135,7 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { final Specification spec = RSQLUtility.parse(rsqlParam, TagFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return convertDsPage(distributionSetTagRepository.findAll(spec, pageable), pageable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java index fbfe8e281..0f53c5b20 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetTypeManagement.java @@ -38,6 +38,7 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; @@ -61,16 +62,19 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana private final VirtualPropertyReplacer virtualPropertyReplacer; private final NoCountPagingRepository criteriaNoCountDao; + private final Database database; JpaDistributionSetTypeManagement(final DistributionSetTypeRepository distributionSetTypeRepository, final SoftwareModuleTypeRepository softwareModuleTypeRepository, final DistributionSetRepository distributionSetRepository, - final VirtualPropertyReplacer virtualPropertyReplacer, final NoCountPagingRepository criteriaNoCountDao) { + final VirtualPropertyReplacer virtualPropertyReplacer, final NoCountPagingRepository criteriaNoCountDao, + final Database database) { this.distributionSetTypeRepository = distributionSetTypeRepository; this.softwareModuleTypeRepository = softwareModuleTypeRepository; this.distributionSetRepository = distributionSetRepository; this.virtualPropertyReplacer = virtualPropertyReplacer; this.criteriaNoCountDao = criteriaNoCountDao; + this.database = database; } @Override @@ -155,9 +159,10 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { - return convertPage(findByCriteriaAPI(pageable, - Arrays.asList(RSQLUtility.parse(rsqlParam, DistributionSetTypeFields.class, virtualPropertyReplacer), - DistributionSetTypeSpecification.isDeleted(false))), + return convertPage( + findByCriteriaAPI(pageable, + Arrays.asList(RSQLUtility.parse(rsqlParam, DistributionSetTypeFields.class, + virtualPropertyReplacer, database), DistributionSetTypeSpecification.isDeleted(false))), pageable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java index a09741a9d..d09239897 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java @@ -46,11 +46,11 @@ import org.eclipse.hawkbit.repository.model.TargetWithActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; @@ -62,26 +62,37 @@ import org.springframework.validation.annotation.Validated; @Transactional(readOnly = true) public class JpaRolloutGroupManagement implements RolloutGroupManagement { - @Autowired - private RolloutGroupRepository rolloutGroupRepository; + private final RolloutGroupRepository rolloutGroupRepository; - @Autowired - private RolloutRepository rolloutRepository; + private final RolloutRepository rolloutRepository; - @Autowired - private ActionRepository actionRepository; + private final ActionRepository actionRepository; - @Autowired - private TargetRepository targetRepository; + private final TargetRepository targetRepository; - @Autowired - private EntityManager entityManager; + private final EntityManager entityManager; - @Autowired - private VirtualPropertyReplacer virtualPropertyReplacer; + private final VirtualPropertyReplacer virtualPropertyReplacer; - @Autowired - private RolloutStatusCache rolloutStatusCache; + private final RolloutStatusCache rolloutStatusCache; + + private final Database database; + + JpaRolloutGroupManagement(final RolloutGroupRepository rolloutGroupRepository, + final RolloutRepository rolloutRepository, final ActionRepository actionRepository, + final TargetRepository targetRepository, final EntityManager entityManager, + final VirtualPropertyReplacer virtualPropertyReplacer, final RolloutStatusCache rolloutStatusCache, + final Database database) { + + this.rolloutGroupRepository = rolloutGroupRepository; + this.rolloutRepository = rolloutRepository; + this.actionRepository = actionRepository; + this.targetRepository = targetRepository; + this.entityManager = entityManager; + this.virtualPropertyReplacer = virtualPropertyReplacer; + this.rolloutStatusCache = rolloutStatusCache; + this.database = database; + } @Override public Optional get(final long rolloutGroupId) { @@ -109,17 +120,11 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId); final Specification specification = RSQLUtility.parse(rsqlParam, RolloutGroupFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); - return convertPage( - rolloutGroupRepository - .findAll( - (root, query, - criteriaBuilder) -> criteriaBuilder.and(criteriaBuilder.equal( - root.get(JpaRolloutGroup_.rollout).get(JpaRollout_.id), rolloutId), - specification.toPredicate(root, query, criteriaBuilder)), - pageable), - pageable); + return convertPage(rolloutGroupRepository.findAll((root, query, criteriaBuilder) -> criteriaBuilder.and( + criteriaBuilder.equal(root.get(JpaRolloutGroup_.rollout).get(JpaRollout_.id), rolloutId), + specification.toPredicate(root, query, criteriaBuilder)), pageable), pageable); } private void throwEntityNotFoundExceptionIfRolloutDoesNotExist(final Long rolloutId) { @@ -206,7 +211,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); final Specification rsqlSpecification = RSQLUtility.parse(rsqlParam, TargetFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return convertTPage(targetRepository.findAll((root, query, criteriaBuilder) -> { final ListJoin rolloutTargetJoin = root.join(JpaTarget_.rolloutTargetGroup); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java index 498791387..415b08a40 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java @@ -85,6 +85,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.jpa.domain.Specification; import org.springframework.integration.support.locks.LockRegistry; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.scheduling.annotation.Async; @@ -148,14 +149,17 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { @Autowired private ApplicationContext applicationContext; + private final Database database; + JpaRolloutManagement(final TargetManagement targetManagement, final DeploymentManagement deploymentManagement, final RolloutGroupManagement rolloutGroupManagement, final DistributionSetManagement distributionSetManagement, final ApplicationContext context, final ApplicationEventPublisher eventPublisher, final VirtualPropertyReplacer virtualPropertyReplacer, - final PlatformTransactionManager txManager, final TenantAware tenantAware, - final LockRegistry lockRegistry) { + final PlatformTransactionManager txManager, final TenantAware tenantAware, final LockRegistry lockRegistry, + final Database database) { super(targetManagement, deploymentManagement, rolloutGroupManagement, distributionSetManagement, context, eventPublisher, virtualPropertyReplacer, txManager, tenantAware, lockRegistry); + this.database = database; } @Override @@ -167,7 +171,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { @Override public Page findByRsql(final Pageable pageable, final String rsqlParam, final boolean deleted) { final List> specList = Lists.newArrayListWithExpectedSize(2); - specList.add(RSQLUtility.parse(rsqlParam, RolloutFields.class, virtualPropertyReplacer)); + specList.add(RSQLUtility.parse(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database)); specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted)); return JpaRolloutHelper.convertPage(findByCriteriaAPI(pageable, specList), pageable); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java index 40a92eb11..f8c92ef8e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleManagement.java @@ -60,7 +60,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.Page; @@ -70,6 +69,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.domain.SliceImpl; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.security.access.prepost.PreAuthorize; @@ -87,32 +87,44 @@ import com.google.common.collect.Lists; @Validated public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { - @Autowired - private EntityManager entityManager; + private final EntityManager entityManager; - @Autowired - private DistributionSetRepository distributionSetRepository; + private final DistributionSetRepository distributionSetRepository; - @Autowired - private SoftwareModuleRepository softwareModuleRepository; + private final SoftwareModuleRepository softwareModuleRepository; - @Autowired - private SoftwareModuleMetadataRepository softwareModuleMetadataRepository; + private final SoftwareModuleMetadataRepository softwareModuleMetadataRepository; - @Autowired - private SoftwareModuleTypeRepository softwareModuleTypeRepository; + private final SoftwareModuleTypeRepository softwareModuleTypeRepository; - @Autowired - private NoCountPagingRepository criteriaNoCountDao; + private final NoCountPagingRepository criteriaNoCountDao; - @Autowired - private AuditorAware auditorProvider; + private final AuditorAware auditorProvider; - @Autowired - private ArtifactManagement artifactManagement; + private final ArtifactManagement artifactManagement; - @Autowired - private VirtualPropertyReplacer virtualPropertyReplacer; + private final VirtualPropertyReplacer virtualPropertyReplacer; + private final Database database; + + JpaSoftwareModuleManagement(final EntityManager entityManager, + final DistributionSetRepository distributionSetRepository, + final SoftwareModuleRepository softwareModuleRepository, + final SoftwareModuleMetadataRepository softwareModuleMetadataRepository, + final SoftwareModuleTypeRepository softwareModuleTypeRepository, + final NoCountPagingRepository criteriaNoCountDao, final AuditorAware auditorProvider, + final ArtifactManagement artifactManagement, final VirtualPropertyReplacer virtualPropertyReplacer, + final Database database) { + this.entityManager = entityManager; + this.distributionSetRepository = distributionSetRepository; + this.softwareModuleRepository = softwareModuleRepository; + this.softwareModuleMetadataRepository = softwareModuleMetadataRepository; + this.softwareModuleTypeRepository = softwareModuleTypeRepository; + this.criteriaNoCountDao = criteriaNoCountDao; + this.auditorProvider = auditorProvider; + this.artifactManagement = artifactManagement; + this.virtualPropertyReplacer = virtualPropertyReplacer; + this.database = database; + } @Override @Transactional @@ -279,7 +291,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable); } @@ -547,7 +559,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement { throwExceptionIfSoftwareModuleDoesNotExist(softwareModuleId); final Specification spec = RSQLUtility.parse(rsqlParam, - SoftwareModuleMetadataFields.class, virtualPropertyReplacer); + SoftwareModuleMetadataFields.class, virtualPropertyReplacer, database); return convertSmMdPage( softwareModuleMetadataRepository .findAll( diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleTypeManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleTypeManagement.java index 9fbaaf37b..8f28fab6a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleTypeManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareModuleTypeManagement.java @@ -33,6 +33,7 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; @@ -55,16 +56,19 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage private final SoftwareModuleRepository softwareModuleRepository; private final NoCountPagingRepository criteriaNoCountDao; + private final Database database; JpaSoftwareModuleTypeManagement(final DistributionSetTypeRepository distributionSetTypeRepository, final SoftwareModuleTypeRepository softwareModuleTypeRepository, final VirtualPropertyReplacer virtualPropertyReplacer, - final SoftwareModuleRepository softwareModuleRepository, final NoCountPagingRepository criteriaNoCountDao) { + final SoftwareModuleRepository softwareModuleRepository, final NoCountPagingRepository criteriaNoCountDao, + final Database database) { this.distributionSetTypeRepository = distributionSetTypeRepository; this.softwareModuleTypeRepository = softwareModuleTypeRepository; this.virtualPropertyReplacer = virtualPropertyReplacer; this.softwareModuleRepository = softwareModuleRepository; this.criteriaNoCountDao = criteriaNoCountDao; + this.database = database; } @Override @@ -87,7 +91,7 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage public Page findByRsql(final Pageable pageable, final String rsqlParam) { final Specification spec = RSQLUtility.parse(rsqlParam, SoftwareModuleTypeFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return convertPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java index 49ce5466b..0b92b0297 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSystemManagement.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.repository.jpa; -import java.math.BigDecimal; import java.util.Collections; import java.util.List; import java.util.function.Consumer; @@ -128,30 +127,29 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst @Override public SystemUsageReport getSystemUsageStatistics() { - BigDecimal sumOfArtifacts = (BigDecimal) entityManager - .createNativeQuery( - "select SUM(file_size) from sp_artifact a INNER JOIN sp_base_software_module sm ON a.software_module = sm.id WHERE sm.deleted = 0") + final Number count = (Number) entityManager.createNativeQuery( + "select SUM(file_size) from sp_artifact a INNER JOIN sp_base_software_module sm ON a.software_module = sm.id WHERE sm.deleted = 0") .getSingleResult(); - if (sumOfArtifacts == null) { - sumOfArtifacts = new BigDecimal(0); + long sumOfArtifacts = 0; + if (count != null) { + sumOfArtifacts = count.longValue(); } // we use native queries to punch through the tenant boundaries. This // has to be used with care! - final Long targets = (Long) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_target") - .getSingleResult(); + final long targets = ((Number) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_target") + .getSingleResult()).longValue(); - final Long artifacts = (Long) entityManager - .createNativeQuery( - "SELECT COUNT(a.id) FROM sp_artifact a INNER JOIN sp_base_software_module sm ON a.software_module = sm.id WHERE sm.deleted = 0") - .getSingleResult(); + final long artifacts = ((Number) entityManager.createNativeQuery( + "SELECT COUNT(a.id) FROM sp_artifact a INNER JOIN sp_base_software_module sm ON a.software_module = sm.id WHERE sm.deleted = 0") + .getSingleResult()).longValue(); - final Long actions = (Long) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_action") - .getSingleResult(); + final long actions = ((Number) entityManager.createNativeQuery("SELECT COUNT(id) FROM sp_action") + .getSingleResult()).longValue(); - return new SystemUsageReportWithTenants(targets, artifacts, actions, - sumOfArtifacts.setScale(0, BigDecimal.ROUND_HALF_UP).longValue(), tenantMetaDataRepository.count()); + return new SystemUsageReportWithTenants(targets, artifacts, actions, sumOfArtifacts, + tenantMetaDataRepository.count()); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java index 30a7f20f8..580a97494 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java @@ -31,13 +31,13 @@ import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecif import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.ConcurrencyFailureException; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specifications; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; @@ -60,14 +60,15 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme private final VirtualPropertyReplacer virtualPropertyReplacer; private final DistributionSetManagement distributionSetManagement; + private final Database database; - @Autowired JpaTargetFilterQueryManagement(final TargetFilterQueryRepository targetFilterQueryRepository, final VirtualPropertyReplacer virtualPropertyReplacer, - final DistributionSetManagement distributionSetManagement) { + final DistributionSetManagement distributionSetManagement, final Database database) { this.targetFilterQueryRepository = targetFilterQueryRepository; this.virtualPropertyReplacer = virtualPropertyReplacer; this.distributionSetManagement = distributionSetManagement; + this.database = database; } @Override @@ -121,7 +122,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme List> specList = Collections.emptyList(); if (!StringUtils.isEmpty(rsqlFilter)) { specList = Collections.singletonList( - RSQLUtility.parse(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer)); + RSQLUtility.parse(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer, database)); } return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable); } @@ -145,7 +146,8 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet)); if (!StringUtils.isEmpty(rsqlFilter)) { - specList.add(RSQLUtility.parse(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer)); + specList.add( + RSQLUtility.parse(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer, database)); } return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable); } @@ -213,7 +215,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme @Override public boolean verifyTargetFilterQuerySyntax(final String query) { - RSQLUtility.parse(query, TargetFields.class, virtualPropertyReplacer); + RSQLUtility.parse(query, TargetFields.class, virtualPropertyReplacer, database); return true; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java index 8c83468e9..d9e4c0cab 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java @@ -53,7 +53,6 @@ import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.tenancy.TenantAware; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEventPublisher; import org.springframework.dao.ConcurrencyFailureException; @@ -63,6 +62,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.domain.SliceImpl; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; @@ -70,6 +70,8 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.validation.annotation.Validated; +import com.google.common.collect.Lists; + /** * JPA implementation of {@link TargetManagement}. * @@ -78,41 +80,54 @@ import org.springframework.validation.annotation.Validated; @Validated public class JpaTargetManagement implements TargetManagement { - @Autowired - private EntityManager entityManager; + private final EntityManager entityManager; - @Autowired - private TargetRepository targetRepository; + private final TargetRepository targetRepository; - @Autowired - private RolloutGroupRepository rolloutGroupRepository; + private final RolloutGroupRepository rolloutGroupRepository; - @Autowired - private DistributionSetRepository distributionSetRepository; + private final DistributionSetRepository distributionSetRepository; - @Autowired - private TargetFilterQueryRepository targetFilterQueryRepository; + private final TargetFilterQueryRepository targetFilterQueryRepository; - @Autowired - private TargetTagRepository targetTagRepository; + private final TargetTagRepository targetTagRepository; - @Autowired - private NoCountPagingRepository criteriaNoCountDao; + private final NoCountPagingRepository criteriaNoCountDao; - @Autowired - private ApplicationEventPublisher eventPublisher; + private final ApplicationEventPublisher eventPublisher; - @Autowired - private ApplicationContext applicationContext; + private final ApplicationContext applicationContext; - @Autowired - private TenantAware tenantAware; + private final TenantAware tenantAware; - @Autowired - private AfterTransactionCommitExecutor afterCommit; + private final AfterTransactionCommitExecutor afterCommit; - @Autowired - private VirtualPropertyReplacer virtualPropertyReplacer; + private final VirtualPropertyReplacer virtualPropertyReplacer; + + private final Database database; + + JpaTargetManagement(final EntityManager entityManager, final TargetRepository targetRepository, + final RolloutGroupRepository rolloutGroupRepository, + final DistributionSetRepository distributionSetRepository, + final TargetFilterQueryRepository targetFilterQueryRepository, + final TargetTagRepository targetTagRepository, final NoCountPagingRepository criteriaNoCountDao, + final ApplicationEventPublisher eventPublisher, final ApplicationContext applicationContext, + final TenantAware tenantAware, final AfterTransactionCommitExecutor afterCommit, + final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) { + this.entityManager = entityManager; + this.targetRepository = targetRepository; + this.rolloutGroupRepository = rolloutGroupRepository; + this.distributionSetRepository = distributionSetRepository; + this.targetFilterQueryRepository = targetFilterQueryRepository; + this.targetTagRepository = targetTagRepository; + this.criteriaNoCountDao = criteriaNoCountDao; + this.eventPublisher = eventPublisher; + this.applicationContext = applicationContext; + this.tenantAware = tenantAware; + this.afterCommit = afterCommit; + this.virtualPropertyReplacer = virtualPropertyReplacer; + this.database = database; + } @Override public Optional getByControllerID(final String controllerId) { @@ -141,13 +156,14 @@ public class JpaTargetManagement implements TargetManagement { .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); return findTargetsBySpec( - RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyReplacer), pageable); + RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, virtualPropertyReplacer, database), + pageable); } @Override public Page findByRsql(final Pageable pageable, final String targetFilterQuery) { - return findTargetsBySpec(RSQLUtility.parse(targetFilterQuery, TargetFields.class, virtualPropertyReplacer), - pageable); + return findTargetsBySpec( + RSQLUtility.parse(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database), pageable); } private Page findTargetsBySpec(final Specification spec, final Pageable pageable) { @@ -215,7 +231,8 @@ public class JpaTargetManagement implements TargetManagement { final String rsqlParam) { throwEntityNotFoundIfDsDoesNotExist(distributionSetID); - final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class, virtualPropertyReplacer); + final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class, virtualPropertyReplacer, + database); return convertPage( targetRepository @@ -251,7 +268,8 @@ public class JpaTargetManagement implements TargetManagement { final String rsqlParam) { throwEntityNotFoundIfDsDoesNotExist(distributionSetId); - final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class, virtualPropertyReplacer); + final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class, virtualPropertyReplacer, + database); return convertPage( targetRepository @@ -430,8 +448,6 @@ public class JpaTargetManagement implements TargetManagement { .when(cb.equal(targetRoot.get(JpaTarget_.assignedDistributionSet).get(JpaDistributionSet_.id), orderByDistributionId), 2) .otherwise(100); - // multiselect statement order by the select case and controllerId - query.distinct(true); // build the specifications and then to predicates necessary by the // given filters final Predicate[] specificationsForMultiSelect = specificationsToPredicate(buildSpecificationList(filterParams), @@ -449,8 +465,7 @@ public class JpaTargetManagement implements TargetManagement { // be mapped directly to a Target entity because the selectCase is not a // attribute of the // Target entity, the the Object array contains the Target on the first - // index (case of the - // multiselect order) of the array and + // index of the array and // the 2nd contains the selectCase int value. final int pageSize = pageable.getPageSize(); final List resultList = entityManager.createQuery(query).setFirstResult(pageable.getOffset()) @@ -488,7 +503,7 @@ public class JpaTargetManagement implements TargetManagement { throwEntityNotFoundIfDsDoesNotExist(distributionSetId); final Specification spec = RSQLUtility.parse(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return findTargetsBySpec( (root, cq, @@ -503,7 +518,7 @@ public class JpaTargetManagement implements TargetManagement { final Collection groups, final String targetFilterQuery) { final Specification spec = RSQLUtility.parse(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return findTargetsBySpec((root, cq, cb) -> cb.and(spec.toPredicate(root, cq, cb), TargetSpecifications.isNotInRolloutGroups(groups).toPredicate(root, cq, cb)), pageRequest); @@ -524,7 +539,7 @@ public class JpaTargetManagement implements TargetManagement { @Override public long countByRsqlAndNotInRolloutGroups(final Collection groups, final String targetFilterQuery) { final Specification spec = RSQLUtility.parse(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); final List> specList = Arrays.asList(spec, TargetSpecifications.isNotInRolloutGroups(groups)); @@ -536,8 +551,8 @@ public class JpaTargetManagement implements TargetManagement { throwEntityNotFoundIfDsDoesNotExist(distributionSetId); final Specification spec = RSQLUtility.parse(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer); - final List> specList = new ArrayList<>(2); + virtualPropertyReplacer, database); + final List> specList = Lists.newArrayListWithExpectedSize(2); specList.add(spec); specList.add(TargetSpecifications.hasNotDistributionSetInActions(distributionSetId)); @@ -579,7 +594,8 @@ public class JpaTargetManagement implements TargetManagement { throwEntityNotFoundExceptionIfTagDoesNotExist(tagId); - final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class, virtualPropertyReplacer); + final Specification spec = RSQLUtility.parse(rsqlParam, TargetFields.class, virtualPropertyReplacer, + database); return convertPage(targetRepository.findAll((Specification) (root, query, cb) -> cb.and( TargetSpecifications.hasTag(tagId).toPredicate(root, query, cb), spec.toPredicate(root, query, cb)), @@ -592,14 +608,14 @@ public class JpaTargetManagement implements TargetManagement { .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); final Specification specs = RSQLUtility.parse(targetFilterQuery.getQuery(), TargetFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return targetRepository.count(specs); } @Override public long countByRsql(final String targetFilterQuery) { final Specification specs = RSQLUtility.parse(targetFilterQuery, TargetFields.class, - virtualPropertyReplacer); + virtualPropertyReplacer, database); return targetRepository.count((root, query, cb) -> { query.distinct(true); return specs.toPredicate(root, query, cb); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java index 634a5c3b3..bfb079622 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java @@ -33,6 +33,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.transaction.annotation.Transactional; @@ -51,12 +52,14 @@ public class JpaTargetTagManagement implements TargetTagManagement { private final TargetRepository targetRepository; private final VirtualPropertyReplacer virtualPropertyReplacer; + private final Database database; JpaTargetTagManagement(final TargetTagRepository targetTagRepository, final TargetRepository targetRepository, - final VirtualPropertyReplacer virtualPropertyReplacer) { + final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) { this.targetTagRepository = targetTagRepository; this.targetRepository = targetRepository; this.virtualPropertyReplacer = virtualPropertyReplacer; + this.database = database; } @Override @@ -102,7 +105,8 @@ public class JpaTargetTagManagement implements TargetTagManagement { @Override public Page findByRsql(final Pageable pageable, final String rsqlParam) { - final Specification spec = RSQLUtility.parse(rsqlParam, TagFields.class, virtualPropertyReplacer); + final Specification spec = RSQLUtility.parse(rsqlParam, TagFields.class, virtualPropertyReplacer, + database); return convertTPage(targetTagRepository.findAll(spec, pageable), pageable); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java index 5ffbfdbf9..319061d06 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java @@ -335,7 +335,6 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { properties.put(PersistenceUnitProperties.LOGGING_LOGGER, "JavaLogger"); // Ensure that we flush only at the end of the transaction properties.put(PersistenceUnitProperties.PERSISTENCE_CONTEXT_FLUSH_MODE, "COMMIT"); - // Enable batch writing properties.put(PersistenceUnitProperties.BATCH_WRITING, "JDBC"); // Batch size @@ -374,8 +373,24 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { */ @Bean @ConditionalOnMissingBean - DistributionSetManagement distributionSetManagement() { - return new JpaDistributionSetManagement(); + DistributionSetManagement distributionSetManagement(final EntityManager entityManager, + final DistributionSetRepository distributionSetRepository, + final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement, + final DistributionSetTypeManagement distributionSetTypeManagement, + final DistributionSetMetadataRepository distributionSetMetadataRepository, + final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository, + final NoCountPagingRepository criteriaNoCountDao, final ApplicationEventPublisher eventPublisher, + final ApplicationContext applicationContext, final TenantAware tenantAware, + final VirtualPropertyReplacer virtualPropertyReplacer, + final SoftwareModuleRepository softwareModuleRepository, + final DistributionSetTagRepository distributionSetTagRepository, + final AfterTransactionCommitExecutor afterCommit, final JpaProperties properties) { + return new JpaDistributionSetManagement(entityManager, distributionSetRepository, distributionSetTagManagement, + systemManagement, distributionSetTypeManagement, distributionSetMetadataRepository, + targetFilterQueryRepository, actionRepository, criteriaNoCountDao, eventPublisher, applicationContext, + tenantAware, virtualPropertyReplacer, softwareModuleRepository, distributionSetTagRepository, + afterCommit, properties.getDatabase()); + } /** @@ -389,9 +404,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { final DistributionSetTypeRepository distributionSetTypeRepository, final SoftwareModuleTypeRepository softwareModuleTypeRepository, final DistributionSetRepository distributionSetRepository, - final VirtualPropertyReplacer virtualPropertyReplacer, final NoCountPagingRepository criteriaNoCountDao) { + final VirtualPropertyReplacer virtualPropertyReplacer, final NoCountPagingRepository criteriaNoCountDao, + final JpaProperties properties) { return new JpaDistributionSetTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository, - distributionSetRepository, virtualPropertyReplacer, criteriaNoCountDao); + distributionSetRepository, virtualPropertyReplacer, criteriaNoCountDao, properties.getDatabase()); } /** @@ -423,8 +439,18 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { */ @Bean @ConditionalOnMissingBean - TargetManagement targetManagement() { - return new JpaTargetManagement(); + TargetManagement targetManagement(final EntityManager entityManager, final TargetRepository targetRepository, + final RolloutGroupRepository rolloutGroupRepository, + final DistributionSetRepository distributionSetRepository, + final TargetFilterQueryRepository targetFilterQueryRepository, + final TargetTagRepository targetTagRepository, final NoCountPagingRepository criteriaNoCountDao, + final ApplicationEventPublisher eventPublisher, final ApplicationContext applicationContext, + final TenantAware tenantAware, final AfterTransactionCommitExecutor afterCommit, + final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties) { + return new JpaTargetManagement(entityManager, targetRepository, rolloutGroupRepository, + distributionSetRepository, targetFilterQueryRepository, targetTagRepository, criteriaNoCountDao, + eventPublisher, applicationContext, tenantAware, afterCommit, virtualPropertyReplacer, + properties.getDatabase()); } /** @@ -444,9 +470,9 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { TargetFilterQueryManagement targetFilterQueryManagement( final TargetFilterQueryRepository targetFilterQueryRepository, final VirtualPropertyReplacer virtualPropertyReplacer, - final DistributionSetManagement distributionSetManagement) { + final DistributionSetManagement distributionSetManagement, final JpaProperties properties) { return new JpaTargetFilterQueryManagement(targetFilterQueryRepository, virtualPropertyReplacer, - distributionSetManagement); + distributionSetManagement, properties.getDatabase()); } /** @@ -457,8 +483,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { @Bean @ConditionalOnMissingBean TargetTagManagement targetTagManagement(final TargetTagRepository targetTagRepository, - final TargetRepository targetRepository, final VirtualPropertyReplacer virtualPropertyReplacer) { - return new JpaTargetTagManagement(targetTagRepository, targetRepository, virtualPropertyReplacer); + final TargetRepository targetRepository, final VirtualPropertyReplacer virtualPropertyReplacer, + final JpaProperties properties) { + return new JpaTargetTagManagement(targetTagRepository, targetRepository, virtualPropertyReplacer, + properties.getDatabase()); } /** @@ -471,9 +499,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { DistributionSetTagManagement distributionSetTagManagement( final DistributionSetTagRepository distributionSetTagRepository, final DistributionSetRepository distributionSetRepository, - final VirtualPropertyReplacer virtualPropertyReplacer, final NoCountPagingRepository criteriaNoCountDao) { + final VirtualPropertyReplacer virtualPropertyReplacer, final NoCountPagingRepository criteriaNoCountDao, + final JpaProperties properties) { return new JpaDistributionSetTagManagement(distributionSetTagRepository, distributionSetRepository, - virtualPropertyReplacer, criteriaNoCountDao); + virtualPropertyReplacer, criteriaNoCountDao, properties.getDatabase()); } /** @@ -483,8 +512,17 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { */ @Bean @ConditionalOnMissingBean - SoftwareModuleManagement softwareModuleManagement() { - return new JpaSoftwareModuleManagement(); + SoftwareModuleManagement softwareModuleManagement(final EntityManager entityManager, + final DistributionSetRepository distributionSetRepository, + final SoftwareModuleRepository softwareModuleRepository, + final SoftwareModuleMetadataRepository softwareModuleMetadataRepository, + final SoftwareModuleTypeRepository softwareModuleTypeRepository, + final NoCountPagingRepository criteriaNoCountDao, final AuditorAware auditorProvider, + final ArtifactManagement artifactManagement, final VirtualPropertyReplacer virtualPropertyReplacer, + final JpaProperties properties) { + return new JpaSoftwareModuleManagement(entityManager, distributionSetRepository, softwareModuleRepository, + softwareModuleMetadataRepository, softwareModuleTypeRepository, criteriaNoCountDao, auditorProvider, + artifactManagement, virtualPropertyReplacer, properties.getDatabase()); } /** @@ -498,9 +536,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { final DistributionSetTypeRepository distributionSetTypeRepository, final SoftwareModuleTypeRepository softwareModuleTypeRepository, final VirtualPropertyReplacer virtualPropertyReplacer, - final SoftwareModuleRepository softwareModuleRepository, final NoCountPagingRepository criteriaNoCountDao) { + final SoftwareModuleRepository softwareModuleRepository, final NoCountPagingRepository criteriaNoCountDao, + final JpaProperties properties) { return new JpaSoftwareModuleTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository, - virtualPropertyReplacer, softwareModuleRepository, criteriaNoCountDao); + virtualPropertyReplacer, softwareModuleRepository, criteriaNoCountDao, properties.getDatabase()); } @Bean @@ -509,11 +548,11 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { final DeploymentManagement deploymentManagement, final RolloutGroupManagement rolloutGroupManagement, final DistributionSetManagement distributionSetManagement, final ApplicationContext context, final ApplicationEventPublisher eventPublisher, final VirtualPropertyReplacer virtualPropertyReplacer, - final PlatformTransactionManager txManager, final TenantAware tenantAware, - final LockRegistry lockRegistry) { + final PlatformTransactionManager txManager, final TenantAware tenantAware, final LockRegistry lockRegistry, + final JpaProperties properties) { return new JpaRolloutManagement(targetManagement, deploymentManagement, rolloutGroupManagement, distributionSetManagement, context, eventPublisher, virtualPropertyReplacer, txManager, tenantAware, - lockRegistry); + lockRegistry, properties.getDatabase()); } /** @@ -523,8 +562,13 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { */ @Bean @ConditionalOnMissingBean - RolloutGroupManagement rolloutGroupManagement() { - return new JpaRolloutGroupManagement(); + RolloutGroupManagement rolloutGroupManagement(final RolloutGroupRepository rolloutGroupRepository, + final RolloutRepository rolloutRepository, final ActionRepository actionRepository, + final TargetRepository targetRepository, final EntityManager entityManager, + final VirtualPropertyReplacer virtualPropertyReplacer, final RolloutStatusCache rolloutStatusCache, + final JpaProperties properties) { + return new JpaRolloutGroupManagement(rolloutGroupRepository, rolloutRepository, actionRepository, + targetRepository, entityManager, virtualPropertyReplacer, rolloutStatusCache, properties.getDatabase()); } /** @@ -542,10 +586,11 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { final AfterTransactionCommitExecutor afterCommit, final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager, final TenantConfigurationManagement tenantConfigurationManagement, - final SystemSecurityContext systemSecurityContext) { + final SystemSecurityContext systemSecurityContext, final JpaProperties properties) { return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetRepository, targetRepository, actionStatusRepository, targetManagement, auditorProvider, eventPublisher, applicationContext, - afterCommit, virtualPropertyReplacer, txManager, tenantConfigurationManagement, systemSecurityContext); + afterCommit, virtualPropertyReplacer, txManager, tenantConfigurationManagement, systemSecurityContext, + properties.getDatabase()); } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java index 48189720b..b3486262a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java @@ -60,28 +60,28 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { @Override @Access(AccessType.PROPERTY) - @Column(name = "created_at", insertable = true, updatable = false) + @Column(name = "created_at", insertable = true, updatable = false, nullable = false) public long getCreatedAt() { return createdAt; } @Override @Access(AccessType.PROPERTY) - @Column(name = "created_by", insertable = true, updatable = false, length = 40) + @Column(name = "created_by", insertable = true, updatable = false, nullable = false, length = 40) public String getCreatedBy() { return createdBy; } @Override @Access(AccessType.PROPERTY) - @Column(name = "last_modified_at", insertable = true, updatable = true) + @Column(name = "last_modified_at", insertable = true, updatable = true, nullable = false) public long getLastModifiedAt() { return lastModifiedAt; } @Override @Access(AccessType.PROPERTY) - @Column(name = "last_modified_by", insertable = true, updatable = true, length = 40) + @Column(name = "last_modified_by", insertable = true, updatable = true, nullable = false, length = 40) public String getLastModifiedBy() { return lastModifiedBy; } @@ -90,6 +90,11 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { public void setCreatedBy(final String createdBy) { if (isController()) { this.createdBy = "CONTROLLER_PLUG_AND_PLAY"; + + // In general modification audit entry is not changed by the + // controller. However, we want to stay consistent with + // EnableJpaAuditing#modifyOnCreate=true. + this.lastModifiedBy = this.createdBy; return; } @@ -99,6 +104,13 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { @CreatedDate public void setCreatedAt(final long createdAt) { this.createdAt = createdAt; + + // In general modification audit entry is not changed by the controller. + // However, we want to stay consistent with + // EnableJpaAuditing#modifyOnCreate=true. + if (isController()) { + this.lastModifiedAt = createdAt; + } } @LastModifiedDate diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java index 8c080554c..74ee54059 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java @@ -24,6 +24,7 @@ import javax.persistence.Table; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.eclipse.persistence.annotations.CascadeOnDelete; /** * Relation element between a {@link DistributionSetType} and its @@ -41,11 +42,13 @@ public class DistributionSetTypeElement implements Serializable { @Column(name = "mandatory") private boolean mandatory; + @CascadeOnDelete @MapsId("dsType") @ManyToOne(optional = false, fetch = FetchType.LAZY) @JoinColumn(name = "distribution_set_type", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_element")) private JpaDistributionSetType dsType; + @CascadeOnDelete @MapsId("smType") @ManyToOne(optional = false, fetch = FetchType.LAZY) @JoinColumn(name = "software_module_type", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_smtype")) @@ -68,7 +71,6 @@ public class DistributionSetTypeElement implements Serializable { */ DistributionSetTypeElement(final JpaDistributionSetType dsType, final JpaSoftwareModuleType smType, final boolean mandatory) { - super(); key = new DistributionSetTypeElementCompositeKey(dsType, smType); this.dsType = dsType; this.smType = smType; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java index 9e8b46b93..62a502b51 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaActionStatus.java @@ -80,7 +80,7 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements @CascadeOnDelete @ElementCollection(fetch = FetchType.LAZY, targetClass = String.class) - @CollectionTable(name = "sp_action_status_messages", joinColumns = @JoinColumn(name = "action_status_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_stat_msg_act_stat")), indexes = { + @CollectionTable(name = "sp_action_status_messages", joinColumns = @JoinColumn(name = "action_status_id", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_stat_msg_act_stat"), updatable = false, nullable = false), indexes = { @Index(name = "sp_idx_action_status_msgs_01", columnList = "action_status_id") }) @Column(name = "detail_message", length = MESSAGE_ENTRY_LENGTH, nullable = false, updatable = false) private List messages; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java index cb7e4dd47..317e8d3ef 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaArtifact.java @@ -45,7 +45,7 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art @NotNull private String sha1Hash; - @Column(name = "provided_file_name", length = 256) + @Column(name = "provided_file_name", length = 256, updatable = false) @Size(min = 1, max = 256) @NotNull private String filename; @@ -54,17 +54,17 @@ public class JpaArtifact extends AbstractJpaTenantAwareBaseEntity implements Art @JoinColumn(name = "software_module", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_assigned_sm")) private JpaSoftwareModule softwareModule; - @Column(name = "md5_hash", length = 32, nullable = true) + @Column(name = "md5_hash", length = 32, updatable = false, nullable = true) private String md5Hash; - @Column(name = "file_size") + @Column(name = "file_size", updatable = false) private long size; /** - * Default constructor. + * Default constructor needed for JPA entities.. */ public JpaArtifact() { - super(); + // Default constructor needed for JPA entities. } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java index ae306a2d8..b1269f7d7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java @@ -68,7 +68,6 @@ public class JpaTenantMetaData extends AbstractJpaBaseEntity implements TenantMe * @param tenant */ public JpaTenantMetaData(final DistributionSetType defaultDsType, final String tenant) { - super(); this.defaultDsType = (JpaDistributionSetType) defaultDsType; this.tenant = tenant; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java index b1a6750ff..829fddbfd 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtility.java @@ -43,6 +43,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.SimpleTypeConverter; import org.springframework.beans.TypeMismatchException; import org.springframework.data.jpa.domain.Specification; +import org.springframework.orm.jpa.vendor.Database; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -114,16 +115,21 @@ public final class RSQLUtility { * @param virtualPropertyReplacer * holds the logic how the known macros have to be resolved; may * be null + * @param database + * in use + * * @return an specification which can be used with JPA * @throws RSQLParameterUnsupportedFieldException * if a field in the RSQL string is used but not provided by the * given {@code fieldNameProvider} * @throws RSQLParameterSyntaxException * if the RSQL syntax is wrong + * */ public static & FieldNameProvider, T> Specification parse(final String rsql, - final Class fieldNameProvider, final VirtualPropertyReplacer virtualPropertyReplacer) { - return new RSQLSpecification<>(rsql.toLowerCase(), fieldNameProvider, virtualPropertyReplacer); + final Class fieldNameProvider, final VirtualPropertyReplacer virtualPropertyReplacer, + final Database database) { + return new RSQLSpecification<>(rsql.toLowerCase(), fieldNameProvider, virtualPropertyReplacer, database); } /** @@ -155,12 +161,14 @@ public final class RSQLUtility { private final String rsql; private final Class enumType; private final VirtualPropertyReplacer virtualPropertyReplacer; + private final Database database; private RSQLSpecification(final String rsql, final Class enumType, - final VirtualPropertyReplacer virtualPropertyReplacer) { + final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) { this.rsql = rsql; this.enumType = enumType; this.virtualPropertyReplacer = virtualPropertyReplacer; + this.database = database; } @Override @@ -169,7 +177,7 @@ public final class RSQLUtility { query.distinct(true); final JpqQueryRSQLVisitor jpqQueryRSQLVisitor = new JpqQueryRSQLVisitor<>(root, cb, enumType, - virtualPropertyReplacer); + virtualPropertyReplacer, database); final List accept = rootNode., String> accept(jpqQueryRSQLVisitor); if (!CollectionUtils.isEmpty(accept)) { @@ -194,6 +202,8 @@ public final class RSQLUtility { */ private static final class JpqQueryRSQLVisitor & FieldNameProvider, T> implements RSQLVisitor, String> { + private static final char ESCAPE_CHAR = '\\'; + public static final Character LIKE_WILDCARD = '*'; private final Root root; @@ -206,13 +216,16 @@ public final class RSQLUtility { private final SimpleTypeConverter simpleTypeConverter; + final Database database; + private JpqQueryRSQLVisitor(final Root root, final CriteriaBuilder cb, final Class enumType, - final VirtualPropertyReplacer virtualPropertyReplacer) { + final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) { this.root = root; this.cb = cb; this.enumType = enumType; this.virtualPropertyReplacer = virtualPropertyReplacer; simpleTypeConverter = new SimpleTypeConverter(); + this.database = database; } private void beginLevel(final boolean isOr) { @@ -402,7 +415,7 @@ public final class RSQLUtility { transformedValue.add(convertValueIfNecessary(node, fieldName, value, fieldPath)); } - return mapToPredicate(node, fieldPath, node.getArguments(), transformedValue, fieldName); + return mapToPredicate(node, fieldPath, node.getArguments(), transformedValue, fieldName, database); } // Exception squid:S2095 - see @@ -514,7 +527,8 @@ public final class RSQLUtility { } private List mapToPredicate(final ComparisonNode node, final Path fieldPath, - final List values, final List transformedValues, final A enumField) { + final List values, final List transformedValues, final A enumField, + final Database database) { // only 'equal' and 'notEqual' can handle transformed value like // enums. The JPA API cannot handle object types for greaterThan etc // methods. @@ -534,19 +548,19 @@ public final class RSQLUtility { } addOperatorPredicate(node, getMapValueFieldPath(enumField, fieldPath), transformedValues, transformedValue, - value, singleList); + value, singleList, database); return Collections.unmodifiableList(singleList); } private void addOperatorPredicate(final ComparisonNode node, final Path fieldPath, final List transformedValues, final Object transformedValue, final String value, - final List singleList) { + final List singleList, final Database database) { switch (node.getOperator().getSymbol()) { case "==": - singleList.add(getEqualToPredicate(transformedValue, fieldPath)); + singleList.add(getEqualToPredicate(transformedValue, fieldPath, database)); break; case "!=": - singleList.add(getNotEqualToPredicate(transformedValue, fieldPath)); + singleList.add(getNotEqualToPredicate(transformedValue, fieldPath, database)); break; case "=gt=": singleList.add(cb.greaterThan(pathOfString(fieldPath), value)); @@ -625,14 +639,15 @@ public final class RSQLUtility { return cb.equal(cb.upper(fieldPath.get(enumField.getKeyFieldName())), keyValue.toUpperCase()); } - private Predicate getEqualToPredicate(final Object transformedValue, final Path fieldPath) { + private Predicate getEqualToPredicate(final Object transformedValue, final Path fieldPath, + final Database database) { if (transformedValue instanceof String) { if (StringUtils.isEmpty(transformedValue)) { return cb.or(cb.isNull(pathOfString(fieldPath)), cb.equal(pathOfString(fieldPath), "")); } - final String preFormattedValue = escapeValueToSQL((String) transformedValue); - return cb.like(cb.upper(pathOfString(fieldPath)), preFormattedValue.toUpperCase()); + final String preFormattedValue = escapeValueToSQL((String) transformedValue, database, ESCAPE_CHAR); + return cb.like(cb.upper(pathOfString(fieldPath)), preFormattedValue.toUpperCase(), ESCAPE_CHAR); } if (transformedValue == null) { @@ -642,14 +657,15 @@ public final class RSQLUtility { return cb.equal(fieldPath, transformedValue); } - private Predicate getNotEqualToPredicate(final Object transformedValue, final Path fieldPath) { + private Predicate getNotEqualToPredicate(final Object transformedValue, final Path fieldPath, + final Database database) { if (transformedValue instanceof String) { if (StringUtils.isEmpty(transformedValue)) { return cb.and(cb.isNotNull(pathOfString(fieldPath)), cb.notEqual(pathOfString(fieldPath), "")); } - final String preFormattedValue = escapeValueToSQL((String) transformedValue); - return cb.notLike(cb.upper(pathOfString(fieldPath)), preFormattedValue.toUpperCase()); + final String preFormattedValue = escapeValueToSQL((String) transformedValue, database, ESCAPE_CHAR); + return cb.notLike(cb.upper(pathOfString(fieldPath)), preFormattedValue.toUpperCase(), ESCAPE_CHAR); } if (transformedValue == null) { @@ -659,8 +675,20 @@ public final class RSQLUtility { return cb.notEqual(fieldPath, transformedValue); } - private static String escapeValueToSQL(final String transformedValue) { - return transformedValue.replace("%", "\\%").replace(LIKE_WILDCARD, '%'); + private static String escapeValueToSQL(final String transformedValue, final Database database, + final char escapeChar) { + final String escaped; + + switch (database) { + case SQL_SERVER: + escaped = transformedValue.replace("%", "[%]").replace("_", "[_]"); + break; + default: + escaped = transformedValue.replace("%", escapeChar + "%").replace("_", escapeChar + "_"); + break; + } + + return escaped.replace(LIKE_WILDCARD, '%'); } @SuppressWarnings("unchecked") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_5__baseline___DB2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_5__baseline___DB2.sql new file mode 100644 index 000000000..2bf33f7c0 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/DB2/V1_12_5__baseline___DB2.sql @@ -0,0 +1,462 @@ +CREATE TABLE sp_ds_type_element + ( + mandatory SMALLINT DEFAULT 0, + distribution_set_type BIGINT NOT NULL, + software_module_type BIGINT NOT NULL, + PRIMARY KEY (distribution_set_type, software_module_type) + ); + +CREATE TABLE sp_action + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + action_type INTEGER NOT NULL, + active SMALLINT DEFAULT 0, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + forced_time BIGINT, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER, + status INTEGER NOT NULL, + distribution_set BIGINT NOT NULL, + rollout BIGINT, + rolloutgroup BIGINT, + target BIGINT NOT NULL, + maintenance_cron_schedule VARCHAR(40), + maintenance_duration VARCHAR(40), + maintenance_time_zone VARCHAR(40), + PRIMARY KEY (id) + ); + + ALTER TABLE sp_action ADD column maintenance_cron_schedule VARCHAR(40); +ALTER TABLE sp_action ADD column maintenance_duration VARCHAR(40); +ALTER TABLE sp_action ADD column maintenance_time_zone VARCHAR(40); + +CREATE INDEX sp_idx_action_01 + ON sp_action (tenant, distribution_set); + +CREATE INDEX sp_idx_action_02 + ON sp_action (tenant, target, active); + +CREATE INDEX sp_idx_action_prim + ON sp_action (tenant, id); + +CREATE TABLE sp_action_status + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + target_occurred_at BIGINT NOT NULL, + optlock_revision INTEGER, + status INTEGER NOT NULL, + action BIGINT NOT NULL, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_action_status_02 + ON sp_action_status (tenant, action, status); + +CREATE INDEX sp_idx_action_status_prim + ON sp_action_status (tenant, id); + +CREATE TABLE sp_artifact + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + provided_file_name VARCHAR(256), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + md5_hash VARCHAR(32), + optlock_revision INTEGER, + sha1_hash VARCHAR(40) NOT NULL, + file_size BIGINT, + software_module BIGINT NOT NULL, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_artifact_01 + ON sp_artifact (tenant, software_module); + +CREATE INDEX sp_idx_artifact_02 + ON sp_artifact (tenant, sha1_hash); + +CREATE INDEX sp_idx_artifact_prim + ON sp_artifact (tenant, id); + +CREATE TABLE sp_distribution_set + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + complete SMALLINT DEFAULT 0, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + required_migration_step SMALLINT DEFAULT 0, + VERSION VARCHAR(64) NOT NULL, + ds_id BIGINT NOT NULL, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_distribution_set_01 + ON sp_distribution_set (tenant, deleted, complete); + +CREATE INDEX sp_idx_distribution_set_prim + ON sp_distribution_set (tenant, id); + +CREATE TABLE sp_ds_metadata + ( + meta_key VARCHAR(128) NOT NULL, + meta_value VARCHAR(4000), + ds_id BIGINT NOT NULL, + PRIMARY KEY (meta_key, ds_id) + ); + +CREATE TABLE sp_distributionset_tag + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16), + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_distribution_set_tag_prim + ON sp_distributionset_tag (tenant, id); + +CREATE TABLE sp_distribution_set_type + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16), + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + type_key VARCHAR(64) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_distribution_set_type_01 + ON sp_distribution_set_type (tenant, deleted); + +CREATE INDEX sp_idx_distribution_set_type_prim + ON sp_distribution_set_type (tenant, id); + +CREATE TABLE sp_rollout + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + action_type INTEGER NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + forced_time BIGINT, + last_check BIGINT, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + rollout_groups_created INTEGER, + start_at BIGINT, + status INTEGER NOT NULL, + target_filter VARCHAR(1024) NOT NULL, + total_targets BIGINT, + distribution_set BIGINT NOT NULL, + PRIMARY KEY (id) + ); + +CREATE TABLE sp_rolloutgroup + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512), + error_action INTEGER, + error_action_exp VARCHAR(512), + error_condition INTEGER, + error_condition_exp VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + status INTEGER NOT NULL, + success_action INTEGER NOT NULL, + success_action_exp VARCHAR(512), + success_condition INTEGER NOT NULL, + success_condition_exp VARCHAR(512) NOT NULL, + target_filter VARCHAR(1024), + target_percentage FLOAT, + total_targets INTEGER, + parent_id BIGINT, + rollout BIGINT NOT NULL, + PRIMARY KEY (id) + ); + +CREATE TABLE sp_base_software_module + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + vendor VARCHAR(256), + VERSION VARCHAR(64) NOT NULL, + module_type BIGINT NOT NULL, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_base_sw_module_01 + ON sp_base_software_module (tenant, deleted, name, VERSION); + +CREATE INDEX sp_idx_base_sw_module_02 + ON sp_base_software_module (tenant, deleted, module_type); + +CREATE INDEX sp_idx_base_sw_module_prim + ON sp_base_software_module (tenant, id); + +CREATE TABLE sp_sw_metadata + ( + meta_key VARCHAR(128) NOT NULL, + target_visible SMALLINT DEFAULT 0, + meta_value VARCHAR(4000), + sw_id BIGINT NOT NULL, + PRIMARY KEY (meta_key, sw_id) + ); + +CREATE TABLE sp_software_module_type + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16), + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted SMALLINT DEFAULT 0, + description VARCHAR(512), + type_key VARCHAR(64) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + max_ds_assignments INTEGER NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_software_module_type_01 + ON sp_software_module_type (tenant, deleted); + +CREATE INDEX sp_idx_software_module_type_prim + ON sp_software_module_type (tenant, id); + +CREATE TABLE sp_target + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + address VARCHAR(512), + controller_id VARCHAR(64) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512), + install_date BIGINT, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + last_target_query BIGINT, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + request_controller_attributes SMALLINT DEFAULT 0 NOT NULL, + sec_token VARCHAR(128) NOT NULL, + update_status INTEGER NOT NULL, + assigned_distribution_set BIGINT, + installed_distribution_set BIGINT, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_target_01 + ON sp_target (tenant, name, assigned_distribution_set); + +CREATE INDEX sp_idx_target_03 + ON sp_target (tenant, controller_id, assigned_distribution_set); + +CREATE INDEX sp_idx_target_04 + ON sp_target (tenant, created_at); + +CREATE INDEX sp_idx_target_prim + ON sp_target (tenant, id); + +CREATE TABLE sp_target_filter_query + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + QUERY VARCHAR(1024) NOT NULL, + auto_assign_distribution_set BIGINT, + PRIMARY KEY (id) + ); + +CREATE TABLE sp_target_tag + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16), + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512), + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_target_tag_prim + ON sp_target_tag (tenant, id); + +CREATE TABLE sp_tenant_configuration + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + conf_key VARCHAR(128) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER, + conf_value VARCHAR(512) NOT NULL, + PRIMARY KEY (id) + ); + +CREATE TABLE sp_tenant + ( + id BIGINT GENERATED always AS IDENTITY NOT NULL, + created_at BIGINT NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at BIGINT NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER, + tenant VARCHAR(40) NOT NULL, + default_ds_type BIGINT NOT NULL, + PRIMARY KEY (id) + ); + +CREATE INDEX sp_idx_tenant_prim + ON sp_tenant (tenant, id); + +CREATE TABLE sp_rollouttargetgroup + ( + rolloutgroup_id BIGINT NOT NULL, + target_id BIGINT NOT NULL, + PRIMARY KEY (rolloutgroup_id, target_id) + ); + +CREATE TABLE sp_action_status_messages + ( + action_status_id BIGINT NOT NULL, + detail_message VARCHAR(512) NOT NULL + ); + +CREATE INDEX sp_idx_action_status_msgs_01 + ON sp_action_status_messages (action_status_id); + +CREATE TABLE sp_ds_module + ( + ds_id BIGINT NOT NULL, + module_id BIGINT NOT NULL, + PRIMARY KEY (ds_id, module_id) + ); + +CREATE TABLE sp_ds_dstag + ( + ds BIGINT NOT NULL, + tag BIGINT NOT NULL, + PRIMARY KEY (ds, tag) + ); + +CREATE TABLE sp_target_attributes + ( + target_id BIGINT NOT NULL, + attribute_value VARCHAR(128), + attribute_key VARCHAR(32) NOT NULL + ); + +CREATE TABLE sp_target_target_tag + ( + target BIGINT NOT NULL, + tag BIGINT NOT NULL, + PRIMARY KEY (target, tag) + ); + +ALTER TABLE sp_distribution_set ADD CONSTRAINT uk_distrib_set UNIQUE (name, version, tenant); +ALTER TABLE sp_distributionset_tag ADD CONSTRAINT uk_ds_tag UNIQUE (name, tenant); +ALTER TABLE sp_distribution_set_type ADD CONSTRAINT uk_dst_name UNIQUE (name, tenant); +ALTER TABLE sp_distribution_set_type ADD CONSTRAINT uk_dst_key UNIQUE (type_key, tenant); +ALTER TABLE sp_rollout ADD CONSTRAINT uk_rollout UNIQUE (name, tenant); +ALTER TABLE sp_rolloutgroup ADD CONSTRAINT uk_rolloutgroup UNIQUE (name, rollout, tenant); +ALTER TABLE sp_base_software_module ADD CONSTRAINT uk_base_sw_mod UNIQUE (module_type, name, version, tenant); +ALTER TABLE sp_software_module_type ADD CONSTRAINT uk_smt_type_key UNIQUE (type_key, tenant); +ALTER TABLE sp_software_module_type ADD CONSTRAINT uk_smt_name UNIQUE (name, tenant); +ALTER TABLE sp_target ADD CONSTRAINT uk_tenant_controller_ UNIQUE (controller_id, tenant); +ALTER TABLE sp_target_filter_query ADD CONSTRAINT uk_tenant_custom_filt UNIQUE (name, tenant); +ALTER TABLE sp_target_tag ADD CONSTRAINT uk_targ_tag UNIQUE (name, tenant); +ALTER TABLE sp_tenant_configuration ADD CONSTRAINT uk_tenant_key UNIQUE (conf_key, tenant); +ALTER TABLE sp_tenant ADD CONSTRAINT uk_tenantmd_tenant UNIQUE (tenant); + +ALTER TABLE sp_ds_type_element ADD CONSTRAINT fk_ds_type_element_element FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_type_element ADD CONSTRAINT fk_ds_type_element_smtype FOREIGN KEY (software_module_type) REFERENCES sp_software_module_type (id) ON DELETE CASCADE; +ALTER TABLE sp_action ADD CONSTRAINT fk_action_rolloutgroup FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); +ALTER TABLE sp_action ADD CONSTRAINT fk_action_rollout FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); +ALTER TABLE sp_action ADD CONSTRAINT fk_targ_act_hist_targ FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_action ADD CONSTRAINT fk_action_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_action_status ADD CONSTRAINT fk_act_stat_action FOREIGN KEY (action) REFERENCES sp_action (id) ON DELETE CASCADE; +ALTER TABLE sp_artifact ADD CONSTRAINT fk_assigned_sm FOREIGN KEY (software_module) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_distribution_set ADD CONSTRAINT fk_ds_dstype_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set_type (id); +ALTER TABLE sp_ds_metadata ADD CONSTRAINT fk_metadata_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_rollout ADD CONSTRAINT fk_rollout_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_rolloutgroup ADD CONSTRAINT fk_rolloutgroup_rollout FOREIGN KEY (rollout) REFERENCES sp_rollout (id) ON DELETE CASCADE; +ALTER TABLE sp_base_software_module ADD CONSTRAINT fk_module_type FOREIGN KEY (module_type) REFERENCES sp_software_module_type (id); +ALTER TABLE sp_sw_metadata ADD CONSTRAINT fk_metadata_sw FOREIGN KEY (sw_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_target ADD CONSTRAINT fk_target_inst_ds FOREIGN KEY (installed_distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target ADD CONSTRAINT fk_target_assign_ds FOREIGN KEY (assigned_distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target_filter_query ADD CONSTRAINT fk_filter_auto_assign_ds FOREIGN KEY (auto_assign_distribution_set) REFERENCES sp_distribution_set (id) ON DELETE SET NULL; +ALTER TABLE sp_tenant ADD CONSTRAINT fk_tenant_md_default_ds_type FOREIGN KEY (default_ds_type) REFERENCES sp_distribution_set_type (id); +ALTER TABLE sp_rollouttargetgroup ADD CONSTRAINT fk_rollouttargetgroup_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_rollouttargetgroup ADD CONSTRAINT fk_rollouttargetgroup_group FOREIGN KEY (rolloutGroup_Id) REFERENCES sp_rolloutgroup (id) ON DELETE CASCADE; +ALTER TABLE sp_action_status_messages ADD CONSTRAINT fk_stat_msg_act_stat FOREIGN KEY (action_status_id) REFERENCES sp_action_status (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_module ADD CONSTRAINT fk_ds_module_module FOREIGN KEY (module_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_module ADD CONSTRAINT fk_ds_module_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_dstag ADD CONSTRAINT fk_ds_dstag_tag FOREIGN KEY (tag) REFERENCES sp_distributionset_tag (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_dstag ADD CONSTRAINT fk_ds_dstag_ds FOREIGN KEY (ds) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_target_attributes ADD CONSTRAINT fk_targ_attrib_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_target_target_tag ADD CONSTRAINT fk_targ_targtag_tag FOREIGN KEY (tag) REFERENCES sp_target_tag (id) ON DELETE CASCADE; +ALTER TABLE sp_target_target_tag ADD CONSTRAINT fk_targ_targtag_target FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_5__baseline___SQL_SERVER.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_5__baseline___SQL_SERVER.sql new file mode 100644 index 000000000..42a3895b4 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/SQL_SERVER/V1_12_5__baseline___SQL_SERVER.sql @@ -0,0 +1,383 @@ +CREATE TABLE sp_ds_type_element +( + mandatory BIT default 0 NULL, + distribution_set_type NUMERIC(19) NOT NULL, + software_module_type NUMERIC(19) NOT NULL, + PRIMARY KEY (distribution_set_type, software_module_type) +); +CREATE TABLE sp_action +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + action_type INTEGER NOT NULL, + active BIT default 0 NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + forced_time NUMERIC(19) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER NULL, + status INTEGER NOT NULL, + distribution_set NUMERIC(19) NOT NULL, + rollout NUMERIC(19) NULL, + rolloutgroup NUMERIC(19) NULL, + target NUMERIC(19) NOT NULL, + maintenance_cron_schedule VARCHAR(40), + maintenance_duration VARCHAR(40), + maintenance_time_zone VARCHAR(40), + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_action_01 ON sp_action (tenant, distribution_set); +CREATE INDEX sp_idx_action_02 ON sp_action (tenant, target, active); +CREATE INDEX sp_idx_action_prim ON sp_action (tenant, id); +CREATE TABLE sp_action_status +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + target_occurred_at NUMERIC(19) NOT NULL, + optlock_revision INTEGER NULL, + status INTEGER NOT NULL, + action NUMERIC(19) NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_action_status_02 ON sp_action_status (tenant, action, status); +CREATE INDEX sp_idx_action_status_prim ON sp_action_status (tenant, id); +CREATE TABLE sp_artifact +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + provided_file_name VARCHAR(256) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + md5_hash VARCHAR(32) NULL, + optlock_revision INTEGER NULL, + sha1_hash VARCHAR(40) NOT NULL, + file_size NUMERIC(19) NULL, + software_module NUMERIC(19) NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_artifact_01 ON sp_artifact (tenant, software_module); +CREATE INDEX sp_idx_artifact_02 ON sp_artifact (tenant, sha1_hash); +CREATE INDEX sp_idx_artifact_prim ON sp_artifact (tenant, id); +CREATE TABLE sp_distribution_set +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + complete BIT default 0 NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + required_migration_step BIT default 0 NULL, + version VARCHAR(64) NOT NULL, + ds_id NUMERIC(19) NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_distribution_set_01 ON sp_distribution_set (tenant, deleted, complete); +CREATE INDEX sp_idx_distribution_set_prim ON sp_distribution_set (tenant, id); +CREATE TABLE sp_ds_metadata +( + meta_key VARCHAR(128) NOT NULL, + meta_value VARCHAR(4000) NULL, + ds_id NUMERIC(19) NOT NULL, + PRIMARY KEY (meta_key, ds_id) +); +CREATE TABLE sp_distributionset_tag +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16) NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_distribution_set_tag_prim ON sp_distributionset_tag (tenant, id); +CREATE TABLE sp_distribution_set_type +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16) NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, + type_key VARCHAR(64) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_distribution_set_type_01 ON sp_distribution_set_type (tenant, deleted); +CREATE INDEX sp_idx_distribution_set_type_prim ON sp_distribution_set_type (tenant, id); +CREATE TABLE sp_rollout +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + action_type INTEGER NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, + forced_time NUMERIC(19) NULL, + last_check NUMERIC(19) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + rollout_groups_created INTEGER NULL, + start_at NUMERIC(19) NULL, + status INTEGER NOT NULL, + target_filter VARCHAR(1024) NOT NULL, + total_targets NUMERIC(19) NULL, + distribution_set NUMERIC(19) NOT NULL, + PRIMARY KEY (id) +); +CREATE TABLE sp_rolloutgroup +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512) NULL, + error_action INTEGER NULL, + error_action_exp VARCHAR(512) NULL, + error_condition INTEGER NULL, + error_condition_exp VARCHAR(512) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + status INTEGER NOT NULL, + success_action INTEGER NOT NULL, + success_action_exp VARCHAR(512) NULL, + success_condition INTEGER NOT NULL, + success_condition_exp VARCHAR(512) NOT NULL, + target_filter VARCHAR(1024) NULL, + target_percentage FLOAT(16) NULL, + total_targets INTEGER NULL, + parent_id NUMERIC(19) NULL, + rollout NUMERIC(19) NOT NULL, + PRIMARY KEY (id) +); +CREATE TABLE sp_base_software_module +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + vendor VARCHAR(256) NULL, + version VARCHAR(64) NOT NULL, + module_type NUMERIC(19) NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_base_sw_module_01 ON sp_base_software_module (tenant, deleted, name, version); +CREATE INDEX sp_idx_base_sw_module_02 ON sp_base_software_module (tenant, deleted, module_type); +CREATE INDEX sp_idx_base_sw_module_prim ON sp_base_software_module (tenant, id); +CREATE TABLE sp_sw_metadata +( + meta_key VARCHAR(128) NOT NULL, + target_visible BIT default 0 NULL, + meta_value VARCHAR(4000) NULL, + sw_id NUMERIC(19) NOT NULL, + PRIMARY KEY (meta_key, sw_id) +); +CREATE TABLE sp_software_module_type +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16) NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + deleted BIT default 0 NULL, + description VARCHAR(512) NULL, + type_key VARCHAR(64) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + max_ds_assignments INTEGER NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_software_module_type_01 ON sp_software_module_type (tenant, deleted); +CREATE INDEX sp_idx_software_module_type_prim ON sp_software_module_type (tenant, id); +CREATE TABLE sp_target +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + address VARCHAR(512) NULL, + controller_id VARCHAR(64) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512) NULL, + install_date NUMERIC(19) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + last_target_query NUMERIC(19) NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + request_controller_attributes BIT default 0 NOT NULL, + sec_token VARCHAR(128) NOT NULL, + update_status INTEGER NOT NULL, + assigned_distribution_set NUMERIC(19) NULL, + installed_distribution_set NUMERIC(19) NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_target_01 ON sp_target (tenant, name, assigned_distribution_set); +CREATE INDEX sp_idx_target_03 ON sp_target (tenant, controller_id, assigned_distribution_set); +CREATE INDEX sp_idx_target_04 ON sp_target (tenant, created_at); +CREATE INDEX sp_idx_target_prim ON sp_target (tenant, id); +CREATE TABLE sp_target_filter_query +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + query VARCHAR(1024) NOT NULL, + auto_assign_distribution_set NUMERIC(19) NULL, + PRIMARY KEY (id) +); +CREATE TABLE sp_target_tag +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + colour VARCHAR(16) NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + description VARCHAR(512) NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + name VARCHAR(64) NOT NULL, + optlock_revision INTEGER NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_target_tag_prim ON sp_target_tag (tenant, id); +CREATE TABLE sp_tenant_configuration +( + id NUMERIC(19) IDENTITY NOT NULL, + tenant VARCHAR(40) NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + conf_key VARCHAR(128) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER NULL, + conf_value VARCHAR(512) NOT NULL, + PRIMARY KEY (id) +); +CREATE TABLE sp_tenant +( + id NUMERIC(19) IDENTITY NOT NULL, + created_at NUMERIC(19) NOT NULL, + created_by VARCHAR(40) NOT NULL, + last_modified_at NUMERIC(19) NOT NULL, + last_modified_by VARCHAR(40) NOT NULL, + optlock_revision INTEGER NULL, + tenant VARCHAR(40) NOT NULL, + default_ds_type NUMERIC(19) NOT NULL, + PRIMARY KEY (id) +); +CREATE INDEX sp_idx_tenant_prim ON sp_tenant (tenant, id); +CREATE TABLE sp_rollouttargetgroup +( + rolloutGroup_Id NUMERIC(19) NOT NULL, + target_id NUMERIC(19) NOT NULL, + PRIMARY KEY (rolloutGroup_Id, target_id) +); +CREATE TABLE sp_action_status_messages +( + action_status_id NUMERIC(19) NOT NULL, + detail_message VARCHAR(512) NOT NULL +); +CREATE INDEX sp_idx_action_status_msgs_01 ON sp_action_status_messages (action_status_id); +CREATE TABLE sp_ds_module +( + ds_id NUMERIC(19) NOT NULL, + module_id NUMERIC(19) NOT NULL, + PRIMARY KEY (ds_id, module_id) +); +CREATE TABLE sp_ds_dstag +( + ds NUMERIC(19) NOT NULL, + TAG NUMERIC(19) NOT NULL, + PRIMARY KEY (ds, TAG) +); +CREATE TABLE sp_target_attributes +( + target_id NUMERIC(19) NOT NULL, + attribute_value VARCHAR(128) NULL, + attribute_key VARCHAR(32) NOT NULL +); +CREATE TABLE sp_target_target_tag +( + target NUMERIC(19) NOT NULL, + tag NUMERIC(19) NOT NULL, + PRIMARY KEY (target, tag) +); +ALTER TABLE sp_distribution_set ADD CONSTRAINT uk_distrib_set UNIQUE (name, version, tenant); +ALTER TABLE sp_distributionset_tag ADD CONSTRAINT uk_ds_tag UNIQUE (name, tenant); +ALTER TABLE sp_distribution_set_type ADD CONSTRAINT uk_dst_name UNIQUE (name, tenant); +ALTER TABLE sp_distribution_set_type ADD CONSTRAINT uk_dst_key UNIQUE (type_key, tenant); +ALTER TABLE sp_rollout ADD CONSTRAINT uk_rollout UNIQUE (name, tenant); +ALTER TABLE sp_rolloutgroup ADD CONSTRAINT uk_rolloutgroup UNIQUE (name, rollout, tenant); +ALTER TABLE sp_base_software_module ADD CONSTRAINT uk_base_sw_mod UNIQUE (module_type, name, version, tenant); +ALTER TABLE sp_software_module_type ADD CONSTRAINT uk_smt_type_key UNIQUE (type_key, tenant); +ALTER TABLE sp_software_module_type ADD CONSTRAINT uk_smt_name UNIQUE (name, tenant); +ALTER TABLE sp_target ADD CONSTRAINT uk_tenant_controller_ UNIQUE (controller_id, tenant); +ALTER TABLE sp_target_filter_query ADD CONSTRAINT uk_tenant_custom_filt UNIQUE (name, tenant); +ALTER TABLE sp_target_tag ADD CONSTRAINT uk_targ_tag UNIQUE (name, tenant); +ALTER TABLE sp_tenant_configuration ADD CONSTRAINT uk_tenant_key UNIQUE (conf_key, tenant); +ALTER TABLE sp_tenant ADD CONSTRAINT uk_tenantmd_tenant UNIQUE (tenant); +ALTER TABLE sp_ds_type_element ADD CONSTRAINT fk_ds_type_element_element FOREIGN KEY (distribution_set_type) REFERENCES sp_distribution_set_type (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_type_element ADD CONSTRAINT fk_ds_type_element_smtype FOREIGN KEY (software_module_type) REFERENCES sp_software_module_type (id) ON DELETE CASCADE; +ALTER TABLE sp_action ADD CONSTRAINT fk_action_rolloutgroup FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); +ALTER TABLE sp_action ADD CONSTRAINT fk_action_rollout FOREIGN KEY (rolloutgroup) REFERENCES sp_rolloutgroup (id); +ALTER TABLE sp_action ADD CONSTRAINT fk_targ_act_hist_targ FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_action ADD CONSTRAINT fk_action_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_action_status ADD CONSTRAINT fk_act_stat_action FOREIGN KEY (action) REFERENCES sp_action (id) ON DELETE CASCADE; +ALTER TABLE sp_artifact ADD CONSTRAINT fk_assigned_sm FOREIGN KEY (software_module) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_distribution_set ADD CONSTRAINT fk_ds_dstype_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set_type (id); +ALTER TABLE sp_ds_metadata ADD CONSTRAINT fk_metadata_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_rollout ADD CONSTRAINT fk_rollout_ds FOREIGN KEY (distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_rolloutgroup ADD CONSTRAINT fk_rolloutgroup_rollout FOREIGN KEY (rollout) REFERENCES sp_rollout (id) ON DELETE CASCADE; +ALTER TABLE sp_base_software_module ADD CONSTRAINT fk_module_type FOREIGN KEY (module_type) REFERENCES sp_software_module_type (id); +ALTER TABLE sp_sw_metadata ADD CONSTRAINT fk_metadata_sw FOREIGN KEY (sw_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_target ADD CONSTRAINT fk_target_inst_ds FOREIGN KEY (installed_distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target ADD CONSTRAINT fk_target_assign_ds FOREIGN KEY (assigned_distribution_set) REFERENCES sp_distribution_set (id); +ALTER TABLE sp_target_filter_query ADD CONSTRAINT fk_filter_auto_assign_ds FOREIGN KEY (auto_assign_distribution_set) REFERENCES sp_distribution_set (id) ON DELETE SET NULL; +ALTER TABLE sp_tenant ADD CONSTRAINT fk_tenant_md_default_ds_type FOREIGN KEY (default_ds_type) REFERENCES sp_distribution_set_type (id); +ALTER TABLE sp_rollouttargetgroup ADD CONSTRAINT fk_rollouttargetgroup_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_rollouttargetgroup ADD CONSTRAINT fk_rollouttargetgroup_group FOREIGN KEY (rolloutGroup_Id) REFERENCES sp_rolloutgroup (id) ON DELETE CASCADE; +ALTER TABLE sp_action_status_messages ADD CONSTRAINT fk_stat_msg_act_stat FOREIGN KEY (action_status_id) REFERENCES sp_action_status (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_module ADD CONSTRAINT fk_ds_module_module FOREIGN KEY (module_id) REFERENCES sp_base_software_module (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_module ADD CONSTRAINT fk_ds_module_ds FOREIGN KEY (ds_id) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_dstag ADD CONSTRAINT fk_ds_dstag_tag FOREIGN KEY (tag) REFERENCES sp_distributionset_tag (id) ON DELETE CASCADE; +ALTER TABLE sp_ds_dstag ADD CONSTRAINT fk_ds_dstag_ds FOREIGN KEY (ds) REFERENCES sp_distribution_set (id) ON DELETE CASCADE; +ALTER TABLE sp_target_attributes ADD CONSTRAINT fk_targ_attrib_target FOREIGN KEY (target_id) REFERENCES sp_target (id) ON DELETE CASCADE; +ALTER TABLE sp_target_target_tag ADD CONSTRAINT fk_targ_targtag_tag FOREIGN KEY (tag) REFERENCES sp_target_tag (id) ON DELETE CASCADE; +ALTER TABLE sp_target_target_tag ADD CONSTRAINT fk_targ_targtag_target FOREIGN KEY (target) REFERENCES sp_target (id) ON DELETE CASCADE; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java index a46d2ca96..0998424f5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java @@ -230,7 +230,7 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest { assertThatExceptionOfType(EntityNotFoundException.class) .isThrownBy(() -> distributionSetManagement.assignTag(assignDS, tag.getId())) - .withMessageContaining("DistributionSet").withMessageContaining(String.valueOf(tag.getId())); + .withMessageContaining("DistributionSet").withMessageContaining(String.valueOf(100L)); } @Test @@ -469,7 +469,7 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest { @Expect(type = DistributionSetCreatedEvent.class, count = 2), @Expect(type = SoftwareModuleCreatedEvent.class, count = 6), @Expect(type = TargetAssignDistributionSetEvent.class, count = 2) }) - public void assigneDistributionSetAndAutoCloseActiveActions() { + public void assignDistributionSetAndAutoCloseActiveActions() { tenantConfigurationManagement .addOrUpdateConfiguration(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, true); @@ -481,8 +481,9 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest { assignDistributionSet(ds1, targets); List assignmentOne = actionRepository.findByDistributionSetId(PAGE, ds1.getId()).getContent(); - assertThat(assignmentOne).hasSize(10).as("Is active").allMatch(Action::isActive).as("Is assigned DS") - .allMatch(action -> action.getDistributionSet().getId() == ds1.getId()).as("Is running") + assertThat(assignmentOne).hasSize(10).as("Is active").allMatch(Action::isActive) + .as("Is assigned to DS " + ds1.getId()) + .allMatch(action -> action.getDistributionSet().getId().equals(ds1.getId())).as("Is running") .allMatch(action -> action.getStatus() == Status.RUNNING); // Second assignment @@ -491,12 +492,14 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest { final List assignmentTwo = actionRepository.findByDistributionSetId(PAGE, ds2.getId()).getContent(); assignmentOne = actionRepository.findByDistributionSetId(PAGE, ds1.getId()).getContent(); - assertThat(assignmentTwo).hasSize(10).as("Is active").allMatch(Action::isActive).as("Is assigned DS") - .allMatch(action -> action.getDistributionSet().getId() == ds2.getId()).as("Is running") + assertThat(assignmentTwo).hasSize(10).as("Is active").allMatch(Action::isActive) + .as("Is assigned to DS " + ds2.getId()) + .allMatch(action -> action.getDistributionSet().getId().equals(ds2.getId())).as("Is running") .allMatch(action -> action.getStatus() == Status.RUNNING); assertThat(assignmentOne).hasSize(10).as("Is active").allMatch(action -> !action.isActive()) - .as("Is assigned to DS").allMatch(action -> action.getDistributionSet().getId() == ds1.getId()) - .as("Is cancelled").allMatch(action -> action.getStatus() == Status.CANCELED); + .as("Is assigned to DS " + ds1.getId()) + .allMatch(action -> action.getDistributionSet().getId().equals(ds1.getId())).as("Is cancelled") + .allMatch(action -> action.getStatus() == Status.CANCELED); assertThat(targetManagement.findByAssignedDistributionSet(PAGE, ds2.getId()).getContent()).hasSize(10) .as("InstallationDate not set").allMatch(target -> (target.getInstallationDate() == null)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RandomGeneratedInputStream.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RandomGeneratedInputStream.java index a7a1c0956..1ddcdc056 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RandomGeneratedInputStream.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RandomGeneratedInputStream.java @@ -33,8 +33,6 @@ public class RandomGeneratedInputStream extends InputStream { * target size of the stream [byte] */ public RandomGeneratedInputStream(final long size) { - super(); - this.size = size; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java index 754608eab..0425fcbbe 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java @@ -164,8 +164,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(pending, null, null, installedSet.getId(), Boolean.FALSE, new String[0])) - .getContent()).as("has number of elements").hasSize(1) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(1).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, installedSet.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsExactly(expected) @@ -197,8 +197,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(pending, null, null, null, Boolean.FALSE, targTagW.getName())) - .getContent()).as("has number of elements").hasSize(2) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(2).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, null, Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsAll(expected) @@ -215,8 +215,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE, targTagW.getName())) - .getContent()).as("has number of elements").hasSize(2) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(2).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, setA.getId(), Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsAll(expected) @@ -233,8 +233,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE, targTagW.getName())) - .getContent()).as("has number of elements").hasSize(1) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(1).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsExactly(expected) @@ -251,8 +251,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0])) - .getContent()).as("has number of elements").hasSize(1) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(1).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsExactly(expected) @@ -268,8 +268,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE, new String[0])) - .getContent()).as("has number of elements").hasSize(3) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(3).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, setA.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsAll(expected) @@ -284,8 +284,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(pending, null, null, null, Boolean.FALSE, new String[0])) - .getContent()).as("has number of elements").hasSize(3) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(3).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, null, Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsAll(expected) @@ -336,8 +336,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(unknown, null, null, setA.getId(), Boolean.FALSE, new String[0])) - .getContent()).as("has number of elements").hasSize(0) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(0).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(unknown, null, null, setA.getId(), Boolean.FALSE, new String[0]))) .as("and filter query returns the same result") @@ -403,8 +403,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0])) - .getContent()).as("has number of elements").hasSize(1) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(1).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsExactly(expected) @@ -419,8 +419,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(null, null, null, setA.getId(), Boolean.FALSE, new String[0])) - .getContent()).as("has number of elements").hasSize(3) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(3).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, null, setA.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsAll(expected) @@ -436,8 +436,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagX.getName())) - .getContent()).as("has number of elements").hasSize(0) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(0).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagX.getName()))) .as("and filter query returns the same result") @@ -452,8 +452,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, targTagW.getName())) - .getContent()).as("has number of elements").hasSize(0) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(0).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, targTagW.getName()))) .as("and filter query returns the same result") @@ -469,8 +469,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { assertThat(targetManagement .findByFilters(PAGE, new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagW.getName())) - .getContent()).as("has number of elements").hasSize(1) - .as("that number is also returned by count query") + .getContent()) + .as("has number of elements").hasSize(1).as("that number is also returned by count query") .hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsExactly(expected) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java index b340c0f03..d5a2b0d12 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/rsql/RSQLUtilityTest.java @@ -47,6 +47,7 @@ import org.mockito.Mock; import org.mockito.Spy; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import org.springframework.orm.jpa.vendor.Database; import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Features; @@ -74,6 +75,8 @@ public class RSQLUtilityTest { @Mock private CriteriaBuilder criteriaBuilderMock; + private final Database testDb = Database.H2; + @Mock private Attribute attribute; @@ -86,8 +89,8 @@ public class RSQLUtilityTest { public void wrongRsqlSyntaxThrowSyntaxException() { final String wrongRSQL = "name==abc;d"; try { - RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class, null).toPredicate(baseSoftwareModuleRootMock, - criteriaQueryMock, criteriaBuilderMock); + RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class, null, testDb) + .toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterSyntaxException e) { } @@ -98,8 +101,8 @@ public class RSQLUtilityTest { final String wrongRSQL = "unknownField==abc"; when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class); try { - RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class, null).toPredicate(baseSoftwareModuleRootMock, - criteriaQueryMock, criteriaBuilderMock); + RSQLUtility.parse(wrongRSQL, SoftwareModuleFields.class, null, testDb) + .toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); fail("Missing an expected RSQLParameterUnsupportedFieldException because of unknown RSQL field"); } catch (final RSQLParameterUnsupportedFieldException e) { } @@ -110,7 +113,7 @@ public class RSQLUtilityTest { public void wrongRsqlMapSyntaxThrowSyntaxException() { String wrongRSQL = TargetFields.ATTRIBUTE + "==abc"; try { - RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(wrongRSQL, TargetFields.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { @@ -118,7 +121,7 @@ public class RSQLUtilityTest { wrongRSQL = TargetFields.ATTRIBUTE + ".unkwon.wrong==abc"; try { - RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(wrongRSQL, TargetFields.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { @@ -126,8 +129,8 @@ public class RSQLUtilityTest { wrongRSQL = DistributionSetFields.METADATA + "==abc"; try { - RSQLUtility.parse(wrongRSQL, DistributionSetFields.class, null).toPredicate(baseSoftwareModuleRootMock, - criteriaQueryMock, criteriaBuilderMock); + RSQLUtility.parse(wrongRSQL, DistributionSetFields.class, null, testDb) + .toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { } @@ -138,7 +141,7 @@ public class RSQLUtilityTest { public void wrongRsqlSubEntitySyntaxThrowSyntaxException() { String wrongRSQL = TargetFields.ASSIGNEDDS + "==abc"; try { - RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(wrongRSQL, TargetFields.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { @@ -146,7 +149,7 @@ public class RSQLUtilityTest { wrongRSQL = TargetFields.ASSIGNEDDS + ".unknownField==abc"; try { - RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(wrongRSQL, TargetFields.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { @@ -154,7 +157,7 @@ public class RSQLUtilityTest { wrongRSQL = TargetFields.ASSIGNEDDS + ".unknownField.ToMuch==abc"; try { - RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(wrongRSQL, TargetFields.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax"); } catch (final RSQLParameterUnsupportedFieldException e) { @@ -173,10 +176,10 @@ public class RSQLUtilityTest { .thenReturn(mock(Predicate.class)); // test - RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - // verfication + // verification verify(criteriaBuilderMock, times(1)).and(any(Predicate.class)); } @@ -192,13 +195,13 @@ public class RSQLUtilityTest { when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock)))) .thenReturn(pathOfString(baseSoftwareModuleRootMock)); // test - RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - // verfication + // verification verify(criteriaBuilderMock, times(1)).and(any(Predicate.class)); verify(criteriaBuilderMock, times(1)).notLike(eq(pathOfString(baseSoftwareModuleRootMock)), - eq("abc".toUpperCase())); + eq("abc".toUpperCase()), eq('\\')); } @Test @@ -213,13 +216,35 @@ public class RSQLUtilityTest { when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock)))) .thenReturn(pathOfString(baseSoftwareModuleRootMock)); // test - RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null).toPredicate(baseSoftwareModuleRootMock, - criteriaQueryMock, criteriaBuilderMock); + RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null, Database.H2) + .toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - // verfication + // verification verify(criteriaBuilderMock, times(1)).and(any(Predicate.class)); verify(criteriaBuilderMock, times(1)).like(eq(pathOfString(baseSoftwareModuleRootMock)), - eq("a\\%".toUpperCase())); + eq("a\\%".toUpperCase()), eq('\\')); + } + + @Test + public void correctRsqlBuildsLikePredicateWithPercentageSQLServer() { + reset(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); + final String correctRsql = "name==a%"; + when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock); + when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class); + when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class)); + when(criteriaBuilderMock. greaterThanOrEqualTo(any(Expression.class), any(String.class))) + .thenReturn(mock(Predicate.class)); + when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock)))) + .thenReturn(pathOfString(baseSoftwareModuleRootMock)); + + // test + RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null, Database.SQL_SERVER) + .toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); + + // verification + verify(criteriaBuilderMock, times(1)).and(any(Predicate.class)); + verify(criteriaBuilderMock, times(1)).like(eq(pathOfString(baseSoftwareModuleRootMock)), + eq("a[%]".toUpperCase()), eq('\\')); } @Test @@ -232,10 +257,10 @@ public class RSQLUtilityTest { when(criteriaBuilderMock. greaterThanOrEqualTo(any(Expression.class), any(String.class))) .thenReturn(mock(Predicate.class)); // test - RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - // verfication + // verification verify(criteriaBuilderMock, times(1)).and(any(Predicate.class)); verify(criteriaBuilderMock, times(1)).lessThan(eq(pathOfString(baseSoftwareModuleRootMock)), eq("abc")); } @@ -249,10 +274,10 @@ public class RSQLUtilityTest { when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class)); // test - RSQLUtility.parse(correctRsql, TestFieldEnum.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(correctRsql, TestFieldEnum.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); - // verfication + // verification verify(criteriaBuilderMock, times(1)).and(any(Predicate.class)); verify(criteriaBuilderMock, times(1)).equal(eq(baseSoftwareModuleRootMock), eq(TestValueEnum.BUMLUX)); } @@ -267,7 +292,7 @@ public class RSQLUtilityTest { try { // test - RSQLUtility.parse(correctRsql, TestFieldEnum.class, null).toPredicate(baseSoftwareModuleRootMock, + RSQLUtility.parse(correctRsql, TestFieldEnum.class, null, testDb).toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); fail("missing RSQLParameterUnsupportedFieldException for wrong enum value"); } catch (final RSQLParameterUnsupportedFieldException e) { @@ -289,8 +314,8 @@ public class RSQLUtilityTest { .thenReturn(mock(Predicate.class)); // test - RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup()).toPredicate(baseSoftwareModuleRootMock, - criteriaQueryMock, criteriaBuilderMock); + RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup(), testDb) + .toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); // verification verify(macroResolver).lookup(overdueProp); @@ -315,8 +340,8 @@ public class RSQLUtilityTest { .thenReturn(mock(Predicate.class)); // test - RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup()).toPredicate(baseSoftwareModuleRootMock, - criteriaQueryMock, criteriaBuilderMock); + RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup(), testDb) + .toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock); // verification verify(macroResolver).lookup(overdueProp); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/jpa-test.properties b/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/jpa-test.properties index 60e396007..a5bf32f47 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/jpa-test.properties +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/jpa-test.properties @@ -11,3 +11,10 @@ hawkbit.server.security.dos.maxStatusEntriesPerAction=10 hawkbit.server.security.dos.maxAttributeEntriesPerTarget=10 # Quota - END + +# Debug utility functions - START +logging.level.org.eclipse.persistence=ERROR +spring.jpa.properties.eclipselink.logging.level=FINE +spring.jpa.properties.eclipselink.logging.level.sql=FINE +spring.jpa.properties.eclipselink.logging.parameters=true +# Debug utility functions - END diff --git a/hawkbit-repository/hawkbit-repository-test/pom.xml b/hawkbit-repository/hawkbit-repository-test/pom.xml index 337899a99..7a858c9d5 100644 --- a/hawkbit-repository/hawkbit-repository-test/pom.xml +++ b/hawkbit-repository/hawkbit-repository-test/pom.xml @@ -39,6 +39,24 @@ hawkbit-artifact-repository-filesystem ${project.version} + + com.h2database + h2 + + + org.mariadb.jdbc + mariadb-java-client + + + com.microsoft.sqlserver + mssql-jdbc + + + + + + + org.springframework.boot spring-boot-starter-logging diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java index 058a9ea79..70f42d662 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java @@ -14,17 +14,13 @@ import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpre import java.io.File; import java.io.IOException; import java.net.URI; +import java.time.ZonedDateTime; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.RandomStringUtils; @@ -104,7 +100,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; // test execution. So, the order execution between EventVerifier and Cleanup is // important! @TestExecutionListeners(inheritListeners = true, listeners = { EventVerifier.class, CleanupTestExecutionListener.class, - MySqlTestDatabase.class }, mergeMode = MergeMode.MERGE_WITH_DEFAULTS) + MySqlTestDatabase.class, MsSqlTestDatabase.class }, mergeMode = MergeMode.MERGE_WITH_DEFAULTS) public abstract class AbstractIntegrationTest { private static final Logger LOG = LoggerFactory.getLogger(AbstractIntegrationTest.class); @@ -378,24 +374,25 @@ public abstract class AbstractIntegrationTest { * * @return {@link String} containing a valid cron expression. */ - public static String getTestSchedule(int minutesToAdd) { + public static String getTestSchedule(final int minutesToAdd) { ZonedDateTime currentTime = ZonedDateTime.now(); currentTime = currentTime.plusMinutes(minutesToAdd); return String.format("0 %d %d %d %d ? %d", currentTime.getMinute(), currentTime.getHour(), currentTime.getDayOfMonth(), currentTime.getMonthValue(), currentTime.getYear()); } - public static String getTestDuration(int duration) { + public static String getTestDuration(final int duration) { return String.format("%02d:%02d:00", duration / 60, duration % 60); } public static String getTestTimeZone() { - ZonedDateTime currentTime = ZonedDateTime.now(); + final ZonedDateTime currentTime = ZonedDateTime.now(); return currentTime.getOffset().getId().replace("Z", "+00:00"); } - public static Map getMaintenanceWindow(String schedule, String duration, String timezone) { - Map maintenanceWindowMap = new HashMap<>(); + public static Map getMaintenanceWindow(final String schedule, final String duration, + final String timezone) { + final Map maintenanceWindowMap = new HashMap<>(); maintenanceWindowMap.put("schedule", schedule); maintenanceWindowMap.put("duration", duration); maintenanceWindowMap.put("timezone", timezone); diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/MsSqlTestDatabase.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/MsSqlTestDatabase.java new file mode 100644 index 000000000..4b9ca4930 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/MsSqlTestDatabase.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2018 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository.test.util; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.apache.commons.lang3.RandomStringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.TestExecutionListener; +import org.springframework.test.context.support.AbstractTestExecutionListener; + +/** + * A {@link TestExecutionListener} for creating and dropping MS SQL Server + * schemas if tests are setup with MS SQL Server. + */ +public class MsSqlTestDatabase extends AbstractTestExecutionListener { + + private static final Logger LOG = LoggerFactory.getLogger(MsSqlTestDatabase.class); + private String schemaName; + private String uri; + private String username; + private String password; + + @Override + public void beforeTestClass(final TestContext testContext) throws Exception { + if (isRunningWithMsSql()) { + LOG.info("Setting up mysql schema for test class {}", testContext.getTestClass().getName()); + this.username = System.getProperty("spring.datasource.username"); + this.password = System.getProperty("spring.datasource.password"); + this.uri = System.getProperty("spring.datasource.url"); + createSchemaUri(); + createSchema(); + } + } + + @Override + public void afterTestClass(final TestContext testContext) throws Exception { + if (isRunningWithMsSql()) { + dropSchema(); + } + } + + private void createSchemaUri() { + schemaName = "SP" + RandomStringUtils.randomAlphanumeric(10); + this.uri = this.uri.substring(0, uri.indexOf(';')); + + System.setProperty("spring.datasource.url", uri + ";database=" + schemaName); + } + + private static boolean isRunningWithMsSql() { + return "SQL_SERVER".equals(System.getProperty("spring.jpa.database")); + } + + private void createSchema() { + try (Connection connection = DriverManager.getConnection(uri, username, password)) { + try (PreparedStatement statement = connection.prepareStatement("CREATE DATABASE " + schemaName + ";")) { + LOG.info("Creating schema {} on uri {}", schemaName, uri); + statement.execute(); + LOG.info("Created schema {} on uri {}", schemaName, uri); + } + } catch (final SQLException e) { + LOG.error("Schema creation failed!", e); + } + + } + + private void dropSchema() { + try (Connection connection = DriverManager.getConnection(uri, username, password)) { + // Needed to avoid the DROP is rejected with "database still in use" + try (PreparedStatement statement = connection + .prepareStatement("ALTER DATABASE " + schemaName + " SET SINGLE_USER WITH ROLLBACK IMMEDIATE;")) { + statement.execute(); + } + + try (PreparedStatement statement = connection.prepareStatement("DROP DATABASE " + schemaName + ";")) { + LOG.info("Dropping schema {} on uri {}", schemaName, uri); + statement.execute(); + LOG.info("Dropped schema {} on uri {}", schemaName, uri); + } + } catch (final SQLException e) { + LOG.error("Schema drop failed!", e); + } + } +} diff --git a/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-mssql.properties b/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-mssql.properties new file mode 100644 index 000000000..17ef486cc --- /dev/null +++ b/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-mssql.properties @@ -0,0 +1,18 @@ +# +# Copyright (c) 2018 Bosch Software Innovations GmbH and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# + +# This profile adds basic configurations for a Microsoft SQL Server DB usage. +# Keep in mind that you need the SQL server driver in your classpath on compile. +# see https://www.eclipse.org/hawkbit/documentation/guide/runhawkbit.html + +spring.jpa.database=SQL_SERVER +spring.datasource.url=jdbc:sqlserver://localhost:1433;database=hawkbit +spring.datasource.username=SA +spring.datasource.password= +spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver diff --git a/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-mysql.properties b/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-mysql.properties index 352f128b8..e6f5cbcf5 100644 --- a/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-mysql.properties +++ b/hawkbit-runtime/hawkbit-update-server/src/main/resources/application-mysql.properties @@ -9,24 +9,10 @@ # This profile adds basic configurations for a MySQL DB usage. # Keep in mind that you need the MariaDB driver in your classpath on compile. -# see https://github.com/eclipse/hawkbit/wiki/Run-hawkBit +# see https://www.eclipse.org/hawkbit/documentation/guide/runhawkbit.html spring.jpa.database=MYSQL spring.datasource.url=jdbc:mysql://localhost:3306/hawkbit spring.datasource.username=root spring.datasource.password= spring.datasource.driverClassName=org.mariadb.jdbc.Driver - -spring.datasource.tomcat.max-active=100 -spring.datasource.tomcat.max-idle=10 -spring.datasource.tomcat.min-idle=10 -spring.datasource.tomcat.initial-size=10 -spring.datasource.tomcat.validation-query=select 1 from dual -spring.datasource.tomcat.validation-interval=30000 -spring.datasource.tomcat.test-on-borrow=true -spring.datasource.tomcat.test-on-return=false -spring.datasource.tomcat.test-while-idle=true -spring.datasource.tomcat.time-between-eviction-runs-millis=30000 -spring.datasource.tomcat.min-evictable-idle-time-millis=60000 -spring.datasource.tomcat.max-wait=10000 -spring.datasource.tomcat.jmx-enabled=true diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/ProxyBaseSoftwareModuleItem.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/ProxyBaseSoftwareModuleItem.java index 1559a9bec..5dd5bc521 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/ProxyBaseSoftwareModuleItem.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/ProxyBaseSoftwareModuleItem.java @@ -46,7 +46,6 @@ public class ProxyBaseSoftwareModuleItem { * Default constructor. */ public ProxyBaseSoftwareModuleItem() { - super(); swId = RANDOM_OBJ.nextLong(); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java index 3a7c6d1fa..99de3a57d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java @@ -78,7 +78,6 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene UploadHandler(final String fileName, final long fileSize, final UploadLayout view, final long maxSize, final Upload upload, final String mimeType, final SoftwareModule selectedSw, final SoftwareModuleManagement softwareManagement) { - super(); this.aborted = false; this.fileName = fileName; this.fileSize = fileSize; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/CommonDialogWindow.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/CommonDialogWindow.java index 63dc9694c..55b56c694 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/CommonDialogWindow.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/CommonDialogWindow.java @@ -491,7 +491,6 @@ public class CommonDialogWindow extends Window { private final Field field; public ChangeListener(final Field field) { - super(); this.field = field; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/entity/SoftwareModuleIdName.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/entity/SoftwareModuleIdName.java index dd80598db..17a6b58e8 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/entity/SoftwareModuleIdName.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/entity/SoftwareModuleIdName.java @@ -30,7 +30,6 @@ public class SoftwareModuleIdName implements Serializable { * of the {@link SoftwareModule} */ public SoftwareModuleIdName(final Long id, final String name) { - super(); this.id = id; this.name = name; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/AbstractGridComponentLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/AbstractGridComponentLayout.java index 2e97293b4..f14243bb7 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/AbstractGridComponentLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/AbstractGridComponentLayout.java @@ -46,7 +46,6 @@ public abstract class AbstractGridComponentLayout extends VerticalLayout { * @param managementUIState */ public AbstractGridComponentLayout(final VaadinMessageSource i18n, final UIEventBus eventBus) { - super(); this.i18n = i18n; this.eventBus = eventBus; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUITabSheet.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUITabSheet.java index 58ef46c40..e80c87fd9 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUITabSheet.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUITabSheet.java @@ -25,7 +25,6 @@ public class SPUITabSheet extends TabSheet { * Constructor. */ public SPUITabSheet() { - super(); decorate(); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/polling/DurationField.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/polling/DurationField.java index d511e275e..a443ddb9c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/polling/DurationField.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/polling/DurationField.java @@ -59,8 +59,6 @@ public class DurationField extends DateField { * Creates a DurationField */ protected DurationField() { - super(); - this.setTimeZone(TimeZone.getTimeZone(ZONEID_UTC)); durationFormat.setTimeZone(TimeZone.getTimeZone(ZONEID_UTC)); additionalFormat.setTimeZone(TimeZone.getTimeZone(ZONEID_UTC)); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SpringContextHelper.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SpringContextHelper.java index 863d47eb4..6e3fa4db1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SpringContextHelper.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SpringContextHelper.java @@ -24,7 +24,7 @@ public final class SpringContextHelper { * Private Constructor. */ private SpringContextHelper() { - super(); + // Utility class } public static void setContext(final ApplicationContext context) { diff --git a/pom.xml b/pom.xml index 88e40053f..cc31f69c9 100644 --- a/pom.xml +++ b/pom.xml @@ -121,6 +121,8 @@ 4.0.3 1.7.6.RELEASE + + 1.3.1.RELEASE 2.0.0 @@ -159,6 +161,7 @@ 1.0.2 19.0 2.0.2 + 6.4.0.jre8 1.50.5 2.2.4 1.1.7 @@ -569,6 +572,19 @@ + + + com.rabbitmq + http-client + ${rabbitmq.http-client.version} + compile + + + spring-web + org.springframework + + + com.cronutils cron-utils @@ -768,7 +784,11 @@ org.mariadb.jdbc mariadb-java-client ${mariadb-java-client.version} - test + + + com.microsoft.sqlserver + mssql-jdbc + ${mssql-jdbc.version} org.springframework.amqp