Skip to content

Conversation

@renczesstefan
Copy link
Member

@renczesstefan renczesstefan commented Jun 17, 2025

Description

Removal of UriNode concept.

Implements NAE-2125

Dependencies

No new dependencies were introduced.

Third party dependencies

No new dependencies were introduced.

Blocking Pull requests

There are no dependencies on other PR.

How Has Been This Tested?

This was tested manually and with unit tests.

Test Configuration

Name Tested on
OS macOS Sequoia 15.3.1
Runtime Java 21
Dependency Manager Maven 3.9.9n
Framework version Spring Boot 3.2.5
Run parameters
Other configuration

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • My changes have been checked, personally or remotely, with @...
  • I have commented my code, particularly in hard-to-understand areas
  • I have resolved all conflicts with the target branch of the PR
  • I have updated and synced my code with the target branch
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes:
    • Lint test
    • Unit tests
    • Integration tests
  • I have checked my contribution with code analysis tools:
  • I have made corresponding changes to the documentation:
    • Developer documentation
    • User Guides
    • Migration Guides

Summary by CodeRabbit

  • Refactor

    • Removed all functionality and dependencies related to URI node management and the URI service across the application.
    • Updated menu item handling to use string paths with a standardized separator instead of URI nodes.
    • Simplified process and service interfaces by removing URI-related parameters and methods.
    • Renamed fields and constructors in menu item models to reflect path-based logic.
    • Cleaned up and removed related controllers, configuration, and test classes.
    • Removed URI node ID fields from domain and elastic case models.
    • Updated import and creation flows to handle Petri nets without URI node references.
  • Bug Fixes

    • Standardized path separator usage for menu item operations.
  • Tests

    • Removed and updated tests that depended on URI node functionality.
  • Chores

    • Cleaned up unused code, fields, and configuration related to URI nodes and services.

This commit removes the entire UriService, its related interfaces, controllers, configuration, tests, and associated functionality. The changes streamline the codebase by eliminating unused URI Node management logic and legacy features.
Introduce a protected evaluateRules method that publishes events using the publisher. This allows for better modular handling of event-driven logic within PetriNetService.
@coderabbitai
Copy link

coderabbitai bot commented Jun 17, 2025

Walkthrough

This change removes the entire URI node infrastructure from the application engine. All code, interfaces, services, controllers, and tests related to UriNode and IUriService are deleted. All usages of URI node IDs are removed from domain objects, APIs, repositories, and process definitions. URI path handling is refactored to use plain string manipulation with a standardized separator.

Changes

Files/Paths (grouped) Change Summary
.../petrinet/service/UriService.java
.../petrinet/service/interfaces/IUriService.java
Deleted URI service implementation and interface.
.../petrinet/web/UriController.java
.../petrinet/web/responsebodies/UriNodeResource.java
.../responsebodies/UriNodeResources.java
Deleted URI node REST controller and HAL resource wrappers.
.../configuration/UriServiceConfiguration.java
.../startup/runner/UriRunner.java
Deleted Spring configuration and startup runner for URI service.
.../petrinet/domain/dataset/logic/action/ActionDelegate.groovy Refactored to remove all IUriService and UriNode usage; switched to string-based path handling.
.../startup/ImportHelper.groovy Removed uriNodeId parameter from createNet methods; no longer uses uriService.
.../petrinet/service/PetriNetService.java
.../petrinet/service/interfaces/IPetriNetService.java
Removed all uriNodeId-related logic and overloads from PetriNet service and interface.
.../petrinet/web/PetriNetController.java Removed uriNodeId parameter from importPetriNet endpoint.
.../elastic/service/ElasticCaseService.java
.../elastic/service/interfaces/IElasticCaseService.java
Removed methods for finding uriNodeId in ElasticCase service and interface.
.../workflow/domain/repositories/CaseRepository.java Removed query method for cases by uriNodeId.
.../workflow/service/WorkflowService.java
.../workflow/service/interfaces/IWorkflowService.java
Removed method for finding cases by uriNodeId; removed setting uriNodeId in case creation.
.../workflow/domain/Case.java
.../elastic/domain/ElasticCase.java
.../adapter/spring/elastic/domain/ElasticCase.java
Removed uriNodeId field, setter, and related methods from Case and ElasticCase classes.
.../workflow/domain/menu/MenuItemBody.java Renamed field and constructor parameter from uri to path.
.../workflow/domain/menu/MenuItemConstants.java Added PATH_SEPARATOR constant for path string operations.
.../petriNets/engine-processes/preference_item.xml Replaced dynamic URI separator and node lookups with direct string operations and "/" separator.
.../TestHelper.groovy
.../action/MenuItemApiTest.groovy
.../petrinet/service/PetriNetServiceTest.groovy
.../petrinet/service/UriServiceTest.groovy
.../workflow/WorkflowServiceTest.groovy
.../workflow/service/TaskServiceTest.java
Removed all test code relying on URI service, UriRunner, or uriNodeId fields.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ActionDelegate
    participant DataSet

    Client->>ActionDelegate: createMenuItem(body)
    ActionDelegate->>ActionDelegate: Construct path string using PATH_SEPARATOR
    ActionDelegate->>DataSet: Store path as string in dataset
    Note over ActionDelegate,DataSet: No UriNode or IUriService involved
