From fc76808fe79fbb2cba618a112b8771e790c8b94d Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 19 Nov 2025 12:13:55 +0100 Subject: [PATCH 01/20] [NAE-2266] Introduce active version of process - add attribute isVersionActive in PetriNet - introduce PetriNetService.getActiveVersionByIdentifier - rename PetriNetService.getNewestVersionByIdentifier to PetriNetService.getLatestVersionByIdentifier - switch usage of getNewestVersionByIdentifier to getActiveVersionByIdentifier - enhance process import validations --- .../logic/action/ActionDelegate.groovy | 2 +- .../action/delegate/RoleActionDelegate.groovy | 4 +- .../engine/startup/ImportHelper.groovy | 4 +- .../CacheConfigurationProperties.java | 12 +- .../services/DashboardItemServiceImpl.java | 2 +- .../DashboardManagementServiceImpl.java | 2 +- .../repositories/PetriNetRepository.java | 5 + .../petrinet/service/PetriNetService.java | 111 +++++++++++++----- .../service/interfaces/IPetriNetService.java | 15 ++- .../startup/runner/DefaultFiltersRunner.java | 2 +- .../startup/runner/ImpersonationRunner.java | 2 +- .../workflow/service/CaseSearchService.java | 2 +- .../service/FieldActionsCacheService.java | 2 +- .../service/FilterImportExportService.java | 2 +- .../service/MenuImportExportService.java | 4 +- .../workflow/service/WorkflowService.java | 6 +- .../export/service/ExportServiceTest.groovy | 4 +- .../ImpersonationServiceTest.groovy | 2 +- .../petrinet/domain/ImporterTest.groovy | 4 +- .../service/CachePetriNetServiceTest.groovy | 2 +- .../engine/workflow/NewInitTest.groovy | 2 +- .../change_caseref_value_action_test.xml | 4 +- .../petriNets/NAE-1290_Export_actions.xml | 2 +- .../elastic/domain/ElasticPetriNet.java | 4 + .../objects/petrinet/domain/PetriNet.java | 50 +++++--- .../petrinet/domain/version/Version.java | 20 ++++ .../spring/petrinet/domain/PetriNet.java | 1 + 27 files changed, 190 insertions(+), 82 deletions(-) diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index 33319096504..25b6eda70b6 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -2439,7 +2439,7 @@ class ActionDelegate { return [(role.importId + ":" + GLOBAL_ROLE), ("$role.name (🌍 Global role)" as String)] } else { if (!temp.containsKey(entry.value)) { - temp.put(entry.value, petriNetService.getNewestVersionByIdentifier(entry.value)) + temp.put(entry.value, petriNetService.getActiveVersionByIdentifier(entry.value)) } PetriNet net = temp[entry.value] ProcessRole role = net.roles.find { it.value.importId == entry.key }.value diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy index 78f640b7052..da2f0806ff0 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy @@ -51,7 +51,7 @@ class RoleActionDelegate extends AbstractActionDelegate { } AbstractUser assignRole(String roleImportId, String petriNetIdentifier, AbstractUser user = affectedUser) { - PetriNet petriNet = petriNetService.getNewestVersionByIdentifier(petriNetIdentifier) + PetriNet petriNet = petriNetService.getActiveVersionByIdentifier(petriNetIdentifier) assignRole(roleImportId, user, petriNet) } @@ -75,7 +75,7 @@ class RoleActionDelegate extends AbstractActionDelegate { } AbstractUser removeRole(String roleImportId, String petriNetIdentifier, AbstractUser user = affectedUser) { - PetriNet petriNet = petriNetService.getNewestVersionByIdentifier(petriNetIdentifier) + PetriNet petriNet = petriNetService.getActiveVersionByIdentifier(petriNetIdentifier) removeRole(roleImportId, user, petriNet) } diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy index 651bf31abba..ed89eeb78f3 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy @@ -128,7 +128,7 @@ class ImportHelper { } Optional upsertNet(String filename, String identifier, VersionType release = VersionType.MAJOR, LoggedUser author = ActorTransformer.toLoggedUser(userService.getSystem())) { - PetriNet petriNet = petriNetService.getNewestVersionByIdentifier(identifier) + PetriNet petriNet = petriNetService.getActiveVersionByIdentifier(identifier) if (!petriNet) { return createNet(filename, release, author) } @@ -249,7 +249,7 @@ class ImportHelper { } Optional importProcessOnce(String message, String netIdentifier, String netFileName) { - PetriNet filter = petriNetService.getNewestVersionByIdentifier(netIdentifier) + PetriNet filter = petriNetService.getActiveVersionByIdentifier(netIdentifier) if (filter != null) { log.info("${message} has already been imported.") return Optional.of(filter) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java index 8050c7ac379..ad32548f84b 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/properties/CacheConfigurationProperties.java @@ -27,9 +27,14 @@ public class CacheConfigurationProperties { private String petriNetByIdentifier = "petriNetByIdentifier"; /** - * Default cache name for caching the newest versions of Petri nets. + * Default cache name for caching the active versions of Petri nets. */ - private String petriNetNewest = "petriNetNewest"; + private String petriNetActive = "petriNetActive"; + + /** + * Default cache name for caching the latest versions of Petri nets. + */ + private String petriNetLatest = "petriNetLatest"; /** * Default cache name for general Petri net caching. @@ -54,7 +59,8 @@ public class CacheConfigurationProperties { * @return a {@link Set} of all cache names. */ public Set getAllCaches() { - Set caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetNewest, petriNetCache, loadedModules)); + Set caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetActive, + petriNetLatest, petriNetCache, loadedModules)); caches.addAll(additional); return caches; } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java index c0a5627de03..8d40f6cb91b 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java @@ -62,7 +62,7 @@ public Case getOrCreate(DashboardItemBody body) throws TransitionNotExecutableEx } LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()); - itemCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier(DashboardItemConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); + itemCase = workflowService.createCase(petriNetService.getActiveVersionByIdentifier(DashboardItemConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); ToDataSetOutcome outcome = body.toDataSet(); itemCase = setDataWithExecute(itemCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet()); return itemCase; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java index 95a426e88eb..a4497831164 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java @@ -64,7 +64,7 @@ public Case createDashboardManagement(DashboardManagementBody body) throws Trans } addReferencedMenuItems(body); LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()); - managementCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); + managementCase = workflowService.createCase(petriNetService.getActiveVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); ToDataSetOutcome outcome = body.toDataSet(); managementCase = setDataWithExecute(managementCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet()); return managementCase; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java index a8dd005b207..d46394681b8 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java @@ -33,6 +33,11 @@ public interface PetriNetRepository extends MongoRepository, Q */ PetriNet findByIdentifierAndVersion(String identifier, Version version); + /** + * todo javadoc + */ + PetriNet findByIdentifierAndVersionActive(String identifier, boolean isVersionActive); + /** * Finds a paginated list of {@link PetriNet} entities by their identifier. * diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index a4684616368..8dc3bcff8f2 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -7,7 +7,6 @@ import com.netgrif.application.engine.files.minio.StorageConfigurationProperties; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.ArcImportReference; -import com.netgrif.application.engine.objects.auth.domain.Group; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetMappingService; @@ -141,15 +140,16 @@ protected Importer getImporter() { @Override public void evictAllCaches() { requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetById()), cacheProperties.getPetriNetById()).clear(); - requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetNewest()), cacheProperties.getPetriNetNewest()).clear(); + requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetActive()), cacheProperties.getPetriNetActive()).clear(); + requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetLatest()), cacheProperties.getPetriNetLatest()).clear(); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetCache()), cacheProperties.getPetriNetCache()).clear(); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetByIdentifier()), cacheProperties.getPetriNetByIdentifier()).clear(); - } public void evictCache(PetriNet net) { requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetById()), cacheProperties.getPetriNetById()).evict(net.getStringId()); - requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetNewest()), cacheProperties.getPetriNetNewest()).evict(net.getIdentifier()); + requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetActive()), cacheProperties.getPetriNetActive()).evict(net.getIdentifier()); + requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetLatest()), cacheProperties.getPetriNetLatest()).evict(net.getIdentifier()); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetCache()), cacheProperties.getPetriNetCache()).evict(net.getObjectId()); requireNonNull(cacheManager.getCache(cacheProperties.getPetriNetByIdentifier()), cacheProperties.getPetriNetByIdentifier()).evict(net.getIdentifier() + net.getVersion().toString()); } @@ -193,38 +193,67 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp ImportPetriNetEventOutcome outcome = new ImportPetriNetEventOutcome(); ByteArrayOutputStream xmlCopy = new ByteArrayOutputStream(); IOUtils.copy(xmlFile, xmlCopy); - Optional imported = getImporter().importPetriNet(new ByteArrayInputStream(xmlCopy.toByteArray())); - if (imported.isEmpty()) { + Optional importedProcess = getImporter().importPetriNet(new ByteArrayInputStream(xmlCopy.toByteArray())); + if (importedProcess.isEmpty()) { return outcome; } - PetriNet net = imported.get(); - - PetriNet existingNet = getNewestVersionByIdentifier(net.getIdentifier()); + PetriNet newProcess = importedProcess.get(); + PetriNet inactivatedProcess = null; - if (existingNet != null) { - if (existingNet.getVersion().equals(net.getVersion())) { - throw new IllegalArgumentException("Provided Petri net version is already present in the system"); + if (self.getPetriNet(newProcess.getIdentifier(), newProcess.getVersion()) != null) { + throw new IllegalArgumentException("A process [%s] with such version [%s] already exists" + .formatted(newProcess.getIdentifier(), newProcess.getVersion())); + } + PetriNet existingLatestProcess = self.getLatestVersionByIdentifier(newProcess.getIdentifier()); + if (existingLatestProcess == null) { + newProcess.setVersion(new Version()); + } else { + if (newProcess.getVersion() == null) { + newProcess.setVersion(existingLatestProcess.getVersion()); + newProcess.incrementVersion(releaseType); + } else if (newProcess.getVersion().isLowerThan(existingLatestProcess.getVersion())) { + throw new IllegalArgumentException("Only higher versions of process [%s] are allowed to import. The requested version [%s] cannot be imported because the higher version [%s] already exists." + .formatted(newProcess.getIdentifier(), newProcess.getVersion(), existingLatestProcess.getVersion())); } - if (net.getVersion() == null) { - net.setVersion(existingNet.getVersion()); - net.incrementVersion(releaseType); + if (existingLatestProcess.isVersionActive()) { + existingLatestProcess.makeInactive(); + inactivatedProcess = existingLatestProcess; + } else { + PetriNet existingActiveProcess = self.getActiveVersionByIdentifier(newProcess.getIdentifier()); + if (existingActiveProcess != null) { + existingActiveProcess.makeInactive(); + inactivatedProcess = existingActiveProcess; + } } - } else if (net.getVersion() == null) { - net.setVersion(new Version()); } + newProcess.makeActive(); - processRoleService.saveAll(net.getRoles().values()); - net.setAuthor(ActorTransformer.toActorRef(author)); - functionCacheService.cachePetriNetFunctions(net); - Path savedPath = getImporter().saveNetFile(net, new ByteArrayInputStream(xmlCopy.toByteArray())); + processRoleService.saveAll(newProcess.getRoles().values()); + newProcess.setAuthor(ActorTransformer.toActorRef(author)); + functionCacheService.cachePetriNetFunctions(newProcess); + Path savedPath = getImporter().saveNetFile(newProcess, new ByteArrayInputStream(xmlCopy.toByteArray())); xmlCopy.close(); - log.info("Petri net " + net.getTitle() + " (" + net.getInitials() + " v" + net.getVersion() + ") imported successfully and saved in a folder: " + savedPath.toString()); + log.info("Petri newProcess " + newProcess.getTitle() + " (" + newProcess.getInitials() + " v" + newProcess.getVersion() + ") importedProcess successfully and saved in a folder: " + savedPath.toString()); - outcome.setOutcomes(eventService.runActions(net.getPreUploadActions(), null, Optional.empty(), params)); + outcome.setOutcomes(eventService.runActions(newProcess.getPreUploadActions(), null, Optional.empty(), params)); publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.PRE)); - save(net); - outcome.setOutcomes(eventService.runActions(net.getPostUploadActions(), null, Optional.empty(), params)); - outcome.setNet(imported.get()); + if (inactivatedProcess != null) { + save(inactivatedProcess); + } + try { + save(newProcess); + } catch (Exception rethrow) { + if (inactivatedProcess != null) { + // make sure there is always an active version + log.warn("Something unexpected happened while saving new version of process [{}]. Rolling back status of a version, that have been inactivated...", + newProcess.getIdentifier()); + inactivatedProcess.makeActive(); + save(inactivatedProcess); + } + throw rethrow; + } + outcome.setOutcomes(eventService.runActions(newProcess.getPostUploadActions(), null, Optional.empty(), params)); + outcome.setNet(importedProcess.get()); publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.POST)); return outcome; } @@ -263,6 +292,9 @@ public PetriNet getPetriNet(String id) { @Override @Cacheable(value = "petriNetByIdentifier", key = "#identifier+#version.toString()", unless = "#result == null") public PetriNet getPetriNet(String identifier, Version version) { + if (identifier == null || version == null) { + return null; + } PetriNet net = repository.findByIdentifierAndVersion(identifier, version); if (net == null) { return null; @@ -284,13 +316,28 @@ public List findAllById(List ids) { } @Override - @Cacheable(value = "petriNetNewest", unless = "#result == null") - public PetriNet getNewestVersionByIdentifier(String identifier) { - List nets = repository.findByIdentifier(identifier, PageRequest.of(0, 1, Sort.Direction.DESC, "version.major", "version.minor", "version.patch")).getContent(); - if (nets.isEmpty()) { + @Cacheable(value = "petriNetActive", unless = "#result == null") + public PetriNet getActiveVersionByIdentifier(String identifier) { + // todo 2266 test + if (identifier == null) { + return null; + } + return repository.findByIdentifierAndVersionActive(identifier, true); + } + + @Override + @Cacheable(value = "petriNetLatest", unless = "#result == null") + public PetriNet getLatestVersionByIdentifier(String identifier) { + // todo 2266 test + if (identifier == null) { + return null; + } + List processes = repository.findByIdentifier(identifier, PageRequest.of(0, 1, + Sort.Direction.DESC, "version.major", "version.minor", "version.patch")).getContent(); + if (processes.isEmpty()) { return null; } - return nets.getFirst(); + return processes.getFirst(); } /** @@ -422,7 +469,7 @@ public List getReferencesByUsersProcessRoles(LoggedUser user, @Override public PetriNetReference getReference(String identifier, Version version, LoggedUser user, Locale locale) { - PetriNet net = version == null ? getNewestVersionByIdentifier(identifier) : getPetriNet(identifier, version); + PetriNet net = version == null ? getActiveVersionByIdentifier(identifier) : getPetriNet(identifier, version); return net != null ? transformToReference(net, locale) : new PetriNetReference(); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java index c6fd966cb51..8988afd5662 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java @@ -153,12 +153,21 @@ static DataFieldReference transformToReference(PetriNet net, Transition transiti List findAllById(List ids); /** - * Retrieves the newest version of a {@link PetriNet} by its identifier. + * Retrieves the active version of a {@link PetriNet} by its identifier. + * todo javadoc isversionactive logic * * @param identifier the unique identifier of the PetriNet - * @return the newest version of the {@link PetriNet} matching the provided identifier + * @return the active version of the {@link PetriNet} matching the provided identifier */ - PetriNet getNewestVersionByIdentifier(String identifier); + PetriNet getActiveVersionByIdentifier(String identifier); + + /** + * Retrieves the latest version of a {@link PetriNet} by its identifier. + * + * @param identifier the unique identifier of the PetriNet + * @return the latest version of the {@link PetriNet} matching the provided identifier + */ + PetriNet getLatestVersionByIdentifier(String identifier); /** * Retrieves a paginated list of all {@link PetriNet} objects. diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java index 93a2618d03a..64453b2c150 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java @@ -424,7 +424,7 @@ public Optional createFilter(String title, String icon, String filterType, } private Optional createFilterCase(String title, String icon, String filterType, String filterVisibility, String filterQuery, List allowedNets, Map filterMetadata, Map titleTranslations, String originId, boolean viewOrigin, boolean isImported) { - PetriNet filterNet = this.petriNetService.getNewestVersionByIdentifier("filter"); + PetriNet filterNet = this.petriNetService.getActiveVersionByIdentifier("filter"); if (filterNet == null) { return Optional.empty(); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java index 44522a25567..6407d1e0012 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java @@ -39,7 +39,7 @@ public void createConfigNets() { } public Optional importProcess(final String message, String netIdentifier, String netFileName) { - PetriNet foundNet = petriNetService.getNewestVersionByIdentifier(netIdentifier); + PetriNet foundNet = petriNetService.getActiveVersionByIdentifier(netIdentifier); if (foundNet != null) { log.info("{} has already been imported.", message); return Optional.of(foundNet); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java index 923d17bfa54..c4769d65658 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java @@ -280,7 +280,7 @@ public Predicate fullText(Object petriNetQuery, String searchPhrase) { // TODO JOFO: unpaged necessary? petriNets = petriNetService.getAll(Pageable.unpaged()).getContent(); } else { - petriNets = processes.stream().map(process -> petriNetService.getNewestVersionByIdentifier(process)).collect(Collectors.toList()); + petriNets = processes.stream().map(process -> petriNetService.getActiveVersionByIdentifier(process)).collect(Collectors.toList()); } if (petriNets.isEmpty()) return null; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java index 1b996bc60da..5ae423c476d 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FieldActionsCacheService.java @@ -71,7 +71,7 @@ public void cachePetriNetFunctions(PetriNet petriNet) { @Override public void reloadCachedFunctions(PetriNet petriNet) { namespaceFunctionsCache.remove(petriNet.getIdentifier()); - cachePetriNetFunctions(petriNetService.getNewestVersionByIdentifier(petriNet.getIdentifier())); + cachePetriNetFunctions(petriNetService.getActiveVersionByIdentifier(petriNet.getIdentifier())); } @Override diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java index 9dd6cea3f5c..54dfed8b6cc 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java @@ -266,7 +266,7 @@ public void changeFilterField(Collection filterFields) { filterFields.forEach(f -> { Task importedFilterTask = taskService.findOne(f); Case filterCase = workflowService.findOne(importedFilterTask.getCaseId()); - PetriNet filterNet = petriNetService.getNewestVersionByIdentifier(FILTER_NET_IDENTIFIER); + PetriNet filterNet = petriNetService.getActiveVersionByIdentifier(FILTER_NET_IDENTIFIER); List requiredNets = filterCase.getDataSet().get(FIELD_FILTER).getAllowedNets(); List currentNets = petriNetService.getExistingPetriNetIdentifiersFromIdentifiersList(requiredNets); if (currentNets.size() < requiredNets.size()) { diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java index 1eb921882b7..4766834b652 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java @@ -237,7 +237,7 @@ public String createMenuItemCase(StringBuilder resultMessage, MenuEntry item, St String roleImportId = menuEntryRole.getRoleImportId(); String netImportId = menuEntryRole.getNetImportId(); if (netImportId != null) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(netImportId); + PetriNet net = petriNetService.getActiveVersionByIdentifier(netImportId); if (net == null) { resultMessage.append("\n- Missing net with import ID: \"").append(netImportId).append("\"").append("for role ").append(roleImportId).append("\n"); netCheck.set(false); @@ -261,7 +261,7 @@ public String createMenuItemCase(StringBuilder resultMessage, MenuEntry item, St } //Creating new Case of preference_filter_item net and setting its data... Case menuItemCase = workflowService.createCase( - petriNetService.getNewestVersionByIdentifier("preference_filter_item").getStringId(), + petriNetService.getActiveVersionByIdentifier("preference_filter_item").getStringId(), item.getEntryName() + "_" + menuIdentifier, "", ActorTransformer.toLoggedUser(userService.getSystem()) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java index 9fdb0e83f11..c4e9bae29a0 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java @@ -285,7 +285,7 @@ public CreateCaseEventOutcome createCase(String netId, String title, String colo @Override public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Locale locale, Map params) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(identifier); + PetriNet net = petriNetService.getActiveVersionByIdentifier(identifier); if (net == null) { throw new IllegalArgumentException("Petri net with identifier [" + identifier + "] does not exist."); } @@ -299,7 +299,7 @@ public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String t @Override public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user, Map params) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(identifier); + PetriNet net = petriNetService.getActiveVersionByIdentifier(identifier); if (net == null) { throw new IllegalArgumentException("Petri net with identifier [" + identifier + "] does not exist."); } @@ -308,7 +308,7 @@ public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String t @Override public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String title, String color, LoggedUser user) { - PetriNet net = petriNetService.getNewestVersionByIdentifier(identifier); + PetriNet net = petriNetService.getActiveVersionByIdentifier(identifier); if (net == null) { throw new IllegalArgumentException("Petri net with identifier [" + identifier + "] does not exist."); } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy index dab63cbf0f5..578ba26f42f 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/export/service/ExportServiceTest.groovy @@ -128,7 +128,7 @@ class ExportServiceTest { taskService.assignTask(ActorTransformer.toLoggedUser(userService.findByEmail(UserConstants.ADMIN_USER_EMAIL, null)), exportTask) Thread.sleep(20000) //Elastic wait - def processId = petriNetService.getNewestVersionByIdentifier("export_test").stringId + def processId = petriNetService.getActiveVersionByIdentifier("export_test").stringId def taskRequest = new ElasticTaskSearchRequest() taskRequest.process = [new com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.PetriNet(processId)] as List taskRequest.transitionId = ["t4"] as List @@ -146,7 +146,7 @@ class ExportServiceTest { @Test void buildDefaultCsvTaskHeaderTest(){ - def processId = petriNetService.getNewestVersionByIdentifier("export_test").stringId + def processId = petriNetService.getActiveVersionByIdentifier("export_test").stringId String exportTask = mainCase.tasks.find { it.transition == "t4" }.task taskService.assignTask(ActorTransformer.toLoggedUser(userService.findByEmail(UserConstants.ADMIN_USER_EMAIL, null)), exportTask) List task = taskRepository.findAll(QTask.task.processId.eq(processId).and(QTask.task.transitionId.eq("t4"))) diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy index b6b97f53520..7eeebba6a5e 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy @@ -311,7 +311,7 @@ class ImpersonationServiceTest { } def createConfigCase(AbstractUser user, String impersonator, List roles = null, List auths = null) { - def caze = helper.createCase("config", petriNetService.getNewestVersionByIdentifier(ImpersonationRunner.IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER)) + def caze = helper.createCase("config", petriNetService.getActiveVersionByIdentifier(ImpersonationRunner.IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER)) def owner = new UserFieldValue(user) caze.dataSet["impersonated"].value = owner caze.dataSet["impersonated_email"].value = owner.username diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy index 15e6138b78c..33645198c1b 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/ImporterTest.groovy @@ -130,7 +130,7 @@ class ImporterTest { assert net.places.size() == 0 // ASSERT IMPORTED NET FROM REPO - net = petriNetService.getNewestVersionByIdentifier("new_model") + net = petriNetService.getActiveVersionByIdentifier("new_model") assert net != null assert net.importId == "new_model" assert net.version.major == 1 @@ -204,7 +204,7 @@ class ImporterTest { assert net2.places.size() == 0 // ASSERT NEW NET FROM REPO - net2 = petriNetService.getNewestVersionByIdentifier("new_model") + net2 = petriNetService.getActiveVersionByIdentifier("new_model") assert net2 != null assert net2.importId == "new_model" assert net2.version.major == 2 diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy index 1c4a7d430ab..2f52400152d 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy @@ -73,7 +73,7 @@ class CachePetriNetServiceTest { PetriNet testNet = testNetOptional.getNet() assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get(testNet.getIdentifier()) == null - PetriNet test = petriNetService.getNewestVersionByIdentifier(testNet.getIdentifier()) + PetriNet test = petriNetService.getActiveVersionByIdentifier(testNet.getIdentifier()) assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get(testNet.getIdentifier()).get().equals(test) } } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy index 3e7f28bd4d8..84d2de4bdc2 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/workflow/NewInitTest.groovy @@ -45,7 +45,7 @@ class NewInitTest { @Test void newInitTest() throws IOException, MissingIconKeyException, MissingPetriNetMetaDataException { petriNetService.importPetriNet(new FileInputStream("src/test/resources/petriNets/nae_1276_Init_value_as_choice.xml"), VersionType.MAJOR, superCreator.getLoggedSuper()) - Case initTestCase = workflowService.createCase(petriNetService.getNewestVersionByIdentifier("new_init_test").stringId, "New init test", "", superCreator.getLoggedSuper()).getCase() + Case initTestCase = workflowService.createCase(petriNetService.getActiveVersionByIdentifier("new_init_test").stringId, "New init test", "", superCreator.getLoggedSuper()).getCase() assert (initTestCase.dataSet["new_init_multichoice"].value as List).stream().any { it.defaultValue == "Bob" } assert (initTestCase.dataSet["new_init_multichoice"].value as List).stream().any { it.defaultValue == "Alice" } assert (initTestCase.dataSet["old_init_multichoice"].value as List).stream().any { it.defaultValue == "Bob" } diff --git a/application-engine/src/test/resources/change_caseref_value_action_test.xml b/application-engine/src/test/resources/change_caseref_value_action_test.xml index cf908b29fe9..ebaf0193308 100644 --- a/application-engine/src/test/resources/change_caseref_value_action_test.xml +++ b/application-engine/src/test/resources/change_caseref_value_action_test.xml @@ -29,7 +29,7 @@ caseref: f.caseref; - def net = petriNetService.getNewestVersionByIdentifier("change_value"); + def net = petriNetService.getActiveVersionByIdentifier("change_value"); def newCase = workflowService.createCase(net.stringId, "", "", userService.transformToLoggedUser(userService.getLoggedOrSystem())).getACase() def newValue = new ArrayList(caseref.value) newValue.add(newCase) @@ -43,7 +43,7 @@ caseref: f.caseref; - def net = petriNetService.getNewestVersionByIdentifier("test"); + def net = petriNetService.getActiveVersionByIdentifier("test"); def newCase = workflowService.createCase(net.stringId, "", "", userService.transformToLoggedUser(userService.getLoggedOrSystem())).getACase() def newValue = new ArrayList(caseref.value) newValue.add(newCase) diff --git a/application-engine/src/test/resources/petriNets/NAE-1290_Export_actions.xml b/application-engine/src/test/resources/petriNets/NAE-1290_Export_actions.xml index 33794373055..c019e50ab23 100644 --- a/application-engine/src/test/resources/petriNets/NAE-1290_Export_actions.xml +++ b/application-engine/src/test/resources/petriNets/NAE-1290_Export_actions.xml @@ -217,7 +217,7 @@ export - def processId = petriNetService.getNewestVersionByIdentifier("export_test").stringId + def processId = petriNetService.getActiveVersionByIdentifier("export_test").stringId def config = new com.netgrif.application.engine.export.domain.ExportDataConfig() config.setDataToExport(["immediate_multichoice","immediate_number", "text"] as LinkedHashSet) exportTasksToFile({it.processId.eq(processId) & it.transitionId.eq("t3")},"src/test/resources/csv/task_mongo_export.csv", config) diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java index bdec2b24c71..04a8177dc9d 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java @@ -24,6 +24,8 @@ public abstract class ElasticPetriNet { private Version version; + private boolean isVersionActive; + private String uriNodeId; private I18nField title; @@ -38,6 +40,7 @@ public ElasticPetriNet(PetriNet net) { this.id = net.getStringId(); this.identifier = net.getIdentifier(); this.version = net.getVersion(); + this.isVersionActive = net.isVersionActive(); this.uriNodeId = net.getUriNodeId(); this.title = this.transformToField(net.getTitle()); this.initials = net.getInitials(); @@ -46,6 +49,7 @@ public ElasticPetriNet(PetriNet net) { public void update(ElasticPetriNet net) { this.version = net.getVersion(); + this.isVersionActive = net.isVersionActive(); if (net.getUriNodeId() != null) { this.uriNodeId = net.getUriNodeId(); } diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java index a8b2fa447cd..16e50f13854 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.objects.petrinet.domain; +import com.netgrif.application.engine.objects.annotations.Indexed; import com.netgrif.application.engine.objects.auth.domain.ActorRef; import com.netgrif.application.engine.objects.petrinet.domain.arcs.Arc; import com.netgrif.application.engine.objects.petrinet.domain.arcs.reference.Referencable; @@ -30,7 +31,7 @@ public abstract class PetriNet extends PetriNetObject { @Getter @Setter - private String identifier; //combination of identifier and version must be unique ... maybe use @CompoundIndex? + private String identifier; // todo: combination of identifier and version must be unique ... maybe use @CompoundIndex? @Getter @Setter @@ -72,6 +73,11 @@ public abstract class PetriNet extends PetriNetObject { @Setter private Version version; + @Getter + @Setter + @Indexed + private boolean isVersionActive; + @Getter @Setter private ActorRef author; @@ -141,22 +147,23 @@ public PetriNet() { this.title = new I18nString(""); this.importId = ""; this.version = new Version(); - defaultCaseName = new I18nString(""); - initialized = false; - creationDate = LocalDateTime.now(); - places = new LinkedHashMap<>(); - transitions = new LinkedHashMap<>(); - arcs = new LinkedHashMap<>(); - dataSet = new LinkedHashMap<>(); - roles = new LinkedHashMap<>(); - negativeViewRoles = new LinkedList<>(); - transactions = new LinkedHashMap<>(); - processEvents = new LinkedHashMap<>(); - caseEvents = new LinkedHashMap<>(); - permissions = new HashMap<>(); - userRefs = new HashMap<>(); - functions = new LinkedList<>(); - tags = new HashMap<>(); + this.defaultCaseName = new I18nString(""); + this.initialized = false; + this.creationDate = LocalDateTime.now(); + this.places = new LinkedHashMap<>(); + this.transitions = new LinkedHashMap<>(); + this.arcs = new LinkedHashMap<>(); + this.dataSet = new LinkedHashMap<>(); + this.roles = new LinkedHashMap<>(); + this.negativeViewRoles = new LinkedList<>(); + this.transactions = new LinkedHashMap<>(); + this.processEvents = new LinkedHashMap<>(); + this.caseEvents = new LinkedHashMap<>(); + this.permissions = new HashMap<>(); + this.userRefs = new HashMap<>(); + this.functions = new LinkedList<>(); + this.tags = new HashMap<>(); + this.makeInactive(); } public PetriNet(PetriNet petriNet) { @@ -167,6 +174,7 @@ public PetriNet(PetriNet petriNet) { this.title = petriNet.getTitle(); this.importId = petriNet.getImportId(); this.version = petriNet.getVersion(); + this.isVersionActive = petriNet.isVersionActive(); this.defaultCaseName = petriNet.getDefaultCaseName(); this.defaultCaseNameExpression = petriNet.getDefaultCaseNameExpression(); this.initials = petriNet.getInitials(); @@ -430,6 +438,14 @@ public boolean hasDynamicCaseName() { return defaultCaseNameExpression != null; } + public void makeActive() { + this.setVersionActive(true); + } + + public void makeInactive() { + this.setVersionActive(false); + } + @Override public String getStringId() { return _id.toString(); diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java index 3c5c2d84be6..0592ab8e212 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java @@ -52,6 +52,12 @@ public void increment(VersionType type) { } } + /** + * todo javadoc + * 0 equals + * <0 this < other + * >0 this > other + */ public int compareTo(Version other) { if (this.major != other.major) { return Long.compare(this.major, other.major); @@ -62,6 +68,20 @@ public int compareTo(Version other) { return Long.compare(this.patch, other.patch); } + /** + * todo javadoc + */ + public boolean isHigherThan(Version other) { + return compareTo(other) > 0; + } + + /** + * todo javadoc + */ + public boolean isLowerThan(Version other) { + return compareTo(other) < 0; + } + @Override public Version clone() { diff --git a/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/PetriNet.java b/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/PetriNet.java index 7e91f07c13f..4076351e98f 100644 --- a/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/PetriNet.java +++ b/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/PetriNet.java @@ -60,6 +60,7 @@ public LinkedHashMap getRoles() { return super.getRoles(); } + // todo: delete clone method if not needed // @Override // public PetriNet clone() { // PetriNet clone = new PetriNet(); From b5bd5b52d12dd0e9d562d04960251eb3f597e7e4 Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 19 Nov 2025 12:57:39 +0100 Subject: [PATCH 02/20] [NAE-2266] Introduce active version of process - fix repository query - fix null pointer exception - fix unwanted java reference --- .../petrinet/domain/repositories/PetriNetRepository.java | 2 +- .../engine/petrinet/service/PetriNetService.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java index d46394681b8..ae445cbe9ae 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java @@ -36,7 +36,7 @@ public interface PetriNetRepository extends MongoRepository, Q /** * todo javadoc */ - PetriNet findByIdentifierAndVersionActive(String identifier, boolean isVersionActive); + PetriNet findByIdentifierAndIsVersionActive(String identifier, boolean isVersionActive); /** * Finds a paginated list of {@link PetriNet} entities by their identifier. diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index 8dc3bcff8f2..1f8b34d1815 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -200,7 +200,7 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp PetriNet newProcess = importedProcess.get(); PetriNet inactivatedProcess = null; - if (self.getPetriNet(newProcess.getIdentifier(), newProcess.getVersion()) != null) { + if (newProcess.getVersion() != null && self.getPetriNet(newProcess.getIdentifier(), newProcess.getVersion()) != null) { throw new IllegalArgumentException("A process [%s] with such version [%s] already exists" .formatted(newProcess.getIdentifier(), newProcess.getVersion())); } @@ -209,7 +209,7 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp newProcess.setVersion(new Version()); } else { if (newProcess.getVersion() == null) { - newProcess.setVersion(existingLatestProcess.getVersion()); + newProcess.setVersion(existingLatestProcess.getVersion().clone()); newProcess.incrementVersion(releaseType); } else if (newProcess.getVersion().isLowerThan(existingLatestProcess.getVersion())) { throw new IllegalArgumentException("Only higher versions of process [%s] are allowed to import. The requested version [%s] cannot be imported because the higher version [%s] already exists." @@ -322,7 +322,7 @@ public PetriNet getActiveVersionByIdentifier(String identifier) { if (identifier == null) { return null; } - return repository.findByIdentifierAndVersionActive(identifier, true); + return repository.findByIdentifierAndIsVersionActive(identifier, true); } @Override From 9059beca3ba54da2a6c102e606e1e719eaf7d20e Mon Sep 17 00:00:00 2001 From: chvostek Date: Wed, 19 Nov 2025 13:22:06 +0100 Subject: [PATCH 03/20] [NAE-2266] Introduce active version of process - fix version initialization --- .../engine/petrinet/service/PetriNetService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index 1f8b34d1815..67cac75c20b 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -205,17 +205,17 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp .formatted(newProcess.getIdentifier(), newProcess.getVersion())); } PetriNet existingLatestProcess = self.getLatestVersionByIdentifier(newProcess.getIdentifier()); - if (existingLatestProcess == null) { + if (existingLatestProcess == null && newProcess.getVersion() == null) { newProcess.setVersion(new Version()); } else { if (newProcess.getVersion() == null) { newProcess.setVersion(existingLatestProcess.getVersion().clone()); newProcess.incrementVersion(releaseType); - } else if (newProcess.getVersion().isLowerThan(existingLatestProcess.getVersion())) { + } else if (existingLatestProcess != null && newProcess.getVersion().isLowerThan(existingLatestProcess.getVersion())) { throw new IllegalArgumentException("Only higher versions of process [%s] are allowed to import. The requested version [%s] cannot be imported because the higher version [%s] already exists." .formatted(newProcess.getIdentifier(), newProcess.getVersion(), existingLatestProcess.getVersion())); } - if (existingLatestProcess.isVersionActive()) { + if (existingLatestProcess != null && existingLatestProcess.isVersionActive()) { existingLatestProcess.makeInactive(); inactivatedProcess = existingLatestProcess; } else { From dfd7afd4863a8e8e71afaefa9aa62189efb0eff6 Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 20 Nov 2025 10:17:22 +0100 Subject: [PATCH 04/20] [NAE-2266] Introduce active version of process - implement tests to test the version --- .../service/PetriNetServiceTest.groovy | 96 ++++++++++++++++--- .../petriNets/process_version_1_0_0.xml | 9 ++ .../petriNets/process_version_2_0_0.xml | 9 ++ .../petriNets/process_version_3_0_0.xml | 9 ++ .../petriNets/process_version_4_0_0.xml | 9 ++ .../petriNets/process_version_5_0_0.xml | 9 ++ 6 files changed, 126 insertions(+), 15 deletions(-) create mode 100644 application-engine/src/test/resources/petriNets/process_version_1_0_0.xml create mode 100644 application-engine/src/test/resources/petriNets/process_version_2_0_0.xml create mode 100644 application-engine/src/test/resources/petriNets/process_version_3_0_0.xml create mode 100644 application-engine/src/test/resources/petriNets/process_version_4_0_0.xml create mode 100644 application-engine/src/test/resources/petriNets/process_version_5_0_0.xml diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index 84ce8b5ee0c..c540bafcd78 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -1,29 +1,24 @@ package com.netgrif.application.engine.petrinet.service import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.objects.auth.domain.ActorRef -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer -import com.netgrif.application.engine.objects.auth.domain.Authority -import com.netgrif.application.engine.objects.auth.domain.User -import com.netgrif.application.engine.objects.auth.domain.enums.UserState +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService import com.netgrif.application.engine.auth.service.UserService -import com.netgrif.application.engine.objects.elastic.domain.ElasticPetriNet import com.netgrif.application.engine.elastic.domain.ElasticPetriNetRepository import com.netgrif.application.engine.ipc.TaskApiTest +import com.netgrif.application.engine.objects.auth.domain.* +import com.netgrif.application.engine.objects.auth.domain.enums.UserState +import com.netgrif.application.engine.objects.elastic.domain.ElasticPetriNet import com.netgrif.application.engine.objects.petrinet.domain.PetriNet import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch -import com.netgrif.application.engine.objects.petrinet.domain.UriContentType -import com.netgrif.application.engine.objects.petrinet.domain.UriNode import com.netgrif.application.engine.objects.petrinet.domain.VersionType -import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository import com.netgrif.application.engine.objects.petrinet.domain.version.Version +import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository +import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.runner.SuperCreatorRunner -import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService @@ -39,6 +34,8 @@ import org.springframework.data.domain.PageRequest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension +import static org.junit.jupiter.api.Assertions.assertThrows + @Disabled @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @@ -46,6 +43,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension class PetriNetServiceTest { public static final String NET_FILE = "process_delete_test.xml" + public static final String VERSION_PROCESS_FILE_FORMAT = "petriNets/process_version_%s_0_0.xml" public static final String NET_SEARCH_FILE = "process_search_test.xml" public static final String CUSTOMER_USER_MAIL = "customer@netgrif.com" @@ -106,7 +104,7 @@ class PetriNetServiceTest { long taskCount = taskRepository.count() - ImportPetriNetEventOutcome testNetOptional = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + ImportPetriNetEventOutcome testNetOptional = importProcess(NET_FILE, superCreator.getLoggedSuper()) assert testNetOptional.getNet() != null assert petriNetRepository.count() == processCount + 1 PetriNet testNet = testNetOptional.getNet() @@ -149,6 +147,70 @@ class PetriNetServiceTest { assert exceptionThrown } + @Test + void testVersionsOnImport() { + ImportPetriNetEventOutcome outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) + PetriNet petriNetV2 = outcome.getNet() + assert petriNetV2 != null + assert petriNetV2.isVersionActive() + Version version = new Version() + version.setMajor(2) + assert petriNetV2.getVersion() == version + Thread.sleep(5000) + Optional elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) + assert elasticPetriNetV2Optional.isPresent() + assert elasticPetriNetV2Optional.get().isVersionActive() + + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("4"), superCreator.loggedSuper) + PetriNet petriNetV4 = outcome.getNet() + assert petriNetV4 != null + assert !petriNetService.get(petriNetV2.getObjectId()).isVersionActive() + assert petriNetV4.isVersionActive() + version = new Version() + version.setMajor(4) + assert petriNetV4.getVersion() == version + Thread.sleep(5000) + elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) + assert !elasticPetriNetV2Optional.get().isVersionActive() + Optional elasticPetriNetV4Optional = elasticPetriNetRepository.findById(petriNetV4.stringId) + assert elasticPetriNetV4Optional.isPresent() + assert elasticPetriNetV4Optional.get().isVersionActive() + + assertThrows(IllegalArgumentException.class, { + // cannot import with lower version number than the highest + importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("1"), superCreator.loggedSuper) + }) + assertThrows(IllegalArgumentException.class, { + // cannot import already existing version + importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) + }) + + petriNetV2.makeActive() + petriNetV2 = petriNetService.save(petriNetV2).get() + assert petriNetV2.isVersionActive() + petriNetV4.makeInactive() + petriNetV4 = petriNetService.save(petriNetV4).get() + assert !petriNetV4.isVersionActive() + + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("5"), superCreator.loggedSuper) + PetriNet petriNetV5 = outcome.getNet() + assert petriNetV5 != null + assert !petriNetService.get(petriNetV2.getObjectId()).isVersionActive() + assert !petriNetService.get(petriNetV4.getObjectId()).isVersionActive() + assert petriNetV5.isVersionActive() + version = new Version() + version.setMajor(5) + assert petriNetV5.getVersion() == version + Thread.sleep(5000) + elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) + assert !elasticPetriNetV2Optional.get().isVersionActive() + elasticPetriNetV4Optional = elasticPetriNetRepository.findById(petriNetV4.stringId) + assert !elasticPetriNetV4Optional.get().isVersionActive() + Optional elasticPetriNetV5Optional = elasticPetriNetRepository.findById(petriNetV5.stringId) + assert elasticPetriNetV5Optional.isPresent() + assert elasticPetriNetV5Optional.get().isVersionActive() + } + @Test void processSearch() { long processCount = petriNetRepository.count() @@ -156,8 +218,8 @@ class PetriNetServiceTest { def user = userService.findUserByUsername(CUSTOMER_USER_MAIL, null) assert user != null && user.isPresent() - petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - petriNetService.importPetriNet(stream(NET_SEARCH_FILE), VersionType.MAJOR, ActorTransformer.toLoggedUser(user.get())) + importProcess(NET_FILE, superCreator.getLoggedSuper()) + importProcess(NET_SEARCH_FILE, ActorTransformer.toLoggedUser(user.get())) assert petriNetRepository.count() == processCount + 2 @@ -209,4 +271,8 @@ class PetriNetServiceTest { search8.setAuthor(author); assert petriNetService.search(search8, superCreator.getLoggedSuper(), PageRequest.of(0, 50), LocaleContextHolder.locale).getNumberOfElements() == 1; } + + private ImportPetriNetEventOutcome importProcess(String filePath, LoggedUser author) { + return petriNetService.importPetriNet(stream(filePath), VersionType.MAJOR, author) + } } diff --git a/application-engine/src/test/resources/petriNets/process_version_1_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_1_0_0.xml new file mode 100644 index 00000000000..63594046899 --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_1_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 1.0.0 + PVT + Process Version 1.0.0 test + false + diff --git a/application-engine/src/test/resources/petriNets/process_version_2_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_2_0_0.xml new file mode 100644 index 00000000000..f095c407ae6 --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_2_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 2.0.0 + PVT + Process Version 2.0.0 test + false + diff --git a/application-engine/src/test/resources/petriNets/process_version_3_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_3_0_0.xml new file mode 100644 index 00000000000..fdf75f42944 --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_3_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 3.0.0 + PVT + Process Version 3.0.0 test + false + diff --git a/application-engine/src/test/resources/petriNets/process_version_4_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_4_0_0.xml new file mode 100644 index 00000000000..58e472c139b --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_4_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 4.0.0 + PVT + Process Version 4.0.0 test + false + diff --git a/application-engine/src/test/resources/petriNets/process_version_5_0_0.xml b/application-engine/src/test/resources/petriNets/process_version_5_0_0.xml new file mode 100644 index 00000000000..21b309f9bed --- /dev/null +++ b/application-engine/src/test/resources/petriNets/process_version_5_0_0.xml @@ -0,0 +1,9 @@ + + + process_version_test + 5.0.0 + PVT + Process Version 5.0.0 test + false + From e8441cb517bfeada2e070f65c907b2277b1e7daf Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 20 Nov 2025 11:49:55 +0100 Subject: [PATCH 05/20] [NAE-2266] Introduce active version of process - implement API to activate the process --- .../petrinet/service/PetriNetService.java | 41 ++++++++++++++++++- .../service/interfaces/IPetriNetService.java | 8 +++- .../petrinet/web/PetriNetController.java | 25 +++++++++++ .../petrinet/MakeVersionActiveDTO.java | 10 +++++ 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/MakeVersionActiveDTO.java diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index 67cac75c20b..bbf03beb12b 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -5,6 +5,7 @@ import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.configuration.properties.CacheConfigurationProperties; import com.netgrif.application.engine.files.minio.StorageConfigurationProperties; +import com.netgrif.application.engine.objects.dto.response.petrinet.MakeVersionActiveDTO; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.ArcImportReference; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; @@ -245,7 +246,7 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp } catch (Exception rethrow) { if (inactivatedProcess != null) { // make sure there is always an active version - log.warn("Something unexpected happened while saving new version of process [{}]. Rolling back status of a version, that have been inactivated...", + log.warn("Something unexpected happened while saving new version of process [{}]. Rolling back process version, that have been inactivated...", newProcess.getIdentifier()); inactivatedProcess.makeActive(); save(inactivatedProcess); @@ -258,6 +259,44 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp return outcome; } + @Override + public MakeVersionActiveDTO makeVersionActive(String processId) { + log.info("Activating the process with id [{}]...", processId); + PetriNet processToActivate = self.getPetriNet(processId); + PetriNet processToInactivate = self.getActiveVersionByIdentifier(processToActivate.getIdentifier()); + + if (processToInactivate != null && processToInactivate.getStringId().equals(processToActivate.getStringId())) { + log.debug("The process to activate is already active. Nothing to do"); + return new MakeVersionActiveDTO(); + } + + if (processToInactivate != null) { + log.debug("Inactivating current active version of process identifier and ID [{}][{}]", + processToInactivate.getIdentifier(), processToInactivate.getStringId()); + processToInactivate.makeInactive(); + save(processToInactivate); + } + + try { + processToActivate.makeActive(); + save(processToActivate); + } catch (Exception rethrow) { + if (processToInactivate != null) { + // make sure there is always an active version + log.warn("Something unexpected happened while activating process [{}]. Rolling back status of a version, that have been inactivated...", + processId); + processToInactivate.makeActive(); + save(processToInactivate); + } + throw rethrow; + } + + log.debug("Successfully activated process with ID [{}] of identifier [{}]", processToActivate.getIdentifier(), + processToActivate.getStringId()); + return new MakeVersionActiveDTO(processToActivate.getStringId(), processToInactivate == null ? null + : processToInactivate.getStringId()); + } + protected void evaluateRules(Event event) { publisher.publishEvent(event); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java index 8988afd5662..245b62bacd7 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.petrinet.service.interfaces; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.objects.dto.response.petrinet.MakeVersionActiveDTO; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.objects.petrinet.domain.Transition; @@ -110,6 +111,11 @@ static DataFieldReference transformToReference(PetriNet net, Transition transiti */ ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser user, Map params) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException; + /** + * todo javadoc + */ + MakeVersionActiveDTO makeVersionActive(String processId); + /** * Saves a PetriNet object. * @@ -157,7 +163,7 @@ static DataFieldReference transformToReference(PetriNet net, Transition transiti * todo javadoc isversionactive logic * * @param identifier the unique identifier of the PetriNet - * @return the active version of the {@link PetriNet} matching the provided identifier + * @return the active version of the {@link PetriNet} matching the provided identifier or null if not found */ PetriNet getActiveVersionByIdentifier(String identifier); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index eb9cb4f90f9..aa001ebed19 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -6,6 +6,7 @@ import com.netgrif.application.engine.eventoutcomes.LocalisedEventOutcomeFactory; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.objects.dto.response.petrinet.MakeVersionActiveDTO; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.objects.petrinet.domain.VersionType; @@ -39,6 +40,7 @@ import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.PagedModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -120,6 +122,29 @@ public EntityModel importPetriNet( } } + @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @Operation(summary = "Make the process active", + description = "Caller must have the ADMIN role. Makes the provided process active. The previous active version is inactivated.", + security = {@SecurityRequirement(name = "BasicAuth")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK. The response contains the IDs of process models, that have been activated and inactivated"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "404", description = "Process model is not found") + }) + @PostMapping(value = "/activate/{id}", produces = MediaTypes.HAL_JSON_VALUE) + public ResponseEntity makeVersionActive(@PathVariable("id") String processId) { + try { + MakeVersionActiveDTO response = service.makeVersionActive(processId); + return ResponseEntity.ok(response); + } catch (IllegalArgumentException e) { + log.error("The process with id [{}] was not found.", processId, e); + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } catch (Exception e) { + log.error("Making process [{}] active failed: ", processId, e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } + @Operation(summary = "Get all processes", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(produces = MediaTypes.HAL_JSON_VALUE) public ResponseEntity> getAll(@RequestParam(value = "indentifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Pageable pageable, Authentication auth, Locale locale) { diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/MakeVersionActiveDTO.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/MakeVersionActiveDTO.java new file mode 100644 index 00000000000..d4b414ab382 --- /dev/null +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/MakeVersionActiveDTO.java @@ -0,0 +1,10 @@ +package com.netgrif.application.engine.objects.dto.response.petrinet; + +import java.io.Serializable; + +public record MakeVersionActiveDTO(String activatedProcessId, String inactivatedProcessId) implements Serializable { + + public MakeVersionActiveDTO() { + this(null, null); + } +} From 0c1c914224667c42cb01852dc862a6ee9ac0e91b Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 20 Nov 2025 14:35:08 +0100 Subject: [PATCH 06/20] [NAE-2266] Introduce active version of process - fix logging --- .../engine/petrinet/service/PetriNetService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index bbf03beb12b..c1c65d98d62 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -271,8 +271,8 @@ public MakeVersionActiveDTO makeVersionActive(String processId) { } if (processToInactivate != null) { - log.debug("Inactivating current active version of process identifier and ID [{}][{}]", - processToInactivate.getIdentifier(), processToInactivate.getStringId()); + log.debug("Inactivating current active version of process with ID [{}] of identifier [{}]", + processToInactivate.getStringId(), processToInactivate.getIdentifier()); processToInactivate.makeInactive(); save(processToInactivate); } @@ -291,8 +291,8 @@ public MakeVersionActiveDTO makeVersionActive(String processId) { throw rethrow; } - log.debug("Successfully activated process with ID [{}] of identifier [{}]", processToActivate.getIdentifier(), - processToActivate.getStringId()); + log.debug("Successfully activated process with ID [{}] of identifier [{}]", processToActivate.getStringId(), + processToActivate.getIdentifier()); return new MakeVersionActiveDTO(processToActivate.getStringId(), processToInactivate == null ? null : processToInactivate.getStringId()); } From 53fb4e63c8324123df3a1f5d8259db82bb873c2d Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 21 Nov 2025 09:02:36 +0100 Subject: [PATCH 07/20] [NAE-2266] Introduce active version of process - fix log message --- .../application/engine/petrinet/service/PetriNetService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index c1c65d98d62..7b32c340292 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -234,7 +234,7 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp functionCacheService.cachePetriNetFunctions(newProcess); Path savedPath = getImporter().saveNetFile(newProcess, new ByteArrayInputStream(xmlCopy.toByteArray())); xmlCopy.close(); - log.info("Petri newProcess " + newProcess.getTitle() + " (" + newProcess.getInitials() + " v" + newProcess.getVersion() + ") importedProcess successfully and saved in a folder: " + savedPath.toString()); + log.info("Petri net " + newProcess.getTitle() + " (" + newProcess.getInitials() + " v" + newProcess.getVersion() + ") imported successfully and saved in a folder: " + savedPath.toString()); outcome.setOutcomes(eventService.runActions(newProcess.getPreUploadActions(), null, Optional.empty(), params)); publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.PRE)); From 1cdfbc484dd486691e3af466847b8b9178cdefb4 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 21 Nov 2025 10:37:39 +0100 Subject: [PATCH 08/20] [NAE-2266] Introduce active version of process - remove unused PetriNetService.evaluateRules method - remove the explicit rollback when saving process changes -> resolved in EE as transactions --- .../petrinet/service/PetriNetService.java | 38 +++---------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index 7b32c340292..3309755ae0f 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -12,7 +12,6 @@ import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetMappingService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetService; -import com.netgrif.application.engine.objects.event.events.Event; import com.netgrif.application.engine.objects.event.events.petrinet.ProcessDeleteEvent; import com.netgrif.application.engine.objects.event.events.petrinet.ProcessDeployEvent; import com.netgrif.application.engine.importer.service.Importer; @@ -238,21 +237,12 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp outcome.setOutcomes(eventService.runActions(newProcess.getPreUploadActions(), null, Optional.empty(), params)); publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.PRE)); + if (inactivatedProcess != null) { save(inactivatedProcess); } - try { - save(newProcess); - } catch (Exception rethrow) { - if (inactivatedProcess != null) { - // make sure there is always an active version - log.warn("Something unexpected happened while saving new version of process [{}]. Rolling back process version, that have been inactivated...", - newProcess.getIdentifier()); - inactivatedProcess.makeActive(); - save(inactivatedProcess); - } - throw rethrow; - } + save(newProcess); + outcome.setOutcomes(eventService.runActions(newProcess.getPostUploadActions(), null, Optional.empty(), params)); outcome.setNet(importedProcess.get()); publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.POST)); @@ -261,6 +251,7 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp @Override public MakeVersionActiveDTO makeVersionActive(String processId) { + // todo 2266 test log.info("Activating the process with id [{}]...", processId); PetriNet processToActivate = self.getPetriNet(processId); PetriNet processToInactivate = self.getActiveVersionByIdentifier(processToActivate.getIdentifier()); @@ -276,20 +267,8 @@ public MakeVersionActiveDTO makeVersionActive(String processId) { processToInactivate.makeInactive(); save(processToInactivate); } - - try { - processToActivate.makeActive(); - save(processToActivate); - } catch (Exception rethrow) { - if (processToInactivate != null) { - // make sure there is always an active version - log.warn("Something unexpected happened while activating process [{}]. Rolling back status of a version, that have been inactivated...", - processId); - processToInactivate.makeActive(); - save(processToInactivate); - } - throw rethrow; - } + processToActivate.makeActive(); + save(processToActivate); log.debug("Successfully activated process with ID [{}] of identifier [{}]", processToActivate.getStringId(), processToActivate.getIdentifier()); @@ -297,11 +276,6 @@ public MakeVersionActiveDTO makeVersionActive(String processId) { : processToInactivate.getStringId()); } - protected void evaluateRules(Event event) { - publisher.publishEvent(event); - - } - @Override public Optional save(PetriNet petriNet) { petriNet.initializeArcs(); From 47ba662d8fce5c8221240e63b9348ba4db68c57a Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 21 Nov 2025 11:24:50 +0100 Subject: [PATCH 09/20] [NAE-2266] Introduce active version of process - remove todos - implement PetriNetServiceTest.testMakeVersionActive --- .../petrinet/service/PetriNetService.java | 3 -- .../service/PetriNetServiceTest.groovy | 32 ++++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index 3309755ae0f..c75b3aef9e3 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -251,7 +251,6 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp @Override public MakeVersionActiveDTO makeVersionActive(String processId) { - // todo 2266 test log.info("Activating the process with id [{}]...", processId); PetriNet processToActivate = self.getPetriNet(processId); PetriNet processToInactivate = self.getActiveVersionByIdentifier(processToActivate.getIdentifier()); @@ -331,7 +330,6 @@ public List findAllById(List ids) { @Override @Cacheable(value = "petriNetActive", unless = "#result == null") public PetriNet getActiveVersionByIdentifier(String identifier) { - // todo 2266 test if (identifier == null) { return null; } @@ -341,7 +339,6 @@ public PetriNet getActiveVersionByIdentifier(String identifier) { @Override @Cacheable(value = "petriNetLatest", unless = "#result == null") public PetriNet getLatestVersionByIdentifier(String identifier) { - // todo 2266 test if (identifier == null) { return null; } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index c540bafcd78..5755494e44a 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -7,6 +7,7 @@ import com.netgrif.application.engine.elastic.domain.ElasticPetriNetRepository import com.netgrif.application.engine.ipc.TaskApiTest import com.netgrif.application.engine.objects.auth.domain.* import com.netgrif.application.engine.objects.auth.domain.enums.UserState +import com.netgrif.application.engine.objects.dto.response.petrinet.MakeVersionActiveDTO import com.netgrif.application.engine.objects.elastic.domain.ElasticPetriNet import com.netgrif.application.engine.objects.petrinet.domain.PetriNet import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch @@ -211,11 +212,40 @@ class PetriNetServiceTest { assert elasticPetriNetV5Optional.get().isVersionActive() } + @Test + void testMakeVersionActive() { + PetriNet petriNetV1 = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("1"), superCreator.loggedSuper).getNet() + PetriNet petriNetV2 = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper).getNet() + PetriNet petriNetV3 = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("3"), superCreator.loggedSuper).getNet() + assert !petriNetService.get(petriNetV1.getObjectId()).isVersionActive() + assert !petriNetService.get(petriNetV2.getObjectId()).isVersionActive() + assert petriNetService.get(petriNetV3.getObjectId()).isVersionActive() + + MakeVersionActiveDTO response = petriNetService.makeVersionActive(petriNetV2.getStringId()) + assert response != null + assert response.activatedProcessId() == petriNetV2.getStringId() + assert response.inactivatedProcessId() == petriNetV3.getStringId() + petriNetV2 = petriNetService.get(petriNetV2.getObjectId()) + assert !petriNetService.get(petriNetV1.getObjectId()).isVersionActive() + assert petriNetService.get(petriNetV2.getObjectId()).isVersionActive() + assert !petriNetService.get(petriNetV3.getObjectId()).isVersionActive() + + petriNetV2.makeInactive() + petriNetService.save(petriNetV2) + + response = petriNetService.makeVersionActive(petriNetV3.getStringId()) + assert response != null + assert response.activatedProcessId() == petriNetV3.getStringId() + assert response.inactivatedProcessId() == null + assert !petriNetService.get(petriNetV1.getObjectId()).isVersionActive() + assert !petriNetService.get(petriNetV2.getObjectId()).isVersionActive() + assert petriNetService.get(petriNetV3.getObjectId()).isVersionActive() + } + @Test void processSearch() { long processCount = petriNetRepository.count() - def user = userService.findUserByUsername(CUSTOMER_USER_MAIL, null) assert user != null && user.isPresent() importProcess(NET_FILE, superCreator.getLoggedSuper()) From 7e0c9b8910e7de4e672c2ef72389a38f69663de4 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 21 Nov 2025 13:55:52 +0100 Subject: [PATCH 10/20] [NAE-2266] Introduce active version of process - fix tests --- .../application/engine/petrinet/domain/PetriNetTest.groovy | 2 +- .../engine/petrinet/service/CachePetriNetServiceTest.groovy | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy index 19b9b76ec8b..f0e54646859 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/PetriNetTest.groovy @@ -136,7 +136,7 @@ class PetriNetTest { try { petriNetService.importPetriNet(netResource3.inputStream, VersionType.MAJOR, superCreator.loggedSuper) } catch (Exception e) { - assert e.getMessage() == "Provided Petri net version is already present in the system" + assert e.getMessage() == "A process [test] with such version [0.0.1] already exists" } } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy index 2f52400152d..a222b227b0b 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy @@ -67,13 +67,13 @@ class CachePetriNetServiceTest { @Test void cacheTest() { - assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get("processDeleteTest") == null + assert cacheManager.getCache(cacheProperties.getPetriNetActive()).get("processDeleteTest") == null ImportPetriNetEventOutcome testNetOptional = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) assert testNetOptional.getNet() != null PetriNet testNet = testNetOptional.getNet() - assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get(testNet.getIdentifier()) == null + assert cacheManager.getCache(cacheProperties.getPetriNetActive()).get(testNet.getIdentifier()) == null PetriNet test = petriNetService.getActiveVersionByIdentifier(testNet.getIdentifier()) - assert cacheManager.getCache(cacheProperties.getPetriNetNewest()).get(testNet.getIdentifier()).get().equals(test) + assert cacheManager.getCache(cacheProperties.getPetriNetActive()).get(testNet.getIdentifier()).get().equals(test) } } From 4670f33fb3b222442a484f011a910611cc223a84 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 21 Nov 2025 15:11:25 +0100 Subject: [PATCH 11/20] [NAE-2266] Introduce active version of process - split PetriNetService.save into two methods --- .../engine/petrinet/service/PetriNetService.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index c75b3aef9e3..befb673bb2f 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -239,9 +239,9 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp publisher.publishEvent(new ProcessDeployEvent(outcome, EventPhase.PRE)); if (inactivatedProcess != null) { - save(inactivatedProcess); + doSaveInternal(inactivatedProcess); } - save(newProcess); + doSaveInternal(newProcess); outcome.setOutcomes(eventService.runActions(newProcess.getPostUploadActions(), null, Optional.empty(), params)); outcome.setNet(importedProcess.get()); @@ -264,10 +264,10 @@ public MakeVersionActiveDTO makeVersionActive(String processId) { log.debug("Inactivating current active version of process with ID [{}] of identifier [{}]", processToInactivate.getStringId(), processToInactivate.getIdentifier()); processToInactivate.makeInactive(); - save(processToInactivate); + doSaveInternal(processToInactivate); } processToActivate.makeActive(); - save(processToActivate); + doSaveInternal(processToActivate); log.debug("Successfully activated process with ID [{}] of identifier [{}]", processToActivate.getStringId(), processToActivate.getIdentifier()); @@ -277,6 +277,10 @@ public MakeVersionActiveDTO makeVersionActive(String processId) { @Override public Optional save(PetriNet petriNet) { + return doSaveInternal(petriNet); + } + + protected final Optional doSaveInternal(PetriNet petriNet) { petriNet.initializeArcs(); this.evictCache(petriNet); petriNet = repository.save(petriNet); @@ -284,7 +288,7 @@ public Optional save(PetriNet petriNet) { try { elasticPetriNetService.indexNow(this.petriNetMappingService.transform(petriNet)); } catch (Exception e) { - log.error("Indexing failed [" + petriNet.getStringId() + "]", e); + log.error("Indexing failed [{}]", petriNet.getStringId(), e); } return Optional.of(petriNet); From cf0651a2d8e3ea90fd38a1f67d63fa5d82888071 Mon Sep 17 00:00:00 2001 From: chvostek Date: Mon, 24 Nov 2025 10:31:10 +0100 Subject: [PATCH 12/20] [NAE-2266] Introduce active version of process - rename version active attribute in PetriNet --- .../repositories/PetriNetRepository.java | 2 +- .../petrinet/service/PetriNetService.java | 2 +- .../service/PetriNetServiceTest.groovy | 36 +++++++++---------- .../elastic/domain/ElasticPetriNet.java | 6 ++-- .../objects/petrinet/domain/PetriNet.java | 4 +-- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java index ae445cbe9ae..bb1d1587ec2 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java @@ -36,7 +36,7 @@ public interface PetriNetRepository extends MongoRepository, Q /** * todo javadoc */ - PetriNet findByIdentifierAndIsVersionActive(String identifier, boolean isVersionActive); + PetriNet findByIdentifierAndVersionActive(String identifier, boolean versionActive); /** * Finds a paginated list of {@link PetriNet} entities by their identifier. diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index befb673bb2f..cf4326a483e 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -337,7 +337,7 @@ public PetriNet getActiveVersionByIdentifier(String identifier) { if (identifier == null) { return null; } - return repository.findByIdentifierAndIsVersionActive(identifier, true); + return repository.findByIdentifierAndVersionActive(identifier, true); } @Override diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index 5755494e44a..d283ffdc13f 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -153,7 +153,7 @@ class PetriNetServiceTest { ImportPetriNetEventOutcome outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) PetriNet petriNetV2 = outcome.getNet() assert petriNetV2 != null - assert petriNetV2.isVersionActive() + assert petriNetV2.versionActive() Version version = new Version() version.setMajor(2) assert petriNetV2.getVersion() == version @@ -188,28 +188,28 @@ class PetriNetServiceTest { petriNetV2.makeActive() petriNetV2 = petriNetService.save(petriNetV2).get() - assert petriNetV2.isVersionActive() + assert petriNetV2.versionActive() petriNetV4.makeInactive() petriNetV4 = petriNetService.save(petriNetV4).get() - assert !petriNetV4.isVersionActive() + assert !petriNetV4.versionActive() outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("5"), superCreator.loggedSuper) PetriNet petriNetV5 = outcome.getNet() assert petriNetV5 != null - assert !petriNetService.get(petriNetV2.getObjectId()).isVersionActive() - assert !petriNetService.get(petriNetV4.getObjectId()).isVersionActive() - assert petriNetV5.isVersionActive() + assert !petriNetService.get(petriNetV2.getObjectId()).versionActive() + assert !petriNetService.get(petriNetV4.getObjectId()).versionActive() + assert petriNetV5.versionActive() version = new Version() version.setMajor(5) assert petriNetV5.getVersion() == version Thread.sleep(5000) elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) - assert !elasticPetriNetV2Optional.get().isVersionActive() + assert !elasticPetriNetV2Optional.get().versionActive() elasticPetriNetV4Optional = elasticPetriNetRepository.findById(petriNetV4.stringId) - assert !elasticPetriNetV4Optional.get().isVersionActive() + assert !elasticPetriNetV4Optional.get().versionActive() Optional elasticPetriNetV5Optional = elasticPetriNetRepository.findById(petriNetV5.stringId) assert elasticPetriNetV5Optional.isPresent() - assert elasticPetriNetV5Optional.get().isVersionActive() + assert elasticPetriNetV5Optional.get().versionActive() } @Test @@ -217,18 +217,18 @@ class PetriNetServiceTest { PetriNet petriNetV1 = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("1"), superCreator.loggedSuper).getNet() PetriNet petriNetV2 = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper).getNet() PetriNet petriNetV3 = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("3"), superCreator.loggedSuper).getNet() - assert !petriNetService.get(petriNetV1.getObjectId()).isVersionActive() - assert !petriNetService.get(petriNetV2.getObjectId()).isVersionActive() - assert petriNetService.get(petriNetV3.getObjectId()).isVersionActive() + assert !petriNetService.get(petriNetV1.getObjectId()).versionActive() + assert !petriNetService.get(petriNetV2.getObjectId()).versionActive() + assert petriNetService.get(petriNetV3.getObjectId()).versionActive() MakeVersionActiveDTO response = petriNetService.makeVersionActive(petriNetV2.getStringId()) assert response != null assert response.activatedProcessId() == petriNetV2.getStringId() assert response.inactivatedProcessId() == petriNetV3.getStringId() petriNetV2 = petriNetService.get(petriNetV2.getObjectId()) - assert !petriNetService.get(petriNetV1.getObjectId()).isVersionActive() - assert petriNetService.get(petriNetV2.getObjectId()).isVersionActive() - assert !petriNetService.get(petriNetV3.getObjectId()).isVersionActive() + assert !petriNetService.get(petriNetV1.getObjectId()).versionActive() + assert petriNetService.get(petriNetV2.getObjectId()).versionActive() + assert !petriNetService.get(petriNetV3.getObjectId()).versionActive() petriNetV2.makeInactive() petriNetService.save(petriNetV2) @@ -237,9 +237,9 @@ class PetriNetServiceTest { assert response != null assert response.activatedProcessId() == petriNetV3.getStringId() assert response.inactivatedProcessId() == null - assert !petriNetService.get(petriNetV1.getObjectId()).isVersionActive() - assert !petriNetService.get(petriNetV2.getObjectId()).isVersionActive() - assert petriNetService.get(petriNetV3.getObjectId()).isVersionActive() + assert !petriNetService.get(petriNetV1.getObjectId()).versionActive() + assert !petriNetService.get(petriNetV2.getObjectId()).versionActive() + assert petriNetService.get(petriNetV3.getObjectId()).versionActive() } @Test diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java index 04a8177dc9d..5f86772a420 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticPetriNet.java @@ -24,7 +24,7 @@ public abstract class ElasticPetriNet { private Version version; - private boolean isVersionActive; + private boolean versionActive; private String uriNodeId; @@ -40,7 +40,7 @@ public ElasticPetriNet(PetriNet net) { this.id = net.getStringId(); this.identifier = net.getIdentifier(); this.version = net.getVersion(); - this.isVersionActive = net.isVersionActive(); + this.versionActive = net.isVersionActive(); this.uriNodeId = net.getUriNodeId(); this.title = this.transformToField(net.getTitle()); this.initials = net.getInitials(); @@ -49,7 +49,7 @@ public ElasticPetriNet(PetriNet net) { public void update(ElasticPetriNet net) { this.version = net.getVersion(); - this.isVersionActive = net.isVersionActive(); + this.versionActive = net.isVersionActive(); if (net.getUriNodeId() != null) { this.uriNodeId = net.getUriNodeId(); } diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java index 16e50f13854..a2d5627ac52 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/PetriNet.java @@ -76,7 +76,7 @@ public abstract class PetriNet extends PetriNetObject { @Getter @Setter @Indexed - private boolean isVersionActive; + private boolean versionActive; @Getter @Setter @@ -174,7 +174,7 @@ public PetriNet(PetriNet petriNet) { this.title = petriNet.getTitle(); this.importId = petriNet.getImportId(); this.version = petriNet.getVersion(); - this.isVersionActive = petriNet.isVersionActive(); + this.versionActive = petriNet.isVersionActive(); this.defaultCaseName = petriNet.getDefaultCaseName(); this.defaultCaseNameExpression = petriNet.getDefaultCaseNameExpression(); this.initials = petriNet.getInitials(); From 48e1411b3c0baeaa29c68e6af539f41d98a6d750 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 25 Nov 2025 10:47:33 +0100 Subject: [PATCH 13/20] [NAE-2266] Introduce active version of process - remove makeVersionActive API --- .../petrinet/service/PetriNetService.java | 27 ------------------- .../service/interfaces/IPetriNetService.java | 6 ----- .../petrinet/web/PetriNetController.java | 25 ----------------- .../petrinet/MakeVersionActiveDTO.java | 10 ------- 4 files changed, 68 deletions(-) delete mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/MakeVersionActiveDTO.java diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index cf4326a483e..947181aa9c4 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -5,7 +5,6 @@ import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.configuration.properties.CacheConfigurationProperties; import com.netgrif.application.engine.files.minio.StorageConfigurationProperties; -import com.netgrif.application.engine.objects.dto.response.petrinet.MakeVersionActiveDTO; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.ArcImportReference; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; @@ -249,32 +248,6 @@ public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionTyp return outcome; } - @Override - public MakeVersionActiveDTO makeVersionActive(String processId) { - log.info("Activating the process with id [{}]...", processId); - PetriNet processToActivate = self.getPetriNet(processId); - PetriNet processToInactivate = self.getActiveVersionByIdentifier(processToActivate.getIdentifier()); - - if (processToInactivate != null && processToInactivate.getStringId().equals(processToActivate.getStringId())) { - log.debug("The process to activate is already active. Nothing to do"); - return new MakeVersionActiveDTO(); - } - - if (processToInactivate != null) { - log.debug("Inactivating current active version of process with ID [{}] of identifier [{}]", - processToInactivate.getStringId(), processToInactivate.getIdentifier()); - processToInactivate.makeInactive(); - doSaveInternal(processToInactivate); - } - processToActivate.makeActive(); - doSaveInternal(processToActivate); - - log.debug("Successfully activated process with ID [{}] of identifier [{}]", processToActivate.getStringId(), - processToActivate.getIdentifier()); - return new MakeVersionActiveDTO(processToActivate.getStringId(), processToInactivate == null ? null - : processToInactivate.getStringId()); - } - @Override public Optional save(PetriNet petriNet) { return doSaveInternal(petriNet); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java index 245b62bacd7..a4494f1d55c 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java @@ -1,7 +1,6 @@ package com.netgrif.application.engine.petrinet.service.interfaces; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.objects.dto.response.petrinet.MakeVersionActiveDTO; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.objects.petrinet.domain.Transition; @@ -111,11 +110,6 @@ static DataFieldReference transformToReference(PetriNet net, Transition transiti */ ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser user, Map params) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException; - /** - * todo javadoc - */ - MakeVersionActiveDTO makeVersionActive(String processId); - /** * Saves a PetriNet object. * diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index aa001ebed19..eb9cb4f90f9 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -6,7 +6,6 @@ import com.netgrif.application.engine.eventoutcomes.LocalisedEventOutcomeFactory; import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.objects.dto.response.petrinet.MakeVersionActiveDTO; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.objects.petrinet.domain.VersionType; @@ -40,7 +39,6 @@ import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.PagedModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -122,29 +120,6 @@ public EntityModel importPetriNet( } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") - @Operation(summary = "Make the process active", - description = "Caller must have the ADMIN role. Makes the provided process active. The previous active version is inactivated.", - security = {@SecurityRequirement(name = "BasicAuth")}) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK. The response contains the IDs of process models, that have been activated and inactivated"), - @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), - @ApiResponse(responseCode = "404", description = "Process model is not found") - }) - @PostMapping(value = "/activate/{id}", produces = MediaTypes.HAL_JSON_VALUE) - public ResponseEntity makeVersionActive(@PathVariable("id") String processId) { - try { - MakeVersionActiveDTO response = service.makeVersionActive(processId); - return ResponseEntity.ok(response); - } catch (IllegalArgumentException e) { - log.error("The process with id [{}] was not found.", processId, e); - return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); - } catch (Exception e) { - log.error("Making process [{}] active failed: ", processId, e); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); - } - } - @Operation(summary = "Get all processes", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(produces = MediaTypes.HAL_JSON_VALUE) public ResponseEntity> getAll(@RequestParam(value = "indentifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Pageable pageable, Authentication auth, Locale locale) { diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/MakeVersionActiveDTO.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/MakeVersionActiveDTO.java deleted file mode 100644 index d4b414ab382..00000000000 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/MakeVersionActiveDTO.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.netgrif.application.engine.objects.dto.response.petrinet; - -import java.io.Serializable; - -public record MakeVersionActiveDTO(String activatedProcessId, String inactivatedProcessId) implements Serializable { - - public MakeVersionActiveDTO() { - this(null, null); - } -} From b30c88419ff4f4ca7723933998338a897a90a0f0 Mon Sep 17 00:00:00 2001 From: chvostek Date: Tue, 25 Nov 2025 11:48:14 +0100 Subject: [PATCH 14/20] [NAE-2266] Introduce active version of process - update PetriNetService.deletePetriNet to handle versionActive attribute - implement another test for process deletion --- .../petrinet/service/PetriNetService.java | 9 +++ .../service/PetriNetServiceTest.groovy | 72 +++++++++---------- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index 947181aa9c4..655ab4235c9 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -588,6 +588,15 @@ public void deletePetriNet(String processId, LoggedUser loggedUser, boolean forc repository.deleteBy_id(petriNet.getObjectId()); evictCache(petriNet); functionCacheService.reloadCachedFunctions(petriNet); + if (petriNet.isVersionActive()) { + PetriNet toBeActivated = self.getLatestVersionByIdentifier(petriNet.getIdentifier()); + if (toBeActivated != null) { + log.debug("The active version was removed. Activating the latest version of the process [{}] with id [{}]...", + toBeActivated.getIdentifier(), toBeActivated.getStringId()); + toBeActivated.makeActive(); + save(toBeActivated); + } + } publisher.publishEvent(new ProcessDeleteEvent(petriNet, EventPhase.POST)); } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index d283ffdc13f..6c1e17f1301 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -7,7 +7,6 @@ import com.netgrif.application.engine.elastic.domain.ElasticPetriNetRepository import com.netgrif.application.engine.ipc.TaskApiTest import com.netgrif.application.engine.objects.auth.domain.* import com.netgrif.application.engine.objects.auth.domain.enums.UserState -import com.netgrif.application.engine.objects.dto.response.petrinet.MakeVersionActiveDTO import com.netgrif.application.engine.objects.elastic.domain.ElasticPetriNet import com.netgrif.application.engine.objects.petrinet.domain.PetriNet import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch @@ -153,7 +152,7 @@ class PetriNetServiceTest { ImportPetriNetEventOutcome outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) PetriNet petriNetV2 = outcome.getNet() assert petriNetV2 != null - assert petriNetV2.versionActive() + assert petriNetV2.versionActive Version version = new Version() version.setMajor(2) assert petriNetV2.getVersion() == version @@ -188,58 +187,57 @@ class PetriNetServiceTest { petriNetV2.makeActive() petriNetV2 = petriNetService.save(petriNetV2).get() - assert petriNetV2.versionActive() + assert petriNetV2.versionActive petriNetV4.makeInactive() petriNetV4 = petriNetService.save(petriNetV4).get() - assert !petriNetV4.versionActive() + assert !petriNetV4.versionActive outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("5"), superCreator.loggedSuper) PetriNet petriNetV5 = outcome.getNet() assert petriNetV5 != null - assert !petriNetService.get(petriNetV2.getObjectId()).versionActive() - assert !petriNetService.get(petriNetV4.getObjectId()).versionActive() - assert petriNetV5.versionActive() + assert !petriNetService.get(petriNetV2.getObjectId()).versionActive + assert !petriNetService.get(petriNetV4.getObjectId()).versionActive + assert petriNetV5.versionActive version = new Version() version.setMajor(5) assert petriNetV5.getVersion() == version Thread.sleep(5000) elasticPetriNetV2Optional = elasticPetriNetRepository.findById(petriNetV2.stringId) - assert !elasticPetriNetV2Optional.get().versionActive() + assert !elasticPetriNetV2Optional.get().versionActive elasticPetriNetV4Optional = elasticPetriNetRepository.findById(petriNetV4.stringId) - assert !elasticPetriNetV4Optional.get().versionActive() + assert !elasticPetriNetV4Optional.get().versionActive Optional elasticPetriNetV5Optional = elasticPetriNetRepository.findById(petriNetV5.stringId) assert elasticPetriNetV5Optional.isPresent() - assert elasticPetriNetV5Optional.get().versionActive() + assert elasticPetriNetV5Optional.get().versionActive } @Test - void testMakeVersionActive() { - PetriNet petriNetV1 = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("1"), superCreator.loggedSuper).getNet() - PetriNet petriNetV2 = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper).getNet() - PetriNet petriNetV3 = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("3"), superCreator.loggedSuper).getNet() - assert !petriNetService.get(petriNetV1.getObjectId()).versionActive() - assert !petriNetService.get(petriNetV2.getObjectId()).versionActive() - assert petriNetService.get(petriNetV3.getObjectId()).versionActive() - - MakeVersionActiveDTO response = petriNetService.makeVersionActive(petriNetV2.getStringId()) - assert response != null - assert response.activatedProcessId() == petriNetV2.getStringId() - assert response.inactivatedProcessId() == petriNetV3.getStringId() - petriNetV2 = petriNetService.get(petriNetV2.getObjectId()) - assert !petriNetService.get(petriNetV1.getObjectId()).versionActive() - assert petriNetService.get(petriNetV2.getObjectId()).versionActive() - assert !petriNetService.get(petriNetV3.getObjectId()).versionActive() - - petriNetV2.makeInactive() - petriNetService.save(petriNetV2) - - response = petriNetService.makeVersionActive(petriNetV3.getStringId()) - assert response != null - assert response.activatedProcessId() == petriNetV3.getStringId() - assert response.inactivatedProcessId() == null - assert !petriNetService.get(petriNetV1.getObjectId()).versionActive() - assert !petriNetService.get(petriNetV2.getObjectId()).versionActive() - assert petriNetService.get(petriNetV3.getObjectId()).versionActive() + void testVersionActiveOnDelete() { + ImportPetriNetEventOutcome outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("1"), superCreator.loggedSuper) + PetriNet processV1 = outcome.getNet() + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("2"), superCreator.loggedSuper) + PetriNet processV2 = outcome.getNet() + outcome = importProcess(VERSION_PROCESS_FILE_FORMAT.formatted("3"), superCreator.loggedSuper) + PetriNet processV3 = outcome.getNet() + + assert !petriNetService.get(processV1.getObjectId()).versionActive + assert !petriNetService.get(processV2.getObjectId()).versionActive + assert petriNetService.get(processV3.getObjectId()).versionActive + + petriNetService.deletePetriNet(processV2.getStringId(), superCreator.loggedSuper) + + assert petriNetRepository.findById(processV2.getStringId()).isEmpty() + assert !petriNetService.get(processV1.getObjectId()).versionActive + assert petriNetService.get(processV3.getObjectId()).versionActive + + petriNetService.deletePetriNet(processV3.getStringId(), superCreator.loggedSuper) + + assert petriNetRepository.findById(processV3.getStringId()).isEmpty() + assert petriNetService.get(processV1.getObjectId()).versionActive + + petriNetService.deletePetriNet(processV1.getStringId(), superCreator.loggedSuper) + + assert petriNetRepository.findById(processV1.getStringId()).isEmpty() } @Test From d7705b2de541bf981a4d593c8b03d77dea2bb74c Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 27 Nov 2025 14:20:38 +0100 Subject: [PATCH 15/20] [NAE-2266] Introduce active version of process - mark methods import petriNet method transactional --- .../application/engine/petrinet/service/PetriNetService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index 655ab4235c9..c3eabbfcf18 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -178,16 +178,19 @@ public List get(List petriNetIds) { @Override @Deprecated + @Transactional public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, String releaseType, LoggedUser author) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { return importPetriNet(xmlFile, VersionType.valueOf(releaseType.trim().toUpperCase()), author); } @Override + @Transactional public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { return importPetriNet(xmlFile, releaseType, author, new HashMap<>()); } @Override + @Transactional public ImportPetriNetEventOutcome importPetriNet(InputStream xmlFile, VersionType releaseType, LoggedUser author, Map params) throws IOException, MissingPetriNetMetaDataException, MissingIconKeyException { ImportPetriNetEventOutcome outcome = new ImportPetriNetEventOutcome(); ByteArrayOutputStream xmlCopy = new ByteArrayOutputStream(); From 2654b7d631ab9f916b0aa77b9bd192b7fedfadf2 Mon Sep 17 00:00:00 2001 From: chvostek Date: Thu, 27 Nov 2025 14:29:33 +0100 Subject: [PATCH 16/20] [NAE-2266] Introduce active version of process - update javadoc --- .../domain/repositories/PetriNetRepository.java | 6 +++++- .../service/interfaces/IPetriNetService.java | 1 - .../objects/petrinet/domain/version/Version.java | 16 ++++++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java index bb1d1587ec2..41d53b6f0c2 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/domain/repositories/PetriNetRepository.java @@ -34,7 +34,11 @@ public interface PetriNetRepository extends MongoRepository, Q PetriNet findByIdentifierAndVersion(String identifier, Version version); /** - * todo javadoc + * Finds a {@link PetriNet} entity by its identifier and versionActive attribute + * + * @param identifier the unique identifier of the PetriNet. + * @param versionActive if true, the active version will be found, otherwise the inactive version + * @return the {@link PetriNet} entity matching the given identifier and versionActive attribute, or {@code null} if none found. */ PetriNet findByIdentifierAndVersionActive(String identifier, boolean versionActive); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java index a4494f1d55c..7ec7bb53bf3 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java @@ -154,7 +154,6 @@ static DataFieldReference transformToReference(PetriNet net, Transition transiti /** * Retrieves the active version of a {@link PetriNet} by its identifier. - * todo javadoc isversionactive logic * * @param identifier the unique identifier of the PetriNet * @return the active version of the {@link PetriNet} matching the provided identifier or null if not found diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java index 0592ab8e212..50dd1f5481d 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/version/Version.java @@ -53,10 +53,10 @@ public void increment(VersionType type) { } /** - * todo javadoc - * 0 equals - * <0 this < other - * >0 this > other + * Compares this version to the other version + * + * @param other other version to be compared with + * @return 0 if the versions equal, <0 if this is lower than other, >0 if this is higher than other */ public int compareTo(Version other) { if (this.major != other.major) { @@ -69,14 +69,18 @@ public int compareTo(Version other) { } /** - * todo javadoc + * Checks if this version is higher than the other + * @param other other version to be compared with + * @return true if this version is higher than the other */ public boolean isHigherThan(Version other) { return compareTo(other) > 0; } /** - * todo javadoc + * Checks if this version is lower than the other + * @param other other version to be compared with + * @return true if this version is lower than the other */ public boolean isLowerThan(Version other) { return compareTo(other) < 0; From 61f9b2ec2d2948fac72797f042673741c643951e Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 28 Nov 2025 10:17:24 +0100 Subject: [PATCH 17/20] [NAE-2266] Introduce active version of process - add null checks --- .../domain/dataset/logic/action/ActionDelegate.groovy | 4 ++++ .../logic/action/delegate/RoleActionDelegate.groovy | 6 ++++++ .../engine/menu/services/DashboardItemServiceImpl.java | 7 ++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index 9647d2d2376..273dce5e927 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -2442,6 +2442,10 @@ class ActionDelegate { temp.put(entry.value, petriNetService.getActiveVersionByIdentifier(entry.value)) } PetriNet net = temp[entry.value] + if (net == null) { + throw new IllegalArgumentException("The process with identifier [%s] could not be found when collecting roles." + .formatted(entry.value)) + } ProcessRole role = net.roles.find { it.value.importId == entry.key }.value return [(role.importId + ":" + net.identifier), ("$role.name ($net.title)" as String)] } diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy index da2f0806ff0..a1b8e7b8dbc 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/delegate/RoleActionDelegate.groovy @@ -52,6 +52,9 @@ class RoleActionDelegate extends AbstractActionDelegate { AbstractUser assignRole(String roleImportId, String petriNetIdentifier, AbstractUser user = affectedUser) { PetriNet petriNet = petriNetService.getActiveVersionByIdentifier(petriNetIdentifier) + if (petriNet == null) { + throw new IllegalArgumentException("The process with identifier [%s] could not be found".formatted(petriNetIdentifier)) + } assignRole(roleImportId, user, petriNet) } @@ -76,6 +79,9 @@ class RoleActionDelegate extends AbstractActionDelegate { AbstractUser removeRole(String roleImportId, String petriNetIdentifier, AbstractUser user = affectedUser) { PetriNet petriNet = petriNetService.getActiveVersionByIdentifier(petriNetIdentifier) + if (petriNet == null) { + throw new IllegalArgumentException("The process with identifier [%s] could not be found".formatted(petriNetIdentifier)) + } removeRole(roleImportId, user, petriNet) } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java index 8d40f6cb91b..aeba0a4e6c8 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java @@ -8,6 +8,7 @@ import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.objects.utils.MenuItemUtils; import com.netgrif.application.engine.objects.workflow.domain.Case; @@ -62,7 +63,11 @@ public Case getOrCreate(DashboardItemBody body) throws TransitionNotExecutableEx } LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()); - itemCase = workflowService.createCase(petriNetService.getActiveVersionByIdentifier(DashboardItemConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); + PetriNet petriNet = petriNetService.getActiveVersionByIdentifier(DashboardItemConstants.PROCESS_IDENTIFIER); + if (petriNet == null) { + throw new IllegalStateException("Dashboard item process not found or not active"); + } + itemCase = workflowService.createCase(petriNet.getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); ToDataSetOutcome outcome = body.toDataSet(); itemCase = setDataWithExecute(itemCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet()); return itemCase; From 289de0fa6efa8785a456bac245de4298f7950215 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 28 Nov 2025 10:19:16 +0100 Subject: [PATCH 18/20] [NAE-2266] Introduce active version of process - add null check --- .../menu/services/DashboardManagementServiceImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java index a4497831164..43268406719 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java @@ -9,6 +9,7 @@ import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; +import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.objects.utils.MenuItemUtils; import com.netgrif.application.engine.objects.workflow.domain.Case; @@ -64,7 +65,11 @@ public Case createDashboardManagement(DashboardManagementBody body) throws Trans } addReferencedMenuItems(body); LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()); - managementCase = workflowService.createCase(petriNetService.getActiveVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER).getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); + PetriNet petriNet = petriNetService.getActiveVersionByIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER); + if (petriNet == null) { + throw new IllegalStateException("Dashboard management process not found or not active"); + } + managementCase = workflowService.createCase(petriNet.getStringId(), body.getName().getDefaultValue(), "", loggedUser).getCase(); ToDataSetOutcome outcome = body.toDataSet(); managementCase = setDataWithExecute(managementCase, DashboardItemConstants.TASK_CONFIGURE, outcome.getDataSet()); return managementCase; From e9ef49401b463c62953596f633c317e0c49cdbd9 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 28 Nov 2025 10:21:04 +0100 Subject: [PATCH 19/20] [NAE-2266] Introduce active version of process - update javadoc --- .../engine/petrinet/service/interfaces/IPetriNetService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java index 7ec7bb53bf3..a1c066b1439 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java @@ -164,7 +164,7 @@ static DataFieldReference transformToReference(PetriNet net, Transition transiti * Retrieves the latest version of a {@link PetriNet} by its identifier. * * @param identifier the unique identifier of the PetriNet - * @return the latest version of the {@link PetriNet} matching the provided identifier + * @return the latest version of the {@link PetriNet} matching the provided identifier or null if not found */ PetriNet getLatestVersionByIdentifier(String identifier); From 2274d62d3a216fcc21a56b789bcdd71c263e3908 Mon Sep 17 00:00:00 2001 From: chvostek Date: Fri, 28 Nov 2025 10:25:44 +0100 Subject: [PATCH 20/20] [NAE-2266] Introduce active version of process - add null check --- .../engine/workflow/service/FilterImportExportService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java index 54dfed8b6cc..cfc56b64685 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java @@ -267,6 +267,9 @@ public void changeFilterField(Collection filterFields) { Task importedFilterTask = taskService.findOne(f); Case filterCase = workflowService.findOne(importedFilterTask.getCaseId()); PetriNet filterNet = petriNetService.getActiveVersionByIdentifier(FILTER_NET_IDENTIFIER); + if (filterNet == null) { + throw new IllegalStateException("No filter process found or active"); + } List requiredNets = filterCase.getDataSet().get(FIELD_FILTER).getAllowedNets(); List currentNets = petriNetService.getExistingPetriNetIdentifiersFromIdentifiersList(requiredNets); if (currentNets.size() < requiredNets.size()) {