From f99da28185f5f2b7760af441d4e2aa41f36d51cc Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Tue, 18 Apr 2017 08:43:38 +0200 Subject: [PATCH] Fix default isolation and auto commit (#484) * Switch to spring/DB default isolation. Signed-off-by: kaizimmerm * Fix dependency to uncommited isolation level in rollout management. Signed-off-by: kaizimmerm * Corrected UQ checks Signed-off-by: kaizimmerm * Remove modifying annotation. Signed-off-by: kaizimmerm * Disable autocommit on connection pool. Cleanups. Flush at commit. Signed-off-by: kaizimmerm * Cleanups. Signed-off-by: kaizimmerm * Fix Rollout UI performance. Signed-off-by: kaizimmerm * Typo fixed Signed-off-by: Dominic Schabel * Remove empty lines Signed-off-by: kaizimmerm --- .../main/resources/hawkbitdefaults.properties | 1 + .../resources/application-test.properties | 1 + .../hawkbit/repository/RolloutManagement.java | 13 --- .../model/TotalTargetCountStatus.java | 7 ++ .../repository/AbstractRolloutManagement.java | 4 +- .../repository/jpa/ActionRepository.java | 9 +- .../jpa/ActionStatusRepository.java | 3 +- .../repository/jpa/BaseEntityRepository.java | 5 +- .../DistributionSetMetadataRepository.java | 3 +- .../jpa/DistributionSetRepository.java | 7 +- .../jpa/DistributionSetTagRepository.java | 5 +- .../jpa/DistributionSetTypeRepository.java | 3 +- .../repository/jpa/JpaArtifactManagement.java | 16 +--- .../jpa/JpaControllerManagement.java | 20 ++-- .../jpa/JpaDeploymentManagement.java | 14 +-- .../jpa/JpaDistributionSetManagement.java | 75 +++++---------- .../repository/jpa/JpaReportManagement.java | 3 +- .../jpa/JpaRolloutGroupManagement.java | 3 +- .../repository/jpa/JpaRolloutManagement.java | 91 +++++++----------- .../repository/jpa/JpaSoftwareManagement.java | 43 +++------ .../repository/jpa/JpaSystemManagement.java | 35 ++----- .../repository/jpa/JpaTagManagement.java | 46 +++------ .../jpa/JpaTargetFilterQueryManagement.java | 24 ++--- .../repository/jpa/JpaTargetManagement.java | 49 +++------- .../jpa/JpaTenantConfigurationManagement.java | 10 +- .../jpa/JpaTenantStatsManagement.java | 3 +- .../jpa/LocalArtifactRepository.java | 3 +- .../RepositoryApplicationConfiguration.java | 4 +- .../jpa/RolloutGroupRepository.java | 5 +- .../repository/jpa/RolloutRepository.java | 3 +- .../jpa/RolloutTargetGroupRepository.java | 3 +- .../jpa/SoftwareModuleMetadataRepository.java | 3 +- .../jpa/SoftwareModuleRepository.java | 5 +- .../jpa/SoftwareModuleTypeRepository.java | 3 +- .../jpa/TargetFilterQueryRepository.java | 5 +- .../repository/jpa/TargetRepository.java | 7 +- .../repository/jpa/TargetTagRepository.java | 5 +- .../jpa/TenantConfigurationRepository.java | 3 +- .../jpa/TenantMetaDataRepository.java | 8 +- .../jpa/event/JpaEventEntityManager.java | 2 +- .../specifications/RolloutSpecification.java | 14 ++- .../specifications/TargetSpecifications.java | 16 ++-- .../V1_11_1__target_filter_query_UQ___H2.sql | 2 + ...1_11_1__target_filter_query_UQ___MYSQL.sql | 2 + .../jpa/AbstractJpaIntegrationTest.java | 2 +- .../jpa/DistributionSetManagementTest.java | 12 +++ .../repository/jpa/RolloutManagementTest.java | 25 ++--- .../repository/jpa/TargetManagementTest.java | 11 +++ .../resources/application-test.properties | 2 + .../test/matcher/EventVerifier.java | 4 + .../test/util/AbstractIntegrationTest.java | 2 +- .../util/JpaTestRepositoryManagement.java | 3 - .../ui/rollout/rollout/ProxyRollout.java | 93 +------------------ .../ui/rollout/rollout/RolloutBeanQuery.java | 52 +++++------ .../ui/rollout/rollout/RolloutListGrid.java | 54 ----------- .../rolloutgroup/RolloutGroupBeanQuery.java | 57 ++++++------ 56 files changed, 300 insertions(+), 603 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_1__target_filter_query_UQ___H2.sql create mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_1__target_filter_query_UQ___MYSQL.sql diff --git a/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties b/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties index f859f6884..cd97b7c49 100644 --- a/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties +++ b/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties @@ -32,6 +32,7 @@ endpoints.spring.cloud.bus.env.enabled=false spring.jpa.database=H2 spring.jpa.show-sql=false spring.datasource.driverClassName=org.h2.Driver +spring.datasource.tomcat.defaultAutoCommit=false # Logging spring.datasource.eclipselink.logging.logger=JavaLogger spring.jpa.properties.eclipselink.logging.level=off diff --git a/hawkbit-ddi-resource/src/test/resources/application-test.properties b/hawkbit-ddi-resource/src/test/resources/application-test.properties index 5ac6df2f7..c26d733a1 100644 --- a/hawkbit-ddi-resource/src/test/resources/application-test.properties +++ b/hawkbit-ddi-resource/src/test/resources/application-test.properties @@ -26,6 +26,7 @@ hawkbit.server.security.dos.maxAttributeEntriesPerTarget=10 spring.jpa.database=H2 spring.datasource.url=jdbc:h2:mem:sp-db;DB_CLOSE_ON_EXIT=FALSE spring.datasource.driverClassName=org.h2.Driver +spring.datasource.tomcat.defaultAutoCommit=false spring.datasource.username=sa spring.datasource.password=sa diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java index 9f135a9fa..3bf3dcdd6 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java @@ -286,19 +286,6 @@ public interface RolloutManagement { */ boolean exists(@NotNull Long rolloutId); - /*** - * Get finished percentage details for a specified group which is in running - * state. - * - * @param rolloutId - * the ID of the {@link Rollout} - * @param rolloutGroupId - * the ID of the {@link RolloutGroup} - * @return percentage finished - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ) - float getFinishedPercentForRunningGroup(@NotNull Long rolloutId, @NotNull Long rolloutGroupId); - /** * Pauses a rollout which is currently running. The Rollout switches * {@link RolloutStatus#PAUSED}. {@link RolloutGroup}s which are currently diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatus.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatus.java index bcb0df3f4..335bb8024 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatus.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TotalTargetCountStatus.java @@ -104,6 +104,13 @@ public class TotalTargetCountStatus { return count == null ? 0L : count; } + /** + * @return finished percentage of targets + */ + public float getFinishedPercent() { + return ((float) getTotalTargetCountByStatus(TotalTargetCountStatus.Status.FINISHED) / totalTargetCount) * 100; + } + /** * Populate all target status to a the given map * diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/AbstractRolloutManagement.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/AbstractRolloutManagement.java index 12bdf630d..0fa84d11f 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/AbstractRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/AbstractRolloutManagement.java @@ -28,7 +28,6 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; @@ -78,12 +77,11 @@ public abstract class AbstractRolloutManagement implements RolloutManagement { this.lockRegistry = lockRegistry; } - protected int runInNewTransaction(final String transactionName, final TransactionCallback action) { + protected Long runInNewTransaction(final String transactionName, final TransactionCallback action) { final DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setName(transactionName); def.setReadOnly(false); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); - def.setIsolationLevel(Isolation.READ_UNCOMMITTED.value()); return new TransactionTemplate(txManager, def).execute(action); } 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 36c626a69..b408ebb5b 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 @@ -35,14 +35,13 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link Action} repository. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface ActionRepository extends BaseEntityRepository, JpaSpecificationExecutor { /** * Retrieves an Action with all lazy attributes. @@ -190,7 +189,7 @@ public interface ActionRepository extends BaseEntityRepository, * the current status of the actions which are affected */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional @Query("UPDATE JpaAction a SET a.status = :statusToSet WHERE a.target IN :targetsIds AND a.active = :active AND a.status = :currentStatus AND a.distributionSet.requiredMigrationStep = false") void switchStatus(@Param("statusToSet") Action.Status statusToSet, @Param("targetsIds") List targetIds, @Param("active") boolean active, @Param("currentStatus") Action.Status currentStatus); @@ -381,7 +380,7 @@ public interface ActionRepository extends BaseEntityRepository, * id of {@link Rollout} * @return list of objects with status and target count */ - @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.target)) FROM JpaAction a WHERE a.rollout.id IN ?1 GROUP BY a.rollout.id,a.status") + @Query("SELECT NEW org.eclipse.hawkbit.repository.model.TotalTargetCountActionStatus( a.rollout.id, a.status , COUNT(a.id)) FROM JpaAction a WHERE a.rollout.id IN ?1 GROUP BY a.rollout.id,a.status") List getStatusCountByRolloutId(List rolloutId); /** @@ -424,7 +423,7 @@ public interface ActionRepository extends BaseEntityRepository, * the IDs of the actions to be deleted. */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 @Query("DELETE FROM JpaAction a WHERE a.id IN ?1") void deleteByIdIn(final Collection actionIDs); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionStatusRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionStatusRepository.java index 1d48e520f..8503f7ed0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionStatusRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionStatusRepository.java @@ -17,14 +17,13 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link ActionStatus} repository. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface ActionStatusRepository extends BaseEntityRepository, JpaSpecificationExecutor { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/BaseEntityRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/BaseEntityRepository.java index 1b1c1fb1d..170507113 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/BaseEntityRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/BaseEntityRepository.java @@ -17,7 +17,6 @@ import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** @@ -29,7 +28,7 @@ import org.springframework.transaction.annotation.Transactional; * of the entity type */ @NoRepositoryBean -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface BaseEntityRepository extends PagingAndSortingRepository { @@ -40,7 +39,7 @@ public interface BaseEntityRepository, JpaSpecificationExecutor { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetRepository.java index 62d38cf2a..46b2c6bb5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetRepository.java @@ -23,14 +23,13 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link DistributionSet} repository. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface DistributionSetRepository extends BaseEntityRepository, JpaSpecificationExecutor { @@ -51,7 +50,7 @@ public interface DistributionSetRepository * to be deleted */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional @Query("update JpaDistributionSet d set d.deleted = 1 where d.id in :ids") void deleteDistributionSet(@Param("ids") Long... ids); @@ -63,7 +62,7 @@ public interface DistributionSetRepository * @return number of affected/deleted records */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 @Query("DELETE FROM JpaDistributionSet d WHERE d.id IN ?1") int deleteByIdIn(Collection ids); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTagRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTagRepository.java index 1fc5b4c44..4d1179689 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTagRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTagRepository.java @@ -17,14 +17,13 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.TargetTag; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link TargetTag} repository. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface DistributionSetTagRepository extends BaseEntityRepository, JpaSpecificationExecutor { /** @@ -35,7 +34,7 @@ public interface DistributionSetTagRepository * @return 1 if tag was deleted */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional Long deleteByName(final String tagName); /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTypeRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTypeRepository.java index 82754d7f8..6cc2dfc3d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTypeRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/DistributionSetTypeRepository.java @@ -15,14 +15,13 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link PagingAndSortingRepository} for {@link DistributionSetType}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface DistributionSetTypeRepository extends BaseEntityRepository, JpaSpecificationExecutor { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java index de3f7082b..160898f96 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaArtifactManagement.java @@ -32,8 +32,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -41,7 +39,7 @@ import org.springframework.validation.annotation.Validated; * JPA based {@link ArtifactManagement} implementation. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaArtifactManagement implements ArtifactManagement { @@ -72,8 +70,7 @@ public class JpaArtifactManagement implements ArtifactManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Artifact createArtifact(final InputStream stream, final Long moduleId, final String filename, final String providedMd5Sum, final String providedSha1Sum, final boolean overrideExisting, final String contentType) { @@ -103,8 +100,7 @@ public class JpaArtifactManagement implements ArtifactManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public boolean clearArtifactBinary(final String sha1Hash, final Long moduleId) { if (localArtifactRepository.existsWithSha1HashAndSoftwareModuleIdIsNot(sha1Hash, moduleId)) { @@ -122,8 +118,7 @@ public class JpaArtifactManagement implements ArtifactManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteArtifact(final Long id) { final JpaArtifact existing = (JpaArtifact) findArtifact(id) .orElseThrow(() -> new EntityNotFoundException(Artifact.class, id)); @@ -190,8 +185,7 @@ public class JpaArtifactManagement implements ArtifactManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Artifact createArtifact(final InputStream inputStream, final Long moduleId, final String filename, final boolean overrideExisting) { return createArtifact(inputStream, moduleId, filename, null, null, overrideExisting, null); 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 06ca21167..0832c0822 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 @@ -59,7 +59,6 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.Modifying; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -68,7 +67,7 @@ import org.springframework.validation.annotation.Validated; * JPA based {@link ControllerManagement} implementation. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaControllerManagement implements ControllerManagement { private static final Logger LOG = LoggerFactory.getLogger(ControllerManagement.class); @@ -126,8 +125,7 @@ public class JpaControllerManagement implements ControllerManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Target updateLastTargetQuery(final String controllerId, final URI address) { final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerId) .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); @@ -196,8 +194,7 @@ public class JpaControllerManagement implements ControllerManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Target findOrRegisterTargetIfItDoesNotexist(final String controllerId, final URI address) { final Specification spec = (targetRoot, query, cb) -> cb .equal(targetRoot.get(JpaTarget_.controllerId), controllerId); @@ -242,7 +239,6 @@ public class JpaControllerManagement implements ControllerManagement { } @Override - @Modifying @Transactional(isolation = Isolation.READ_COMMITTED) public Action addCancelActionStatus(final ActionStatusCreate c) { final JpaActionStatusCreate create = (JpaActionStatusCreate) c; @@ -286,7 +282,6 @@ public class JpaControllerManagement implements ControllerManagement { } @Override - @Modifying @Transactional(isolation = Isolation.READ_COMMITTED) public Action addUpdateActionStatus(final ActionStatusCreate c) { final JpaActionStatusCreate create = (JpaActionStatusCreate) c; @@ -386,8 +381,7 @@ public class JpaControllerManagement implements ControllerManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Target updateControllerAttributes(final String controllerId, final Map data) { final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerId) .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); @@ -407,8 +401,7 @@ public class JpaControllerManagement implements ControllerManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Action registerRetrieved(final Long actionId, final String message) { return handleRegisterRetrieved(actionId, message); } @@ -467,8 +460,7 @@ public class JpaControllerManagement implements ControllerManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public ActionStatus addInformationalActionStatus(final ActionStatusCreate c) { final JpaActionStatusCreate create = (JpaActionStatusCreate) c; final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId()); 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 47316fb61..0b18ca79e 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 @@ -79,7 +79,6 @@ 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.data.jpa.repository.Modifying; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.annotation.Isolation; @@ -94,7 +93,7 @@ import com.google.common.collect.Lists; * JPA implementation for {@link DeploymentManagement}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaDeploymentManagement implements DeploymentManagement { private static final Logger LOG = LoggerFactory.getLogger(JpaDeploymentManagement.class); @@ -141,8 +140,7 @@ public class JpaDeploymentManagement implements DeploymentManagement { private PlatformTransactionManager txManager; @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional // Exception squid:S2095: see // https://jira.sonarsource.com/browse/SONARJAVA-1478 @SuppressWarnings({ "squid:S2095" }) @@ -153,7 +151,6 @@ public class JpaDeploymentManagement implements DeploymentManagement { } @Override - @Modifying @Transactional(isolation = Isolation.READ_COMMITTED) public DistributionSetAssignmentResult assignDistributionSet(final Long dsID, final Collection targets) { @@ -161,7 +158,6 @@ public class JpaDeploymentManagement implements DeploymentManagement { } @Override - @Modifying @Transactional(isolation = Isolation.READ_COMMITTED) public DistributionSetAssignmentResult assignDistributionSet(final Long dsID, final Collection targets, final String actionMessage) { @@ -356,7 +352,6 @@ public class JpaDeploymentManagement implements DeploymentManagement { } @Override - @Modifying @Transactional(isolation = Isolation.READ_COMMITTED) public Action cancelAction(final Long actionId) { LOG.debug("cancelAction({})", actionId); @@ -399,7 +394,6 @@ public class JpaDeploymentManagement implements DeploymentManagement { } @Override - @Modifying @Transactional(isolation = Isolation.READ_COMMITTED) public Action forceQuitAction(final Long actionId) { final JpaAction action = actionRepository.findById(actionId) @@ -444,7 +438,6 @@ public class JpaDeploymentManagement implements DeploymentManagement { final DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setName("startScheduledActions-" + rolloutId); def.setReadOnly(false); - def.setIsolationLevel(Isolation.READ_UNCOMMITTED.value()); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); return new TransactionTemplate(txManager, def).execute(status -> { final Page rolloutGroupActions = findActionsByRolloutAndRolloutGroupParent(rolloutId, @@ -631,8 +624,7 @@ public class JpaDeploymentManagement implements DeploymentManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Action forceTargetAction(final Long actionId) { final JpaAction action = actionRepository.findById(actionId) .orElseThrow(() -> new EntityNotFoundException(Action.class, actionId)); 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 44e57f43d..7514b9441 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 @@ -68,8 +68,6 @@ 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.repository.Modifying; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; @@ -81,7 +79,7 @@ import com.google.common.collect.Lists; * JPA implementation of {@link DistributionSetManagement}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaDistributionSetManagement implements DistributionSetManagement { @@ -138,8 +136,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSetTagAssignmentResult toggleTagAssignment(final Collection dsIds, final String tagName) { final List sets = findDistributionSetListWithDetails(dsIds); @@ -186,8 +183,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSet updateDistributionSet(final DistributionSetUpdate u) { final GenericDistributionSetUpdate update = (GenericDistributionSetUpdate) u; @@ -237,8 +233,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteDistributionSet(final Collection distributionSetIDs) { final List setsFound = findDistributionSetAllById(distributionSetIDs); @@ -275,33 +270,24 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSet createDistributionSet(final DistributionSetCreate c) { final JpaDistributionSetCreate create = (JpaDistributionSetCreate) c; if (create.getType() == null) { create.type(systemManagement.getTenantMetadata().getDefaultDsType().getKey()); } - final JpaDistributionSet dSet = create.build(); - - if (distributionSetRepository.countByNameAndVersion(dSet.getName(), dSet.getVersion()) > 0) { - throw new EntityAlreadyExistsException("DistributionSet with that name and version already exists."); - } - - return distributionSetRepository.save(dSet); + return distributionSetRepository.save(create.build()); } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List createDistributionSets(final Collection creates) { return creates.stream().map(this::createDistributionSet).collect(Collectors.toList()); } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSet assignSoftwareModules(final Long setId, final Collection moduleIds) { final Collection modules = softwareModuleRepository.findByIdIn(moduleIds); @@ -320,8 +306,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSet unassignSoftwareModule(final Long setId, final Long moduleId) { final JpaDistributionSet set = findDistributionSetAndThrowExceptionIfNotFound(setId); final JpaSoftwareModule module = findSoftwareModuleAndThrowExceptionIfNotFound(moduleId); @@ -334,8 +319,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSetType updateDistributionSetType(final DistributionSetTypeUpdate u) { final GenericDistributionSetTypeUpdate update = (GenericDistributionSetTypeUpdate) u; @@ -361,8 +345,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSetType assignMandatorySoftwareModuleTypes(final Long dsTypeId, final Collection softwareModulesTypeIds) { final Collection modules = softwareModuleTypeRepository @@ -382,8 +365,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSetType assignOptionalSoftwareModuleTypes(final Long dsTypeId, final Collection softwareModulesTypeIds) { @@ -411,8 +393,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSetType unassignSoftwareModuleType(final Long dsTypeId, final Long softwareModuleTypeId) { final JpaDistributionSetType type = findDistributionSetTypeAndThrowExceptionIfNotFound(dsTypeId); @@ -591,8 +572,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSetType createDistributionSetType(final DistributionSetTypeCreate c) { final JpaDistributionSetTypeCreate create = (JpaDistributionSetTypeCreate) c; @@ -600,8 +580,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteDistributionSetType(final Long typeId) { final JpaDistributionSetType toDelete = distributionSetTypeRepository.findById(typeId) @@ -616,8 +595,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public List createDistributionSetMetadata(final Long dsId, final Collection md) { md.forEach(meta -> checkAndThrowAlreadyIfDistributionSetMetadataExists( @@ -632,8 +610,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public DistributionSetMetadata updateDistributionSetMetadata(final Long dsId, final MetaData md) { // check if exists otherwise throw entity not found exception @@ -648,8 +625,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public void deleteDistributionSetMetadata(final Long distributionSetId, final String key) { final JpaDistributionSetMetadata metadata = (JpaDistributionSetMetadata) findDistributionSetMetadata( distributionSetId, key).orElseThrow( @@ -833,8 +809,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List assignTag(final Collection dsIds, final Long dsTagId) { final List allDs = findDistributionSetListWithDetails(dsIds); @@ -853,8 +828,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List unAssignAllDistributionSetsByTag(final Long dsTagId) { final DistributionSetTag distributionSetTag = tagManagement.findDistributionSetTagById(dsTagId) @@ -868,8 +842,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSet unAssignTag(final Long dsId, final Long dsTagId) { final List allDs = findDistributionSetListWithDetails(Arrays.asList(dsId)); @@ -891,16 +864,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List createDistributionSetTypes(final Collection types) { return types.stream().map(this::createDistributionSetType).collect(Collectors.toList()); } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteDistributionSet(final Long setId) { throwExceptionIfDistributionSetDoesNotExist(setId); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaReportManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaReportManagement.java index 448f5b314..d9f911e01 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaReportManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaReportManagement.java @@ -41,7 +41,6 @@ import org.eclipse.hawkbit.repository.report.model.SeriesTime; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -49,7 +48,7 @@ import org.springframework.validation.annotation.Validated; * JPA implementation of {@link ReportManagement}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaReportManagement implements ReportManagement { 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 245b38c72..dc81d3e8a 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 @@ -51,7 +51,6 @@ 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.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -59,7 +58,7 @@ import org.springframework.validation.annotation.Validated; * JPA implementation of {@link RolloutGroupManagement}. */ @Validated -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public class JpaRolloutGroupManagement implements RolloutGroupManagement { @Autowired 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 713039fb3..ca491ec00 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 @@ -17,6 +17,7 @@ import java.util.concurrent.locks.Lock; import java.util.stream.Collectors; import java.util.stream.StreamSupport; +import javax.persistence.EntityManager; import javax.validation.ConstraintDeclarationException; import org.apache.commons.lang3.StringUtils; @@ -35,7 +36,6 @@ import org.eclipse.hawkbit.repository.builder.RolloutUpdate; import org.eclipse.hawkbit.repository.event.remote.entity.RolloutGroupCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent; import org.eclipse.hawkbit.repository.exception.ConstraintViolationException; -import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; @@ -78,13 +78,11 @@ 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.data.jpa.repository.Modifying; import org.springframework.integration.support.locks.LockRegistry; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionException; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.concurrent.ListenableFuture; @@ -96,7 +94,7 @@ import com.google.common.collect.Lists; * JPA implementation of {@link RolloutManagement}. */ @Validated -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public class JpaRolloutManagement extends AbstractRolloutManagement { private static final Logger LOGGER = LoggerFactory.getLogger(JpaRolloutManagement.class); @@ -128,6 +126,9 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { @Autowired private AfterTransactionCommitExecutor afterCommit; + @Autowired + private EntityManager entityManager; + JpaRolloutManagement(final TargetManagement targetManagement, final DeploymentManagement deploymentManagement, final RolloutGroupManagement rolloutGroupManagement, final DistributionSetManagement distributionSetManagement, final ApplicationContext context, @@ -140,7 +141,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { @Override public Page findAll(final Pageable pageable, final boolean deleted) { - final Specification spec = RolloutSpecification.isDeleted(deleted); + final Specification spec = RolloutSpecification.isDeletedWithDistributionSet(deleted); return JpaRolloutHelper.convertPage(rolloutRepository.findAll(spec, pageable), pageable); } @@ -148,7 +149,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { public Page findAllByPredicate(final String rsqlParam, final Pageable pageable, final boolean deleted) { final List> specList = Lists.newArrayListWithExpectedSize(2); specList.add(RSQLUtility.parse(rsqlParam, RolloutFields.class, virtualPropertyReplacer)); - specList.add(RolloutSpecification.isDeleted(deleted)); + specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted)); return JpaRolloutHelper.convertPage(findByCriteriaAPI(pageable, specList), pageable); } @@ -171,8 +172,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public Rollout createRollout(final RolloutCreate rollout, final int amountGroup, final RolloutGroupConditions conditions) { RolloutHelper.verifyRolloutGroupParameter(amountGroup); @@ -181,8 +181,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public Rollout createRollout(final RolloutCreate rollout, final List groups, final RolloutGroupConditions conditions) { RolloutHelper.verifyRolloutGroupParameter(groups.size()); @@ -191,10 +190,6 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } private JpaRollout createRollout(final JpaRollout rollout) { - final Optional existingRollout = rolloutRepository.findByName(rollout.getName()); - if (existingRollout.isPresent()) { - throw new EntityAlreadyExistsException(existingRollout.get().getName()); - } final Long totalTargets = targetManagement.countTargetByTargetFilterQuery(rollout.getTargetFilterQuery()); if (totalTargets == 0) { @@ -346,10 +341,12 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { final List readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout, RolloutGroupStatus.READY, group); - final long targetsInGroupFilter = targetManagement - .countAllTargetsByTargetFilterQueryAndNotInRolloutGroups(readyGroups, groupTargetFilter); + final long targetsInGroupFilter = runInNewTransaction("countAllTargetsByTargetFilterQueryAndNotInRolloutGroups", + count -> targetManagement.countAllTargetsByTargetFilterQueryAndNotInRolloutGroups(readyGroups, + groupTargetFilter)); final long expectedInGroup = Math.round(group.getTargetPercentage() / 100 * (double) targetsInGroupFilter); - final long currentlyInGroup = rolloutTargetGroupRepository.countByRolloutGroup(group); + final long currentlyInGroup = runInNewTransaction("countRolloutTargetGroupByRolloutGroup", + count -> rolloutTargetGroupRepository.countByRolloutGroup(group)); // Switch the Group status to READY, when there are enough Targets in // the Group @@ -369,7 +366,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } while (targetsLeftToAdd > 0); group.setStatus(RolloutGroupStatus.READY); - group.setTotalTargets(rolloutTargetGroupRepository.countByRolloutGroup(group).intValue()); + group.setTotalTargets(runInNewTransaction("countRolloutTargetGroupByRolloutGroup", + count -> rolloutTargetGroupRepository.countByRolloutGroup(group)).intValue()); return rolloutGroupRepository.save(group); } catch (final TransactionException e) { @@ -378,7 +376,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } } - private Integer assignTargetsToGroupInNewTransaction(final Rollout rollout, final RolloutGroup group, + private Long assignTargetsToGroupInNewTransaction(final Rollout rollout, final RolloutGroup group, final String targetFilter, final long limit) { return runInNewTransaction("assignTargetsToRolloutGroup", status -> { @@ -390,7 +388,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { createAssignmentOfTargetsToGroup(targets, group); - return targets.getNumberOfElements(); + return Long.valueOf(targets.getNumberOfElements()); }); } @@ -414,8 +412,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public Rollout startRollout(final Long rolloutId) { LOGGER.debug("startRollout called for rollout {}", rolloutId); @@ -496,7 +493,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { return totalActionsCreated; } - private Integer createActionsForTargetsInNewTransaction(final long rolloutId, final long groupId, final int limit) { + private Long createActionsForTargetsInNewTransaction(final long rolloutId, final long groupId, final int limit) { return runInNewTransaction("createActionsForTargets", status -> { final PageRequest pageRequest = new PageRequest(0, limit); final Rollout rollout = rolloutRepository.findOne(rolloutId); @@ -512,7 +509,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { createScheduledAction(targets.getContent(), distributionSet, actionType, forceTime, rollout, group); } - return targets.getNumberOfElements(); + return Long.valueOf(targets.getNumberOfElements()); }); } @@ -545,8 +542,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public void pauseRollout(final Long rolloutId) { final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(rolloutId); if (!RolloutStatus.RUNNING.equals(rollout.getStatus())) { @@ -563,8 +559,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public void resumeRollout(final Long rolloutId) { final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(rolloutId); if (!(RolloutStatus.PAUSED.equals(rollout.getStatus()))) { @@ -660,6 +655,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } private boolean isRolloutComplete(final JpaRollout rollout) { + // ensure that changes in the same transaction count + entityManager.flush(); final Long groupsActiveLeft = rolloutGroupRepository.countByRolloutIdAndStatusOrStatus(rollout.getId(), RolloutGroupStatus.RUNNING, RolloutGroupStatus.SCHEDULED); return groupsActiveLeft == 0; @@ -742,7 +739,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } } - private int executeFittingHandler(final Long rolloutId) { + private long executeFittingHandler(final Long rolloutId) { LOGGER.debug("handle rollout {}", rolloutId); final JpaRollout rollout = rolloutRepository.findOne(rolloutId); @@ -788,8 +785,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public void deleteRollout(final long rolloutId) { final JpaRollout jpaRollout = rolloutRepository.findOne(rolloutId); @@ -821,8 +817,12 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { deleteScheduledActions(rollout, scheduledActions); // avoid another scheduler round and re-check if all scheduled actions - // has been cleaned up - final boolean hasScheduledActionsLeft = findScheduledActionsByRollout(rollout).getNumberOfElements() > 0; + // has been cleaned up. we flush first to ensure that the we include the + // deletion above + entityManager.flush(); + final boolean hasScheduledActionsLeft = actionRepository.countByRolloutIdAndStatus(rollout.getId(), + Status.SCHEDULED) > 0; + if (hasScheduledActionsLeft) { return; } @@ -870,7 +870,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { @Override public Long countRolloutsAll() { - return rolloutRepository.count(RolloutSpecification.isDeleted(false)); + return rolloutRepository.count(RolloutSpecification.isDeletedWithDistributionSet(false)); } @Override @@ -893,8 +893,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public Rollout updateRollout(final RolloutUpdate u) { final GenericRolloutUpdate update = (GenericRolloutUpdate) u; final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(update.getId()); @@ -930,7 +929,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { @Override public Page findAllRolloutsWithDetailedStatus(final Pageable pageable, final boolean deleted) { Page rollouts; - final Specification spec = RolloutSpecification.isDeleted(deleted); + final Specification spec = RolloutSpecification.isDeletedWithDistributionSet(deleted); rollouts = rolloutRepository.findAll(spec, pageable); setRolloutStatusDetails(rollouts); return JpaRolloutHelper.convertPage(rollouts, pageable); @@ -975,24 +974,6 @@ public class JpaRolloutManagement extends AbstractRolloutManagement { } } - @Override - public float getFinishedPercentForRunningGroup(final Long rolloutId, final Long rolloutGroupId) { - final RolloutGroup rolloutGroup = rolloutGroupRepository.findById(rolloutGroupId) - .orElseThrow(() -> new EntityNotFoundException(RolloutGroup.class, rolloutGroupId)); - - final long totalGroup = rolloutGroup.getTotalTargets(); - if (totalGroup == 0) { - // in case e.g. targets has been deleted we don't have any actions - // left for this group, so the group is finished - return 100; - } - - final Long finished = actionRepository.countByRolloutIdAndRolloutGroupIdAndStatus(rolloutId, - rolloutGroup.getId(), Action.Status.FINISHED); - // calculate threshold - return ((float) finished / (float) totalGroup) * 100; - } - @Override public boolean exists(final Long rolloutId) { return rolloutRepository.exists(rolloutId); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java index 33d92a313..ed72f0e65 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java @@ -69,9 +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.data.jpa.repository.Modifying; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -83,7 +81,7 @@ import com.google.common.collect.Sets; * JPA implementation of {@link SoftwareManagement}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaSoftwareManagement implements SoftwareManagement { @@ -118,8 +116,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { private VirtualPropertyReplacer virtualPropertyReplacer; @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public SoftwareModule updateSoftwareModule(final SoftwareModuleUpdate u) { final GenericSoftwareModuleUpdate update = (GenericSoftwareModuleUpdate) u; @@ -133,8 +130,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public SoftwareModuleType updateSoftwareModuleType(final SoftwareModuleTypeUpdate u) { final GenericSoftwareModuleTypeUpdate update = (GenericSoftwareModuleTypeUpdate) u; @@ -148,8 +144,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public SoftwareModule createSoftwareModule(final SoftwareModuleCreate c) { final JpaSoftwareModuleCreate create = (JpaSoftwareModuleCreate) c; @@ -157,8 +152,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List createSoftwareModule(final Collection swModules) { return swModules.stream().map(this::createSoftwareModule).collect(Collectors.toList()); } @@ -230,8 +224,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteSoftwareModules(final Collection ids) { final List swModulesToDelete = softwareModuleRepository.findByIdIn(ids); @@ -489,8 +482,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public SoftwareModuleType createSoftwareModuleType(final SoftwareModuleTypeCreate c) { final JpaSoftwareModuleTypeCreate create = (JpaSoftwareModuleTypeCreate) c; @@ -498,8 +490,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteSoftwareModuleType(final Long typeId) { final JpaSoftwareModuleType toDelete = softwareModuleTypeRepository.findById(typeId) .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleType.class, typeId)); @@ -523,8 +514,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public SoftwareModuleMetadata createSoftwareModuleMetadata(final Long moduleId, final MetaData md) { checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, md); @@ -540,8 +530,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public List createSoftwareModuleMetadata(final Long moduleId, final Collection md) { md.forEach(meta -> checkAndThrowAlreadyIfSoftwareModuleMetadataExists(moduleId, meta)); @@ -555,8 +544,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public SoftwareModuleMetadata updateSoftwareModuleMetadata(final Long moduleId, final MetaData md) { // check if exists otherwise throw entity not found exception @@ -600,8 +588,7 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public void deleteSoftwareModuleMetadata(final Long moduleId, final String key) { final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) findSoftwareModuleMetadata(moduleId, key) .orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, moduleId, key)); @@ -665,15 +652,13 @@ public class JpaSoftwareManagement implements SoftwareManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteSoftwareModule(final Long moduleId) { deleteSoftwareModules(Sets.newHashSet(moduleId)); } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List createSoftwareModuleType(final Collection creates) { return creates.stream().map(this::createSoftwareModuleType).collect(Collectors.toList()); } 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 df103c9ea..ca7862715 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 @@ -32,10 +32,8 @@ import org.eclipse.persistence.config.PersistenceUnitProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.interceptor.KeyGenerator; -import org.springframework.data.jpa.repository.Modifying; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.DefaultTransactionDefinition; @@ -46,7 +44,7 @@ import org.springframework.validation.annotation.Validated; * JPA implementation of {@link SystemManagement}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, SystemManagement { @Autowired @@ -152,8 +150,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying public TenantMetaData getTenantMetadata(final String tenant) { final TenantMetaData result = tenantMetaDataRepository.findByTenantIgnoreCase(tenant); // Create if it does not exist @@ -188,11 +184,11 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst def.setName("initial-tenant-creation"); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); def.setReadOnly(false); - def.setIsolationLevel(Isolation.READ_UNCOMMITTED.value()); - return systemSecurityContext.runAsSystemAsTenant( - () -> new TransactionTemplate(txManager, def).execute(status -> tenantMetaDataRepository - .save(new JpaTenantMetaData(createStandardSoftwareDataSetup(), tenant))), - tenant); + return systemSecurityContext + .runAsSystemAsTenant(() -> new TransactionTemplate(txManager, def).execute(status -> { + final DistributionSetType defaultDsType = createStandardSoftwareDataSetup(); + return tenantMetaDataRepository.save(new JpaTenantMetaData(defaultDsType, tenant)); + }), tenant); } @Override @@ -201,8 +197,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public void deleteTenant(final String tenant) { cacheManager.evictCaches(tenant); tenantAware.runAsTenant(tenant, () -> { @@ -223,8 +218,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying public TenantMetaData getTenantMetadata() { if (tenantAware.getCurrentTenant() == null) { throw new IllegalStateException("Tenant not set"); @@ -235,17 +228,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst @Override @Cacheable(value = "currentTenant", keyGenerator = "currentTenantKeyGenerator", cacheManager = "directCacheManager", unless = "#result == null") - // set transaction to not supported, due we call this in - // BaseEntity#prePersist methods - // and it seems that JPA committing the transaction when executing this - // transactional method, - // which then leads that the BaseEntity#prePersist is called again to - // persist the un-persisted - // entity and we landing again in the #currentTenant() method - // suspend the transaction here to do a read-request against the medata - // table, when the current - // tenant is not cached anyway already. - @Transactional(propagation = Propagation.NOT_SUPPORTED, isolation = Isolation.READ_UNCOMMITTED) public String currentTenant() { final String initialTenantCreation = currentTenantCacheKeyGenerator.getCreateInitialTenant().get(); if (initialTenantCreation == null) { @@ -257,8 +239,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public TenantMetaData updateTenantMetadata(final Long defaultDsType) { final JpaTenantMetaData data = (JpaTenantMetaData) getTenantMetadata(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTagManagement.java index 091ddf66a..7665bff43 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTagManagement.java @@ -19,7 +19,6 @@ import org.eclipse.hawkbit.repository.TagManagement; import org.eclipse.hawkbit.repository.builder.GenericTagUpdate; import org.eclipse.hawkbit.repository.builder.TagCreate; import org.eclipse.hawkbit.repository.builder.TagUpdate; -import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.builder.JpaTagCreate; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; @@ -34,8 +33,6 @@ 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.repository.Modifying; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -43,7 +40,7 @@ import org.springframework.validation.annotation.Validated; * JP>A implementation of {@link TagManagement}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaTagManagement implements TagManagement { @@ -68,22 +65,15 @@ public class JpaTagManagement implements TagManagement { } @Override - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public TargetTag createTargetTag(final TagCreate c) { final JpaTagCreate create = (JpaTagCreate) c; - final JpaTargetTag targetTag = create.buildTargetTag(); - - if (findTargetTag(targetTag.getName()).isPresent()) { - throw new EntityAlreadyExistsException(); - } - - return targetTagRepository.save(targetTag); + return targetTagRepository.save(create.buildTargetTag()); } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List createTargetTags(final Collection tt) { @SuppressWarnings({ "unchecked", "rawtypes" }) final Collection targetTags = (Collection) tt; @@ -93,8 +83,7 @@ public class JpaTagManagement implements TagManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteTargetTag(final String targetTagName) { final TargetTag tag = targetTagRepository.findByNameEquals(targetTagName) .orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagName)); @@ -131,8 +120,7 @@ public class JpaTagManagement implements TagManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public TargetTag updateTargetTag(final TagUpdate u) { final GenericTagUpdate update = (GenericTagUpdate) u; @@ -147,8 +135,8 @@ public class JpaTagManagement implements TagManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + + @Transactional public DistributionSetTag updateDistributionSetTag(final TagUpdate u) { final GenericTagUpdate update = (GenericTagUpdate) u; @@ -168,23 +156,14 @@ public class JpaTagManagement implements TagManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public DistributionSetTag createDistributionSetTag(final TagCreate c) { final JpaTagCreate create = (JpaTagCreate) c; - - final JpaDistributionSetTag distributionSetTag = create.buildDistributionSetTag(); - - if (distributionSetTagRepository.findByNameEquals(distributionSetTag.getName()).isPresent()) { - throw new EntityAlreadyExistsException(); - } - - return distributionSetTagRepository.save(distributionSetTag); + return distributionSetTagRepository.save(create.buildDistributionSetTag()); } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List createDistributionSetTags(final Collection dst) { @SuppressWarnings({ "rawtypes", "unchecked" }) @@ -196,8 +175,7 @@ public class JpaTagManagement implements TagManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteDistributionSetTag(final String tagName) { final DistributionSetTag tag = distributionSetTagRepository.findByNameEquals(tagName) .orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, tagName)); 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 c81847855..93f9a0220 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 @@ -20,7 +20,6 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.builder.GenericTargetFilterQueryUpdate; import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate; import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate; -import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; @@ -37,8 +36,6 @@ 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.data.jpa.repository.Modifying; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -49,7 +46,7 @@ import com.google.common.collect.Lists; * JPA implementation of {@link TargetFilterQueryManagement}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement { @@ -68,23 +65,16 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme this.distributionSetManagement = distributionSetManagement; } - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional @Override public TargetFilterQuery createTargetFilterQuery(final TargetFilterQueryCreate c) { final JpaTargetFilterQueryCreate create = (JpaTargetFilterQueryCreate) c; - final JpaTargetFilterQuery query = create.build(); - - if (targetFilterQueryRepository.findByName(query.getName()).isPresent()) { - throw new EntityAlreadyExistsException(query.getName()); - } - return targetFilterQueryRepository.save(query); + return targetFilterQueryRepository.save(create.build()); } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteTargetFilterQuery(final Long targetFilterQueryId) { findTargetFilterQueryById(targetFilterQueryId) .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); @@ -178,8 +168,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public TargetFilterQuery updateTargetFilterQuery(final TargetFilterQueryUpdate u) { final GenericTargetFilterQueryUpdate update = (GenericTargetFilterQueryUpdate) u; @@ -192,8 +181,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public TargetFilterQuery updateTargetFilterQueryAutoAssignDS(final Long queryId, final Long dsId) { final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(queryId); 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 31e1b2fbd..6858c2e98 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 @@ -32,7 +32,6 @@ import org.eclipse.hawkbit.repository.TimestampCalculator; import org.eclipse.hawkbit.repository.builder.TargetCreate; import org.eclipse.hawkbit.repository.builder.TargetUpdate; import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent; -import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetCreate; import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetUpdate; @@ -61,8 +60,6 @@ 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.data.jpa.repository.Modifying; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -72,7 +69,7 @@ import com.google.common.collect.Lists; * JPA implementation of {@link TargetManagement}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaTargetManagement implements TargetManagement { @@ -116,8 +113,8 @@ public class JpaTargetManagement implements TargetManagement { @Override public List findTargetByControllerID(final Collection controllerIDs) { - return Collections.unmodifiableList(targetRepository - .findAll(TargetSpecifications.byControllerIdWithStatusAndAssignedInJoin(controllerIDs))); + return Collections.unmodifiableList( + targetRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs))); } @Override @@ -150,8 +147,7 @@ public class JpaTargetManagement implements TargetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Target updateTarget(final TargetUpdate u) { final JpaTargetUpdate update = (JpaTargetUpdate) u; @@ -167,8 +163,7 @@ public class JpaTargetManagement implements TargetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteTargets(final Collection targetIDs) { final List targets = targetRepository.findAll(targetIDs); @@ -184,8 +179,7 @@ public class JpaTargetManagement implements TargetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public void deleteTarget(final String controllerID) { final Target target = targetRepository.findByControllerId(controllerID) .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerID)); @@ -324,13 +318,12 @@ public class JpaTargetManagement implements TargetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public TargetTagAssignmentResult toggleTagAssignment(final Collection controllerIds, final String tagName) { final TargetTag tag = targetTagRepository.findByNameEquals(tagName) .orElseThrow(() -> new EntityNotFoundException(TargetTag.class, tagName)); final List allTargets = targetRepository - .findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(controllerIds)); + .findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds)); if (allTargets.size() < controllerIds.size()) { throw new EntityNotFoundException(Target.class, controllerIds, @@ -362,11 +355,10 @@ public class JpaTargetManagement implements TargetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List assignTag(final Collection controllerIds, final Long tagId) { final List allTargets = targetRepository - .findAll(TargetSpecifications.byControllerIdWithStatusAndTagsInJoin(controllerIds)); + .findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds)); if (allTargets.size() < controllerIds.size()) { throw new EntityNotFoundException(Target.class, controllerIds, @@ -392,8 +384,7 @@ public class JpaTargetManagement implements TargetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List unAssignAllTargetsByTag(final Long targetTagId) { final TargetTag tag = targetTagRepository.findById(targetTagId) @@ -407,8 +398,7 @@ public class JpaTargetManagement implements TargetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Target unAssignTag(final String controllerID, final Long targetTagId) { final Target target = targetRepository.findByControllerId(controllerID) .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerID)); @@ -553,23 +543,14 @@ public class JpaTargetManagement implements TargetManagement { } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public Target createTarget(final TargetCreate c) { final JpaTargetCreate create = (JpaTargetCreate) c; - - final JpaTarget target = create.build(); - - if (targetRepository.existsByControllerId(target.getControllerId())) { - throw new EntityAlreadyExistsException(); - } - - return targetRepository.save(target); + return targetRepository.save(create.build()); } @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional public List createTargets(final Collection targets) { return targets.stream().map(this::createTarget).collect(Collectors.toList()); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantConfigurationManagement.java index e24bd3506..4c5e93702 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantConfigurationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantConfigurationManagement.java @@ -23,15 +23,13 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.context.ApplicationContext; import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; /** * Central tenant configuration management operations of the SP server. */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) @Validated public class JpaTenantConfigurationManagement implements TenantConfigurationManagement { @@ -123,8 +121,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana @Override @CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName") - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public TenantConfigurationValue addOrUpdateConfiguration( final String configurationKeyName, final T value) { @@ -162,8 +159,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana @Override @CacheEvict(value = "tenantConfiguration", key = "#configurationKeyName") - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - @Modifying + @Transactional public void deleteConfiguration(final String configurationKeyName) { tenantConfigurationRepository.deleteByKey(configurationKeyName); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantStatsManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantStatsManagement.java index 10d760b1c..321dcdb3c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantStatsManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantStatsManagement.java @@ -12,7 +12,6 @@ import org.eclipse.hawkbit.repository.TenantStatsManagement; import org.eclipse.hawkbit.repository.report.model.TenantUsage; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -37,7 +36,7 @@ public class JpaTenantStatsManagement implements TenantStatsManagement { private TenantAware tenantAware; @Override - @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_UNCOMMITTED) + @Transactional(propagation = Propagation.REQUIRES_NEW) public TenantUsage getStatsOfTenant() { final String tenant = tenantAware.getCurrentTenant(); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java index ef8463c94..419984128 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/LocalArtifactRepository.java @@ -18,14 +18,13 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link Artifact} repository. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface LocalArtifactRepository extends BaseEntityRepository { /** 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 a75c3bc1f..27641ac60 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 @@ -276,7 +276,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { @Override protected Map getVendorProperties() { - final Map properties = Maps.newHashMapWithExpectedSize(4); + final Map properties = Maps.newHashMapWithExpectedSize(5); // Turn off dynamic weaving to disable LTW lookup in static weaving mode properties.put("eclipselink.weaving", "false"); // needed for reports @@ -285,6 +285,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { properties.put("eclipselink.ddl-generation", "none"); // Embeed into hawkBit logging properties.put("eclipselink.logging.logger", "JavaLogger"); + // Ensure that we flush only at the end of the transaction + properties.put("eclipselink.persistence-context.flush-mode", "COMMIT"); return properties; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java index dcfc9d528..e16545782 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutGroupRepository.java @@ -21,13 +21,12 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * The repository interface for the {@link RolloutGroup} model. */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface RolloutGroupRepository extends BaseEntityRepository, JpaSpecificationExecutor { @@ -119,7 +118,7 @@ public interface RolloutGroupRepository * the status of the rolloutgroups */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional @Query("UPDATE JpaRolloutGroup g SET g.status = :status WHERE g.parent = :parent") void setStatusForCildren(@Param("status") RolloutGroupStatus status, @Param("parent") RolloutGroup parent); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutRepository.java index 46b7be916..0e4efb09e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutRepository.java @@ -17,13 +17,12 @@ import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * The repository interface for the {@link Rollout} model. */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface RolloutRepository extends BaseEntityRepository, JpaSpecificationExecutor { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutTargetGroupRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutTargetGroupRepository.java index a4fc68541..475f4f89a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutTargetGroupRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RolloutTargetGroupRepository.java @@ -13,14 +13,13 @@ import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup; import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroupId; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.CrudRepository; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * Spring data repository for {@link RolloutTargetGroup}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface RolloutTargetGroupRepository extends CrudRepository, JpaSpecificationExecutor { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java index 702093599..f30c8b33e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleMetadataRepository.java @@ -15,14 +15,13 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link SoftwareModuleMetadata} repository. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface SoftwareModuleMetadataRepository extends PagingAndSortingRepository, JpaSpecificationExecutor { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleRepository.java index 70e45b2a1..045b890d6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleRepository.java @@ -23,14 +23,13 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link SoftwareModule} repository. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface SoftwareModuleRepository extends BaseEntityRepository, JpaSpecificationExecutor { @@ -70,7 +69,7 @@ public interface SoftwareModuleRepository * */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional @Query("UPDATE JpaSoftwareModule b SET b.deleted = 1, b.lastModifiedAt = :lastModifiedAt, b.lastModifiedBy = :lastModifiedBy WHERE b.id IN :ids") void deleteSoftwareModule(@Param("lastModifiedAt") Long modifiedAt, @Param("lastModifiedBy") String modifiedBy, @Param("ids") final Long... ids); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleTypeRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleTypeRepository.java index 9d2a3ad94..75382ea58 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleTypeRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/SoftwareModuleTypeRepository.java @@ -18,14 +18,13 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * Repository for {@link SoftwareModuleType}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface SoftwareModuleTypeRepository extends BaseEntityRepository, JpaSpecificationExecutor { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryRepository.java index ec13a75c0..6be600621 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetFilterQueryRepository.java @@ -17,14 +17,13 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * Spring data repositories for {@link TargetFilterQuery}s. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface TargetFilterQueryRepository extends BaseEntityRepository, JpaSpecificationExecutor { @@ -49,7 +48,7 @@ public interface TargetFilterQueryRepository * distribution set ids to be set to null */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional @Query("update JpaTargetFilterQuery d set d.autoAssignDistributionSet = NULL where d.autoAssignDistributionSet in :ids") void unsetAutoAssignDistributionSet(@Param("ids") Long... dsIds); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetRepository.java index 7e5a9c5eb..7feb367d3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetRepository.java @@ -25,14 +25,13 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link Target} repository. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface TargetRepository extends BaseEntityRepository, JpaSpecificationExecutor { /** @@ -50,7 +49,7 @@ public interface TargetRepository extends BaseEntityRepository, * to update */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional @Query("UPDATE JpaTarget t SET t.assignedDistributionSet = :set, t.lastModifiedAt = :lastModifiedAt, t.lastModifiedBy = :lastModifiedBy, t.updateStatus = :status WHERE t.id IN :targets") void setAssignedDistributionSetAndUpdateStatus(@Param("status") TargetUpdateStatus status, @Param("set") JpaDistributionSet set, @Param("lastModifiedAt") Long modifiedAt, @@ -85,7 +84,7 @@ public interface TargetRepository extends BaseEntityRepository, * to be deleted */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 @Query("DELETE FROM JpaTarget t WHERE t.id IN ?1") void deleteByIdIn(final Collection targetIDs); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetTagRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetTagRepository.java index 9c232c756..7caafdffc 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetTagRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetTagRepository.java @@ -15,14 +15,13 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; import org.eclipse.hawkbit.repository.model.TargetTag; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * {@link TargetTag} repository. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface TargetTagRepository extends BaseEntityRepository, JpaSpecificationExecutor { @@ -34,7 +33,7 @@ public interface TargetTagRepository * @return 1 if tag was deleted */ @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) + @Transactional Long deleteByName(String tagName); /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantConfigurationRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantConfigurationRepository.java index 4649d00fe..50165a11c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantConfigurationRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantConfigurationRepository.java @@ -10,14 +10,13 @@ package org.eclipse.hawkbit.repository.jpa; import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration; import org.eclipse.hawkbit.repository.model.TenantConfiguration; -import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** * The spring-data repository for the entity {@link TenantConfiguration}. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface TenantConfigurationRepository extends BaseEntityRepository { /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantMetaDataRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantMetaDataRepository.java index b5de8f112..d15ee242d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantMetaDataRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TenantMetaDataRepository.java @@ -12,15 +12,16 @@ import java.util.List; import org.eclipse.hawkbit.repository.jpa.model.JpaTenantMetaData; import org.eclipse.hawkbit.repository.model.TenantMetaData; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * repository for operations on {@link TenantMetaData} entity. * */ -@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) +@Transactional(readOnly = true) public interface TenantMetaDataRepository extends PagingAndSortingRepository { /** @@ -30,6 +31,7 @@ public interface TenantMetaDataRepository extends PagingAndSortingRepositorynull */ + @Transactional(propagation = Propagation.REQUIRES_NEW) TenantMetaData findByTenantIgnoreCase(String tenant); @Override @@ -38,6 +40,8 @@ public interface TenantMetaDataRepository extends PagingAndSortingRepository isDeleted(final Boolean isDeleted) { - return (root, query, cb) -> cb.equal(root. get(JpaRollout_.deleted), isDeleted); + public static Specification isDeletedWithDistributionSet(final Boolean isDeleted) { + return (root, query, cb) -> { + + final Predicate predicate = cb.equal(root. get(JpaRollout_.deleted), isDeleted); + root.fetch(JpaRollout_.distributionSet); + return predicate; + }; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java index 05957166f..2f3f2aa73 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java @@ -50,15 +50,14 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s including - * {@link TargetTag}s and {@link TargetStatus}. + * {@link TargetTag}s. * * @param controllerIDs * to search for * * @return the {@link Target} {@link Specification} */ - public static Specification byControllerIdWithStatusAndTagsInJoin( - final Collection controllerIDs) { + public static Specification byControllerIdWithTagsInJoin(final Collection controllerIDs) { return (targetRoot, query, cb) -> { final Predicate predicate = targetRoot.get(JpaTarget_.controllerId).in(controllerIDs); targetRoot.fetch(JpaTarget_.tags, JoinType.LEFT); @@ -68,16 +67,15 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s including { - * {@link TargetStatus}. + * {@link Specification} for retrieving {@link JpaTarget}s including + * {@link JpaTarget#getAssignedDistributionSet()}. * * @param controllerIDs * to search for * * @return the {@link Target} {@link Specification} */ - public static Specification byControllerIdWithStatusAndAssignedInJoin( - final Collection controllerIDs) { + public static Specification byControllerIdWithAssignedDsInJoin(final Collection controllerIDs) { return (targetRoot, query, cb) -> { final Predicate predicate = targetRoot.get(JpaTarget_.controllerId).in(controllerIDs); @@ -92,9 +90,7 @@ public final class TargetSpecifications { * * @param updateStatus * to be filtered on - * @param fetch - * {@code true} to fetch the {@link TargetInfo} otherwise only - * join it. + * * @return the {@link Target} {@link Specification} */ public static Specification hasTargetUpdateStatus(final Collection updateStatus) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_1__target_filter_query_UQ___H2.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_1__target_filter_query_UQ___H2.sql new file mode 100644 index 000000000..f494313a8 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/H2/V1_11_1__target_filter_query_UQ___H2.sql @@ -0,0 +1,2 @@ + alter table sp_target_filter_query + add constraint uk_tenant_custom_filter_name unique (name, tenant); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_1__target_filter_query_UQ___MYSQL.sql b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_1__target_filter_query_UQ___MYSQL.sql new file mode 100644 index 000000000..f494313a8 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/resources/db/migration/MYSQL/V1_11_1__target_filter_query_UQ___MYSQL.sql @@ -0,0 +1,2 @@ + alter table sp_target_filter_query + add constraint uk_tenant_custom_filter_name unique (name, tenant); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java index e57ac909f..2b7344c7b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/AbstractJpaIntegrationTest.java @@ -97,7 +97,7 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest @Autowired protected TenantConfigurationProperties tenantConfigurationProperties; - @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED) + @Transactional(readOnly = true) protected List findActionsByRolloutAndStatus(final Rollout rollout, final Action.Status actionStatus) { return Lists.newArrayList(actionRepository.findByRolloutIdAndStatus(pageReq, rollout.getId(), actionStatus)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java index bfcd52552..6e2e162d2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DistributionSetManagementTest.java @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.repository.jpa; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.ArrayList; @@ -327,6 +328,17 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest { } + @Test + @Description("Verifies that a DS cannot be created if another DS with same name and version exists.") + public void createDistributionSetWithDuplicateNameAndVersionFails() { + distributionSetManagement + .createDistributionSet(entityFactory.distributionSet().create().name("newtypesoft").version("1")); + + assertThatExceptionOfType(EntityAlreadyExistsException.class).isThrownBy(() -> distributionSetManagement + .createDistributionSet(entityFactory.distributionSet().create().name("newtypesoft").version("1"))); + + } + @Test @Description("Verifies that multiple DS are of default type if not specified explicitly at creation time.") public void createMultipleDistributionSetsWithImplicitType() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java index 5a27e732f..805af5da8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java @@ -133,7 +133,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { + " by means of throwing EntityNotFoundException.") @ExpectEvents({ @Expect(type = RolloutDeletedEvent.class, count = 0), @Expect(type = RolloutGroupCreatedEvent.class, count = 10), - @Expect(type = RolloutGroupUpdatedEvent.class, count = 20), + @Expect(type = RolloutGroupUpdatedEvent.class, count = 10), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = RolloutUpdatedEvent.class, count = 1), @@ -143,12 +143,6 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { verifyThrownExceptionBy(() -> rolloutManagement.deleteRollout(NOT_EXIST_IDL), "Rollout"); - verifyThrownExceptionBy(() -> rolloutManagement.getFinishedPercentForRunningGroup(NOT_EXIST_IDL, NOT_EXIST_IDL), - "Rollout"); - verifyThrownExceptionBy( - () -> rolloutManagement.getFinishedPercentForRunningGroup(createdRollout.getId(), NOT_EXIST_IDL), - "RolloutGroup"); - verifyThrownExceptionBy(() -> rolloutManagement.pauseRollout(NOT_EXIST_IDL), "Rollout"); verifyThrownExceptionBy(() -> rolloutManagement.resumeRollout(NOT_EXIST_IDL), "Rollout"); verifyThrownExceptionBy(() -> rolloutManagement.startRollout(NOT_EXIST_IDL), "Rollout"); @@ -1005,23 +999,24 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { rolloutManagement.handleRollouts(); myRollout = rolloutManagement.findRolloutById(myRollout.getId()).get(); - float percent = rolloutManagement.getFinishedPercentForRunningGroup(myRollout.getId(), - myRollout.getRolloutGroups().get(0).getId()); + float percent = rolloutGroupManagement + .findRolloutGroupWithDetailedStatus(myRollout.getRolloutGroups().get(0).getId()).get() + .getTotalTargetCountStatus().getFinishedPercent(); assertThat(percent).isEqualTo(40); changeStatusForRunningActions(myRollout, Status.FINISHED, 3); rolloutManagement.handleRollouts(); - percent = rolloutManagement.getFinishedPercentForRunningGroup(myRollout.getId(), - myRollout.getRolloutGroups().get(0).getId()); + percent = rolloutGroupManagement.findRolloutGroupWithDetailedStatus(myRollout.getRolloutGroups().get(0).getId()) + .get().getTotalTargetCountStatus().getFinishedPercent(); assertThat(percent).isEqualTo(100); changeStatusForRunningActions(myRollout, Status.FINISHED, 4); changeStatusForAllRunningActions(myRollout, Status.ERROR); rolloutManagement.handleRollouts(); - percent = rolloutManagement.getFinishedPercentForRunningGroup(myRollout.getId(), - myRollout.getRolloutGroups().get(1).getId()); + percent = rolloutGroupManagement.findRolloutGroupWithDetailedStatus(myRollout.getRolloutGroups().get(1).getId()) + .get().getTotalTargetCountStatus().getFinishedPercent(); assertThat(percent).isEqualTo(80); } @@ -1465,7 +1460,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { @Expect(type = TargetCreatedEvent.class, count = 25), @Expect(type = RolloutUpdatedEvent.class, count = 2), @Expect(type = RolloutGroupCreatedEvent.class, count = 5), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), - @Expect(type = RolloutGroupUpdatedEvent.class, count = 10) }) + @Expect(type = RolloutGroupUpdatedEvent.class, count = 5) }) public void deleteRolloutWhichHasNeverStartedIsHardDeleted() { final int amountTargetsForRollout = 10; final int amountOtherTargets = 15; @@ -1488,7 +1483,7 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest { @Test @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 3), - @Expect(type = RolloutGroupUpdatedEvent.class, count = 16), + @Expect(type = RolloutGroupUpdatedEvent.class, count = 10), @Expect(type = RolloutUpdatedEvent.class, count = 6), @Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = TargetCreatedEvent.class, count = 25), @Expect(type = TargetUpdatedEvent.class, count = 2), diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java index d27a34800..2a8f51d11 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.repository.jpa; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; @@ -192,6 +193,16 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest { } } + @Test + @Description("Verify that a target with same controller ID than another device cannot be created.") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) }) + public void createTargetThatViolatesUniqueConstraintFails() { + targetManagement.createTarget(entityFactory.target().create().controllerId("123")); + + assertThatExceptionOfType(EntityAlreadyExistsException.class) + .isThrownBy(() -> targetManagement.createTarget(entityFactory.target().create().controllerId("123"))); + } + @Test @Description("Verify that a target with whitespaces in controller id cannot be created") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) }) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/application-test.properties b/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/application-test.properties index c630197c2..9cf054b49 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/application-test.properties +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/resources/application-test.properties @@ -9,6 +9,7 @@ logging.level.=INFO logging.level.org.eclipse.persistence=ERROR +logging.level.org.eclipse.hawkbit.repository.test.matcher.EventVerifier=ERROR spring.data.mongodb.uri=mongodb://localhost/spArtifactRepository${random.value} spring.data.mongodb.port=28017 @@ -22,6 +23,7 @@ hawkbit.server.security.dos.maxAttributeEntriesPerTarget=10 spring.jpa.database=H2 spring.datasource.url=jdbc:h2:mem:sp-db;DB_CLOSE_ON_EXIT=FALSE spring.datasource.driverClassName=org.h2.Driver +spring.datasource.tomcat.default-auto-commit=false spring.datasource.username=sa spring.datasource.password=sa diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/matcher/EventVerifier.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/matcher/EventVerifier.java index 06d06f21e..f78943cdb 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/matcher/EventVerifier.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/matcher/EventVerifier.java @@ -23,6 +23,8 @@ import org.junit.Assert; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cloud.bus.event.RemoteApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; @@ -38,6 +40,7 @@ import com.jayway.awaitility.core.ConditionTimeoutException; * Test rule to setup and verify the event count for a method. */ public class EventVerifier implements TestRule { + private static final Logger LOGGER = LoggerFactory.getLogger(EventVerifier.class); private EventCaptor eventCaptor; @@ -116,6 +119,7 @@ public class EventVerifier implements TestRule { @Override public void onApplicationEvent(final RemoteApplicationEvent event) { + LOGGER.debug("Received event {}", event.getClass().getSimpleName()); capturedEvents.add(event.getClass()); } 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 7bd329c72..62a0c4913 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 @@ -270,7 +270,7 @@ public abstract class AbstractIntegrationTest implements EnvironmentAware { @Before public void before() throws Exception { mvc = createMvcWebAppContext().build(); - final String description = "Updated description to have lastmodified available in tests"; + final String description = "Updated description."; osType = securityRule .runAsPrivileged(() -> testdataFactory.findOrCreateSoftwareModuleType(TestdataFactory.SM_TYPE_OS)); diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/JpaTestRepositoryManagement.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/JpaTestRepositoryManagement.java index b4e3b49dd..149050be0 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/JpaTestRepositoryManagement.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/JpaTestRepositoryManagement.java @@ -15,7 +15,6 @@ import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.transaction.annotation.Transactional; public class JpaTestRepositoryManagement implements TestRepositoryManagement { @@ -45,13 +44,11 @@ public class JpaTestRepositoryManagement implements TestRepositoryManagement { } @Override - @Transactional public void clearTestRepository() { deleteAllRepos(); cacheManager.getDirectCacheNames().forEach(name -> cacheManager.getDirectCache(name).clear()); } - @Transactional public void deleteAllRepos() { final List tenants = systemSecurityContext.runAsSystem(() -> systemManagement.findTenants()); tenants.forEach(tenant -> { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/ProxyRollout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/ProxyRollout.java index 1b045000c..4124d90e9 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/ProxyRollout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/ProxyRollout.java @@ -8,11 +8,7 @@ */ package org.eclipse.hawkbit.ui.rollout.rollout; -import java.util.Set; - -import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; -import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; @@ -30,99 +26,24 @@ public class ProxyRollout { private String modifiedDate; - private Integer numberOfGroups; + private int numberOfGroups; private Boolean isActionRecieved = Boolean.FALSE; - private Boolean isRequiredMigrationStep = Boolean.FALSE; - private String totalTargetsCount; private RolloutRendererData rolloutRendererData; - private String discription; - - private String type; - - private Set swModules; - private Long id; private String name; private String version; private String description; - private DistributionSet distributionSet; private String createdBy; private String lastModifiedBy; private long forcedTime; private RolloutStatus status; private TotalTargetCountStatus totalTargetCountStatus; - /** - * @return the isRequiredMigrationStep - */ - - public Boolean getIsRequiredMigrationStep() { - return isRequiredMigrationStep; - } - - /** - * @param isRequiredMigrationStep - * the isRequiredMigrationStep to set - */ - - public void setIsRequiredMigrationStep(final Boolean isRequiredMigrationStep) { - this.isRequiredMigrationStep = isRequiredMigrationStep; - } - - /** - * @return the discription - */ - - public String getDiscription() { - return discription; - } - - /** - * @param discription - * the discription to set - */ - - public void setDiscription(final String discription) { - this.discription = discription; - } - - /** - * @return the type - */ - public String getType() { - return type; - } - - /** - * @param type - * the type to set - */ - - public void setType(final String type) { - this.type = type; - } - - /** - * - * @return the Set of Software modules - */ - public Set getSwModules() { - return swModules; - } - - /** - * @param swModules - * Set to set - */ - public void setSwModules(final Set swModules) { - this.swModules = swModules; - } - public RolloutRendererData getRolloutRendererData() { return rolloutRendererData; } @@ -149,7 +70,7 @@ public class ProxyRollout { /** * @return the numberOfGroups */ - public Integer getNumberOfGroups() { + public int getNumberOfGroups() { return numberOfGroups; } @@ -157,7 +78,7 @@ public class ProxyRollout { * @param numberOfGroups * the numberOfGroups to set */ - public void setNumberOfGroups(final Integer numberOfGroups) { + public void setNumberOfGroups(final int numberOfGroups) { this.numberOfGroups = numberOfGroups; } @@ -257,14 +178,6 @@ public class ProxyRollout { this.description = description; } - public DistributionSet getDistributionSet() { - return distributionSet; - } - - public void setDistributionSet(final DistributionSet distributionSet) { - this.distributionSet = distributionSet; - } - public String getCreatedBy() { return createdBy; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutBeanQuery.java index ec21ba46f..d06e84cea 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutBeanQuery.java @@ -10,9 +10,9 @@ package org.eclipse.hawkbit.ui.rollout.rollout; import static org.apache.commons.lang3.ArrayUtils.isEmpty; -import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -104,36 +104,30 @@ public class RolloutBeanQuery extends AbstractBeanQuery { } private static List getProxyRolloutList(final Slice rolloutBeans) { - final List proxyRolloutList = new ArrayList<>(); - for (final Rollout rollout : rolloutBeans) { - final ProxyRollout proxyRollout = new ProxyRollout(); - proxyRollout.setName(rollout.getName()); - proxyRollout.setDescription(rollout.getDescription()); - final DistributionSet distributionSet = rollout.getDistributionSet(); - proxyRollout.setDistributionSetNameVersion( - HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(), distributionSet.getVersion())); - proxyRollout.setDistributionSet(distributionSet); - proxyRollout.setNumberOfGroups(Integer.valueOf(rollout.getRolloutGroups().size())); - proxyRollout.setCreatedDate(SPDateTimeUtil.getFormattedDate(rollout.getCreatedAt())); - proxyRollout.setModifiedDate(SPDateTimeUtil.getFormattedDate(rollout.getLastModifiedAt())); - proxyRollout.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(rollout)); - proxyRollout.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(rollout)); - proxyRollout.setForcedTime(rollout.getForcedTime()); - proxyRollout.setId(rollout.getId()); - proxyRollout.setStatus(rollout.getStatus()); - proxyRollout - .setRolloutRendererData(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString())); + return rolloutBeans.getContent().stream().map(RolloutBeanQuery::createProxy).collect(Collectors.toList()); + } - final TotalTargetCountStatus totalTargetCountActionStatus = rollout.getTotalTargetCountStatus(); - proxyRollout.setTotalTargetCountStatus(totalTargetCountActionStatus); - proxyRollout.setTotalTargetsCount(String.valueOf(rollout.getTotalTargets())); - proxyRollout.setType(distributionSet.getType().getName()); - proxyRollout.setIsRequiredMigrationStep(distributionSet.isRequiredMigrationStep()); - proxyRollout.setSwModules(distributionSet.getModules()); + private static ProxyRollout createProxy(final Rollout rollout) { + final ProxyRollout proxyRollout = new ProxyRollout(); + proxyRollout.setName(rollout.getName()); + proxyRollout.setDescription(rollout.getDescription()); + final DistributionSet distributionSet = rollout.getDistributionSet(); + proxyRollout.setDistributionSetNameVersion( + HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(), distributionSet.getVersion())); + proxyRollout.setNumberOfGroups(rollout.getRolloutGroupsCreated()); + proxyRollout.setCreatedDate(SPDateTimeUtil.getFormattedDate(rollout.getCreatedAt())); + proxyRollout.setModifiedDate(SPDateTimeUtil.getFormattedDate(rollout.getLastModifiedAt())); + proxyRollout.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(rollout)); + proxyRollout.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(rollout)); + proxyRollout.setForcedTime(rollout.getForcedTime()); + proxyRollout.setId(rollout.getId()); + proxyRollout.setStatus(rollout.getStatus()); + proxyRollout.setRolloutRendererData(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString())); - proxyRolloutList.add(proxyRollout); - } - return proxyRolloutList; + final TotalTargetCountStatus totalTargetCountActionStatus = rollout.getTotalTargetCountStatus(); + proxyRollout.setTotalTargetCountStatus(totalTargetCountActionStatus); + proxyRollout.setTotalTargetsCount(String.valueOf(rollout.getTotalTargets())); + return proxyRollout; } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java index 1b788f757..cdd04a4b0 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java @@ -17,7 +17,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; -import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.eclipse.hawkbit.repository.EntityFactory; @@ -26,7 +25,6 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; -import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus.Status; import org.eclipse.hawkbit.ui.SpPermissionChecker; @@ -84,10 +82,6 @@ public class RolloutListGrid extends AbstractGrid { private static final String DELETE_OPTION = "Delete"; - private static final String DS_TYPE = "type"; - - private static final String SW_MODULES = "swModules"; - private static final String IS_REQUIRED_MIGRATION_STEP = "isRequiredMigrationStep"; private static final String ROLLOUT_RENDERER_DATA = "rolloutRendererData"; @@ -223,8 +217,6 @@ public class RolloutListGrid extends AbstractGrid { protected void addContainerProperties() { final LazyQueryContainer rolloutGridContainer = (LazyQueryContainer) getContainerDataSource(); rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, "", false, false); - rolloutGridContainer.addContainerProperty(DS_TYPE, String.class, null, false, false); - rolloutGridContainer.addContainerProperty(SW_MODULES, Set.class, null, false, false); rolloutGridContainer.addContainerProperty(ROLLOUT_RENDERER_DATA, RolloutRendererData.class, null, false, false); rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_DESC, String.class, null, false, false); rolloutGridContainer.addContainerProperty(IS_REQUIRED_MIGRATION_STEP, boolean.class, null, false, false); @@ -307,8 +299,6 @@ public class RolloutListGrid extends AbstractGrid { @Override protected void setColumnHeaderNames() { getColumn(ROLLOUT_RENDERER_DATA).setHeaderCaption(i18n.getMessage("header.name")); - getColumn(DS_TYPE).setHeaderCaption(i18n.getMessage("header.type")); - getColumn(SW_MODULES).setHeaderCaption(i18n.getMessage("header.swmodules")); getColumn(IS_REQUIRED_MIGRATION_STEP).setHeaderCaption(i18n.getMessage("header.migrations.step")); getColumn(SPUILabelDefinitions.VAR_DIST_NAME_VERSION) .setHeaderCaption(i18n.getMessage("header.distributionset")); @@ -362,8 +352,6 @@ public class RolloutListGrid extends AbstractGrid { final List columnList = new ArrayList<>(); columnList.add(ROLLOUT_RENDERER_DATA); columnList.add(SPUILabelDefinitions.VAR_DIST_NAME_VERSION); - columnList.add(DS_TYPE); - columnList.add(SW_MODULES); columnList.add(IS_REQUIRED_MIGRATION_STEP); columnList.add(SPUILabelDefinitions.VAR_STATUS); columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS); @@ -400,8 +388,6 @@ public class RolloutListGrid extends AbstractGrid { columnsToBeHidden.add(SPUILabelDefinitions.VAR_MODIFIED_BY); columnsToBeHidden.add(SPUILabelDefinitions.VAR_DESC); columnsToBeHidden.add(IS_REQUIRED_MIGRATION_STEP); - columnsToBeHidden.add(DS_TYPE); - columnsToBeHidden.add(SW_MODULES); for (final Object propertyId : columnsToBeHidden) { getColumn(propertyId).setHidden(true); } @@ -561,51 +547,11 @@ public class RolloutListGrid extends AbstractGrid { description = ((RolloutRendererData) cell.getProperty().getValue()).getName(); } else if (SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS.equals(cell.getPropertyId())) { description = getTooltip(((TotalTargetCountStatus) cell.getValue()).getStatusTotalCountMap()); - } else if (SPUILabelDefinitions.VAR_DIST_NAME_VERSION.equals(cell.getPropertyId())) { - description = getDSDetails(cell.getItem()); } return description; } - private static String getDSDetails(final Item rolloutItem) { - final StringBuilder swModuleNames = new StringBuilder(); - final StringBuilder swModuleVendors = new StringBuilder(); - @SuppressWarnings("unchecked") - final Set swModules = (Set) rolloutItem.getItemProperty(SW_MODULES).getValue(); - swModules.forEach(swModule -> { - swModuleNames.append(swModule.getName()); - swModuleNames.append(" , "); - swModuleVendors.append(swModule.getVendor()); - swModuleVendors.append(" , "); - }); - final StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(HawkbitCommonUtil.HTML_UL_OPEN_TAG); - stringBuilder.append(HawkbitCommonUtil.HTML_LI_OPEN_TAG); - stringBuilder.append(" DistributionSet Description : ") - .append((String) rolloutItem.getItemProperty(SPUILabelDefinitions.VAR_DESC).getValue()); - stringBuilder.append(HawkbitCommonUtil.HTML_LI_CLOSE_TAG); - stringBuilder.append(HawkbitCommonUtil.HTML_LI_OPEN_TAG); - stringBuilder.append(" DistributionSet Type : ") - .append((String) rolloutItem.getItemProperty(DS_TYPE).getValue()); - stringBuilder.append(HawkbitCommonUtil.HTML_LI_CLOSE_TAG); - stringBuilder.append(HawkbitCommonUtil.HTML_LI_OPEN_TAG); - stringBuilder.append("Required Migration step : ") - .append((boolean) rolloutItem.getItemProperty(IS_REQUIRED_MIGRATION_STEP).getValue() ? "Yes" : "No"); - stringBuilder.append(HawkbitCommonUtil.HTML_LI_CLOSE_TAG); - - stringBuilder.append(HawkbitCommonUtil.HTML_LI_OPEN_TAG); - stringBuilder.append("SoftWare Modules : ").append(swModuleNames.toString()); - stringBuilder.append(HawkbitCommonUtil.HTML_LI_CLOSE_TAG); - - stringBuilder.append(HawkbitCommonUtil.HTML_LI_OPEN_TAG); - stringBuilder.append("Vendor(s) : ").append(swModuleVendors.toString()); - stringBuilder.append(HawkbitCommonUtil.HTML_LI_CLOSE_TAG); - - stringBuilder.append(HawkbitCommonUtil.HTML_UL_CLOSE_TAG); - return stringBuilder.toString(); - } - private static class RollouStatusCellStyleGenerator implements CellStyleGenerator { private static final List DELETE_COPY_BUTTON_ENABLED = Arrays.asList(RolloutStatus.CREATING, diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupBeanQuery.java index 567004a78..939bdd725 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupBeanQuery.java @@ -15,6 +15,7 @@ import static org.springframework.data.domain.Sort.Direction.DESC; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutManagement; @@ -113,38 +114,34 @@ public class RolloutGroupBeanQuery extends AbstractBeanQuery } private List getProxyRolloutGroupList(final List rolloutGroupBeans) { - final List proxyRolloutGroupsList = new ArrayList<>(); - for (final RolloutGroup rolloutGroup : rolloutGroupBeans) { - final ProxyRolloutGroup proxyRolloutGroup = new ProxyRolloutGroup(); - proxyRolloutGroup.setName(rolloutGroup.getName()); - proxyRolloutGroup.setDescription(rolloutGroup.getDescription()); - proxyRolloutGroup.setCreatedDate(SPDateTimeUtil.getFormattedDate(rolloutGroup.getCreatedAt())); - proxyRolloutGroup.setModifiedDate(SPDateTimeUtil.getFormattedDate(rolloutGroup.getLastModifiedAt())); - proxyRolloutGroup.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(rolloutGroup)); - proxyRolloutGroup.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(rolloutGroup)); - proxyRolloutGroup.setId(rolloutGroup.getId()); - proxyRolloutGroup.setStatus(rolloutGroup.getStatus()); - proxyRolloutGroup.setErrorAction(rolloutGroup.getErrorAction()); - proxyRolloutGroup.setErrorActionExp(rolloutGroup.getErrorActionExp()); - proxyRolloutGroup.setErrorCondition(rolloutGroup.getErrorCondition()); - proxyRolloutGroup.setErrorConditionExp(rolloutGroup.getErrorConditionExp()); - proxyRolloutGroup.setSuccessCondition(rolloutGroup.getSuccessCondition()); - proxyRolloutGroup.setSuccessConditionExp(rolloutGroup.getSuccessConditionExp()); - proxyRolloutGroup.setFinishedPercentage(calculateFinishedPercentage(rolloutGroup)); - - proxyRolloutGroup.setRolloutRendererData(new RolloutRendererData(rolloutGroup.getName(), null)); - - proxyRolloutGroup.setTotalTargetsCount(String.valueOf(rolloutGroup.getTotalTargets())); - proxyRolloutGroup.setTotalTargetCountStatus(rolloutGroup.getTotalTargetCountStatus()); - - proxyRolloutGroupsList.add(proxyRolloutGroup); - } - return proxyRolloutGroupsList; + return rolloutGroupBeans.stream().map(RolloutGroupBeanQuery::createProxy).collect(Collectors.toList()); } - private String calculateFinishedPercentage(final RolloutGroup rolloutGroup) { - return HawkbitCommonUtil.formattingFinishedPercentage(rolloutGroup, getRolloutManagement() - .getFinishedPercentForRunningGroup(rolloutGroup.getRollout().getId(), rolloutGroup.getId())); + private static ProxyRolloutGroup createProxy(final RolloutGroup rolloutGroup) { + final ProxyRolloutGroup proxyRolloutGroup = new ProxyRolloutGroup(); + proxyRolloutGroup.setName(rolloutGroup.getName()); + proxyRolloutGroup.setDescription(rolloutGroup.getDescription()); + proxyRolloutGroup.setCreatedDate(SPDateTimeUtil.getFormattedDate(rolloutGroup.getCreatedAt())); + proxyRolloutGroup.setModifiedDate(SPDateTimeUtil.getFormattedDate(rolloutGroup.getLastModifiedAt())); + proxyRolloutGroup.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(rolloutGroup)); + proxyRolloutGroup.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(rolloutGroup)); + proxyRolloutGroup.setId(rolloutGroup.getId()); + proxyRolloutGroup.setStatus(rolloutGroup.getStatus()); + proxyRolloutGroup.setErrorAction(rolloutGroup.getErrorAction()); + proxyRolloutGroup.setErrorActionExp(rolloutGroup.getErrorActionExp()); + proxyRolloutGroup.setErrorCondition(rolloutGroup.getErrorCondition()); + proxyRolloutGroup.setErrorConditionExp(rolloutGroup.getErrorConditionExp()); + proxyRolloutGroup.setSuccessCondition(rolloutGroup.getSuccessCondition()); + proxyRolloutGroup.setSuccessConditionExp(rolloutGroup.getSuccessConditionExp()); + proxyRolloutGroup.setFinishedPercentage(HawkbitCommonUtil.formattingFinishedPercentage(rolloutGroup, + rolloutGroup.getTotalTargetCountStatus().getFinishedPercent())); + + proxyRolloutGroup.setRolloutRendererData(new RolloutRendererData(rolloutGroup.getName(), null)); + + proxyRolloutGroup.setTotalTargetsCount(String.valueOf(rolloutGroup.getTotalTargets())); + proxyRolloutGroup.setTotalTargetCountStatus(rolloutGroup.getTotalTargetCountStatus()); + + return proxyRolloutGroup; } @Override