Loading

Suggested labels

Small


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d3ad8a and f0c23d0.

📒 Files selected for processing (1)
  • application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (16 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Test
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai bot added the Small label Jun 17, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🔭 Outside diff range comments (2)
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (2)

34-38: Whole test class is @Disabled – risk of silently rotting code

With the removal of UriNode the test was disabled instead of being adapted.
Leaving a key integration test muted will hide regressions. Either:

  • Update the test to the new path semantics and re-enable it, or
  • Delete the file entirely if the scenarios are covered elsewhere.

Retaining a disabled test adds maintenance cost without benefit.


114-121: Field name still uses legacy uri

The data-set map key is "uri", but the codebase migrated to "path".
Keeping the old key undermines the refactor and will break ActionDelegate once the test
is re-enabled.

-        "uri": "/netgrif/test_new",
+        "path": "/netgrif/test_new",
🧹 Nitpick comments (8)
application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (2)

94-99: Hard-coded path separator – use the newly introduced constant

"/netgrif/test" is built with a magic "/". Prefer the canonical separator:

- "/netgrif/test"
+ "${MenuItemConstants.PATH_SEPARATOR.attributeId}netgrif${MenuItemConstants.PATH_SEPARATOR.attributeId}test"

This ensures future changes to the separator propagate automatically.


79-88: Repeated Thread.sleep – replace with polling

Thread.sleep introduces flaky tests and inflates the execution time. Switch to Awaitility or a simple poll loop with timeout.

Awaitility.await()
         .atMost(Duration.ofSeconds(5))
         .until(() -> condition());
nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (1)

79-108: Constructor explosion – prefer builder over 6-arg ctors

Six overloaded constructors make the API error-prone. Lombok’s @Builder (or a manual builder) would convey intent better and allow optional parameters:

@Builder
public class MenuItemBody { ... }

This will also keep binary compatibility when further attributes are added.

application-engine/src/main/resources/petriNets/engine-processes/preference_item.xml (2)

158-168: Avoid silent use of hard-coded “/”; reuse the central separator constant.

The surrounding refactor introduced MenuItemConstants.PATH_SEPARATOR (value “/”).
For consistency and future-proofing, build newUri with that constant instead of the literal slash.

-String newUri = moveDestUri.value.join("/")
+String newUri = moveDestUri.value.join(MenuItemConstants.PATH_SEPARATOR)

251-253: Micro-optimisation: avoid repeated lastIndexOf on immutable string.

nodePath.value is evaluated twice. Cache it to a local variable for clarity and a tiny perf win.

-def idx = nodePath.value.lastIndexOf("/")
-return nodePath.value.substring(idx + 1)
+def path = nodePath.value
+def idx  = path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR)
+return path.substring(idx + 1)
application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java (1)

275-278: Minor: unnecessary list copy.

repository.findAllById(ids) already returns a mutable List; wrapping it in a new ArrayList is redundant.

-return new ArrayList<>(repository.findAllById(ids));
+return repository.findAllById(ids);
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (2)

2164-2171: nameFromPath returns the slash-prefixed segment

substring(lastIndexOf('/')) keeps the leading slash (e.g. "/folder").
Downstream code (option lists, display names) probably expects just "folder".
Consider +1 to drop the separator to avoid awkward labels.

-    return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId))
+    return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId) + 1)

2794-2809: Edge cases in splitUriPath

  1. path.split("/") returns ["", "folder"] for "/folder", so replacing index 0 works, but multiple consecutive slashes or trailing slash ("/folder/") yield empty tokens you don’t normalise.
  2. Throwing IllegalArgumentException for any non-root path that splits to length 0 is unreachable; consider removing.

Recommend using Paths.get(...).normalize() or manual filtering of empty elements for robustness.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb581e3 and af13957.

📒 Files selected for processing (29)
  • application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (11 hunks)
  • application-engine/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/UriServiceConfiguration.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticCaseService.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java (3 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/UriService.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IUriService.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (1 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/UriController.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/UriNodeResource.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/UriNodeResources.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/UriRunner.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepository.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java (0 hunks)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowService.java (0 hunks)
  • application-engine/src/main/resources/petriNets/engine-processes/preference_item.xml (3 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy (0 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/action/MenuItemApiTest.groovy (2 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy (0 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/UriServiceTest.groovy (0 hunks)
  • application-engine/src/test/groovy/com/netgrif/application/engine/workflow/WorkflowServiceTest.groovy (0 hunks)
  • application-engine/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java (0 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java (0 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/Case.java (0 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemBody.java (2 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java (1 hunks)
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/ElasticCase.java (0 hunks)
💤 Files with no reviewable changes (21)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepository.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowService.java
  • application-engine/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/ElasticCase.java
  • application-engine/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/interfaces/IElasticCaseService.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/UriNodeResources.java
  • application-engine/src/test/groovy/com/netgrif/application/engine/workflow/WorkflowServiceTest.groovy
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/UriServiceConfiguration.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetService.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/Case.java
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/UriRunner.java
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/UriServiceTest.groovy
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/UriNodeResource.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IUriService.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/UriService.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/UriController.java
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: task-list-completed
  • GitHub Check: Build
  • GitHub Check: task-list-completed
🔇 Additional comments (3)
application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java (1)

111-113: Resource leak – input stream should be closed

multipartFile.getInputStream() is never closed. Wrap with try-with-resources, or pass the MultipartFile directly to the service to let it take ownership.

application-engine/src/main/resources/petriNets/engine-processes/preference_item.xml (1)

190-196: ```shell
#!/usr/bin/env bash
set -e

echo "Searching for lingering uriService references in process definitions..."
rg "uriService" -n application-engine/src/main/resources


</details>
<details>
<summary>application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java (1)</summary>

`283-288`: **Java 21 `List#getFirst()` is OK – verify toolchain.**

`getFirst()` requires JDK 21. The build matrix states Java 21, but CI or downstream consumers must also compile with 21+. Double-check before merge.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment on lines 109 to 113
Authentication auth, Locale locale) throws MissingPetriNetMetaDataException, MissingIconKeyException {
try {
String decodedUriNodeId = new String(Base64.decodeBase64(uriNodeId));
VersionType release = releaseType == null ? VersionType.MAJOR : VersionType.valueOf(releaseType.trim().toUpperCase());
ImportPetriNetEventOutcome importPetriNetOutcome = service.importPetriNet(multipartFile.getInputStream(), release, (LoggedUser) auth.getPrincipal(), decodedUriNodeId);
ImportPetriNetEventOutcome importPetriNetOutcome = service.importPetriNet(multipartFile.getInputStream(), release, (LoggedUser) auth.getPrincipal());
return EventOutcomeWithMessageResource.successMessage("Petri net " + multipartFile.getOriginalFilename() + " imported successfully",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Possible IllegalArgumentException on invalid meta value

VersionType.valueOf(releaseType.trim().toUpperCase()) will throw IllegalArgumentException
for unexpected input, resulting in a 500 error. Convert it to a controlled 400 response:

- VersionType release = releaseType == null ? VersionType.MAJOR : VersionType.valueOf(releaseType.trim().toUpperCase());
+ VersionType release;
+ try {
+     release = releaseType == null
+             ? VersionType.MAJOR
+             : VersionType.valueOf(releaseType.trim().toUpperCase());
+ } catch (IllegalArgumentException ex) {
+     return EventOutcomeWithMessageResource.errorMessage("Unknown meta version type: " + releaseType);
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Authentication auth, Locale locale) throws MissingPetriNetMetaDataException, MissingIconKeyException {
try {
String decodedUriNodeId = new String(Base64.decodeBase64(uriNodeId));
VersionType release = releaseType == null ? VersionType.MAJOR : VersionType.valueOf(releaseType.trim().toUpperCase());
ImportPetriNetEventOutcome importPetriNetOutcome = service.importPetriNet(multipartFile.getInputStream(), release, (LoggedUser) auth.getPrincipal(), decodedUriNodeId);
ImportPetriNetEventOutcome importPetriNetOutcome = service.importPetriNet(multipartFile.getInputStream(), release, (LoggedUser) auth.getPrincipal());
return EventOutcomeWithMessageResource.successMessage("Petri net " + multipartFile.getOriginalFilename() + " imported successfully",
Authentication auth, Locale locale) throws MissingPetriNetMetaDataException, MissingIconKeyException {
try {
VersionType release;
try {
release = releaseType == null
? VersionType.MAJOR
: VersionType.valueOf(releaseType.trim().toUpperCase());
} catch (IllegalArgumentException ex) {
return EventOutcomeWithMessageResource.errorMessage("Unknown meta version type: " + releaseType);
}
ImportPetriNetEventOutcome importPetriNetOutcome = service.importPetriNet(
multipartFile.getInputStream(),
release,
(LoggedUser) auth.getPrincipal()
);
return EventOutcomeWithMessageResource.successMessage(
"Petri net " + multipartFile.getOriginalFilename() + " imported successfully",
🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java
around lines 109 to 113, the call to VersionType.valueOf with releaseType can
throw an IllegalArgumentException if the input is invalid, causing a 500 error.
To fix this, catch the IllegalArgumentException when parsing releaseType, and
instead return a controlled 400 Bad Request response indicating the invalid
input. This prevents server errors and provides clearer feedback to the client.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IllegalArgumentException will be added to enclosing try catch block.

Corrected a misspelled variable `pathNUame` to `pathName` in the `getOrCreateFolderItem` method. This fixes an issue where folder creation logic could break due to the typo.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (1)

2117-2122: createNodePath still produces “//” for already-sanitised paths

This was reported in a previous review and the risky branch is unchanged.
If path is "/foo/" (ends with separator but is not the root) the else
appends another /, yielding "/foo//bar".

(See past review around lines 2117-2123.)

Please normalise the incoming path (or trim the trailing separator) before concatenation.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af13957 and 5ae20f5.

📒 Files selected for processing (1)
  • application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy (11 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: Build
  • GitHub Check: task-list-completed

Comment on lines 2089 to 2103
Case parentItemCase = getOrCreateFolderItem(body.path)
I18nString newName = body.menuName ?: (body.filter?.dataSet[FILTER_FIELD_I18N_FILTER_NAME].value as I18nString)

Case menuItemCase = createCase(FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER, newName?.defaultValue)
menuItemCase.setUriNodeId(uriService.findByUri(body.uri).stringId)
menuItemCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_ALLOWED_ROLES.attributeId].options = body.allowedRoles
menuItemCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_BANNED_ROLES.attributeId].options = body.bannedRoles
if (parentItemCase != null) {
parentItemCase = appendChildCaseIdAndSave(parentItemCase, menuItemCase.stringId)
}
menuItemCase = workflowService.save(menuItemCase)
Task newItemTask = taskService.findOne(menuItemCase.tasks.find { it.transition == MenuItemConstants.PREFERENCE_ITEM_FIELD_INIT_TRANS_ID.attributeId }.task)
String nodePath = createNodePath(body.uri, sanitizedIdentifier)
uriService.getOrCreate(nodePath, UriContentType.CASE)
String nodePath = createNodePath(body.path, sanitizedIdentifier)

newItemTask = assignTask(newItemTask)
setData(newItemTask, body.toDataSet(parentItemCase.stringId, nodePath))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Possible NullPointerException when body.path == "/"

getOrCreateFolderItem("/") legitimately returns null (root has no folder case).
parentItemCase is dereferenced unconditionally a few lines later:

setData(newItemTask, body.toDataSet(parentItemCase.stringId, nodePath))

If the path is root, the application crashes before the item is stored.

-        setData(newItemTask, body.toDataSet(parentItemCase.stringId, nodePath))
+        // root has no parent – pass null instead of exploding
+        setData(newItemTask, body.toDataSet(parentItemCase?.stringId, nodePath))
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
around lines 2089 to 2103, the variable parentItemCase can be null when
body.path is "/", causing a NullPointerException when accessing
parentItemCase.stringId. To fix this, add a null check before dereferencing
parentItemCase.stringId in the call to body.toDataSet, and handle the root path
case appropriately by passing a safe value or adjusting the logic to avoid using
parentItemCase.stringId when parentItemCase is null.

Comment on lines 2163 to 2171
protected String nameFromPath(String path) {
if (path == null || path == MenuItemConstants.PATH_SEPARATOR.attributeId || path.length() == 0) {
return ""
}
if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId) == 0) {
return path.replace(MenuItemConstants.PATH_SEPARATOR.attributeId, "")
}
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

nameFromPath returns the separator ("/b" instead of "b").

substring(lastIndex) keeps the leading slash.
Down-stream calls treat the value as folder name – the extra / breaks look-ups
and produces malformed titles.

-        return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId))
+        return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId) + 1)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
protected String nameFromPath(String path) {
if (path == null || path == MenuItemConstants.PATH_SEPARATOR.attributeId || path.length() == 0) {
return ""
}
if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId) == 0) {
return path.replace(MenuItemConstants.PATH_SEPARATOR.attributeId, "")
}
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId))
}
protected String nameFromPath(String path) {
if (path == null || path == MenuItemConstants.PATH_SEPARATOR.attributeId || path.length() == 0) {
return ""
}
if (path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId) == 0) {
return path.replace(MenuItemConstants.PATH_SEPARATOR.attributeId, "")
}
return path.substring(path.lastIndexOf(MenuItemConstants.PATH_SEPARATOR.attributeId) + 1)
}
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
around lines 2163 to 2171, the method nameFromPath returns a string starting
with the path separator because substring is called with lastIndexOf only, which
includes the separator. To fix this, adjust the substring call to start from
lastIndexOf plus one, so the returned name excludes the leading separator and
downstream folder name look-ups work correctly.

Comment on lines 2822 to 2828
Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$path\"")
Set<String> childrenIds = caseByPath.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as Set
if (!childrenIds.isEmpty()) {
for (String id : childrenIds) {
UriNode childNode = uriService.findById(id)
options.put(childNode.name, new I18nString(childNode.name))
Case childFolderCase = workflowService.findOne(id)
options.put(childFolderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_NAME.attributeId].value as String, new I18nString(childFolderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_NAME.attributeId].value as String))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Null-safety when collecting children options

findCaseElastic(..) may return null – e.g. an empty tree or wrong path.
Current code dereferences caseByPath unguarded, causing NPE during option
generation.

-        Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$path\"")
-        Set<String> childrenIds = caseByPath.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as Set
-        if (!childrenIds.isEmpty()) {
+        Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$path\"")
+        if (caseByPath) {
+            Set<String> childrenIds = caseByPath.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as Set
+            if (!childrenIds.isEmpty()) {
                 …
             }
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$path\"")
Set<String> childrenIds = caseByPath.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as Set
if (!childrenIds.isEmpty()) {
for (String id : childrenIds) {
UriNode childNode = uriService.findById(id)
options.put(childNode.name, new I18nString(childNode.name))
Case childFolderCase = workflowService.findOne(id)
options.put(childFolderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_NAME.attributeId].value as String, new I18nString(childFolderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_NAME.attributeId].value as String))
}
Case caseByPath = findCaseElastic("processIdentifier:$FilterRunner.PREFERRED_ITEM_NET_IDENTIFIER AND dataSet.nodePath.textValue.keyword:\"$path\"")
if (caseByPath) {
Set<String> childrenIds = caseByPath.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_CHILD_ITEM_IDS.attributeId].value as Set
if (!childrenIds.isEmpty()) {
for (String id : childrenIds) {
Case childFolderCase = workflowService.findOne(id)
options.put(
childFolderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_NAME.attributeId].value as String,
new I18nString(childFolderCase.dataSet[MenuItemConstants.PREFERENCE_ITEM_FIELD_NODE_NAME.attributeId].value as String)
)
}
}
}
🤖 Prompt for AI Agents
In
application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy
around lines 2822 to 2828, the variable caseByPath can be null if
findCaseElastic returns no result, leading to a NullPointerException when
accessing its dataSet. Add a null check after assigning caseByPath to ensure it
is not null before accessing its properties and processing childrenIds. If
caseByPath is null, skip the children options collection to prevent the NPE.

@renczesstefan renczesstefan changed the title Remove UriNode concept [NAE-2125] Remove URI service usage from admin and menu items Jun 17, 2025
renczesstefan and others added 18 commits June 20, 2025 09:05
Introduced annotations (`EntryPoint` and `EntryPointMethod`) and corresponding domain models (`Plugin`, `EntryPoint`, `Method`, and `ListenerFilter`) to support a plugin architecture. These enable defining and managing plugins, their methods, and listener filters for remote invocation.
Introduced a new interface to define plugin registration configuration. It includes methods for retrieving the plugin name, version, and entry points. This provides a foundation for standardizing plugin integration.
Introduced core classes and services to enable a plugin architecture. This includes plugin injection, entry point management, and dynamic meta-class updates for ActionDelegate. The changes set the foundation for extensible plugin support within the system.
Introduced core classes and services to enable a plugin architecture. This includes plugin injection, entry point management, and dynamic meta-class updates for ActionDelegate. The changes set the foundation for extensible plugin support within the system.
The EntryPointLoaderService interface was unused and redundant, so it has been deleted to simplify the codebase. This helps maintain cleaner and more maintainable code.
Replaced the use of EntryPointLoaderService with ApplicationContext to retrieve PluginRegistrationConfiguration beans. This simplifies the process of loading plugins and their entry points, consolidating configuration management and improving maintainability.
Updated the PluginRunner to assign the plugin version from the configuration file instead of using a hardcoded value. This ensures better flexibility and easier version management for plugins.
Introduced PluginHolder as a new field in ActionDelegate and initialized it in the constructor. This change supports enhanced plugin management within the ActionDelegate logic.
- Enhanced PluginInjector with improved meta-class injection logic and documentation.
- Updated PluginRegistrationConfiguration to include metadata retrieval.
- Introduced @target and @retention annotations for ListenerFilter definition.
- Ensured compatibility with method-level usage and set retention policy at runtime.
[NAE-2129] Inject Plugin JAR into Community Edition
- Deleted the unused `IUriService` import from `ActionDelegate.groovy` to improve code cleanliness.
- No changes to functionality or behavior, ensuring adherence to best practices.
Replaced all instances of `MenuItemConstants.attributeId` with `value` for improved clarity and consistency in referencing constants. Updated related logic in workflow and dataset handling across multiple files to align with the new structure.
Introduced a @Getter annotation for the 'path' field to expose it externally and implemented a setter method to ensure the value is trimmed before assignment. These changes improve data encapsulation and ensure the 'path' field is managed consistently.
If the import service does not return a PetriNet object, a warning is logged, and an empty Optional is returned. This prevents potential null pointer issues and improves logging for debugging.
Simplified and optimized the `createNodePath` method by normalizing the input path before concatenation. This reduces redundancy and ensures consistent handling of path separators.
tuplle
tuplle previously approved these changes Jun 24, 2025
@machacjozef machacjozef changed the base branch from release/7.0.0-rev2 to release/7.0.0-rev3 June 25, 2025 09:27
@machacjozef machacjozef dismissed tuplle’s stale review June 25, 2025 09:27

The base branch was changed.

@machacjozef machacjozef merged commit 6e596b5 into release/7.0.0-rev3 Jun 25, 2025
6 of 7 checks passed
@machacjozef machacjozef deleted the uri_removal branch June 25, 2025 09:29
def newUri = uriService.getOrCreate("/netgrif/test_new", UriContentType.DEFAULT)
caze = setData(caze, [
"uri": newUri.path,
"uri": "/netgrif/test_new",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants