Skip to content

[NAE-2418] Verify @Transient handling across persistence layers in na…#436

Open
renczesstefan wants to merge 6 commits intorelease/7.0.0-rev10from
NAE-2418
Open

[NAE-2418] Verify @Transient handling across persistence layers in na…#436
renczesstefan wants to merge 6 commits intorelease/7.0.0-rev10from
NAE-2418

Conversation

@renczesstefan
Copy link
Copy Markdown
Member

@renczesstefan renczesstefan commented Apr 27, 2026

Description

Implements NAE-2418

Dependencies

No new dependencies were introduced.

Third party dependencies

There are no dependencies on other PR.

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 Tahoe 26.3
Runtime Java 21
Dependency Manager Maven 3.9.9n
Framework version Spring Boot 3.4.4
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 @machacjozef
  • 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

  • Chores

    • Added Spring-data-aware adapter types and switched runtime instantiation to them for improved persistence compatibility.
    • Introduced denormalized ID sets for authorities and process roles to support reliable persistence and lookup.
  • New Features

    • Registered a Petri net load event hook.
    • Added a user-load listener that resolves and populates authorities and process roles after data is loaded.
  • Refactor

    • Made core arc, user and group types abstract and introduced adapter implementations for clearer separation.

…e-spring-core-adapter

Replaced the incorrect `java.beans.Transient` import with `org.springframework.data.annotation.Transient`. This ensures proper handling of transiency in the context of Spring Data.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

Warning

Rate limit exceeded

@renczesstefan has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 25 minutes and 49 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f2f78a72-ebd8-4d37-81ac-1152d8953d29

📥 Commits

Reviewing files that changed from the base of the PR and between ae51eb2 and 9d9812d.

📒 Files selected for processing (7)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetEventHandler.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractActor.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/arcs/Arc.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/arcs/InhibitorArc.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/arcs/ReadArc.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/arcs/ResetArc.java
  • nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserMongoEventListener.java

Walkthrough

Core auth/actor types gained denormalized ID sets and MongoDB post-load resolution; many User/Group usages were switched to Spring adapter subclasses. Core Petri net arc types were made abstract and Spring adapter arc subclasses were added with persistence-transient getters. Minor Spring Data import and an empty PetriNet after-load hook were added.

Changes

Auth / Actor model, persistence wiring, and tests

Layer / File(s) Summary
Data Shape
nae-object-library/src/main/java/.../AbstractActor.java
Added authorityIds and processRoleIds fields and setters; updated authority/process-role mutators to maintain ID sets; added clearProcessRoles().
Core type changes
nae-object-library/src/main/java/.../User.java, .../Group.java
Made User and Group abstract (class signatures changed).
Adapter types
nae-spring-core-adapter/src/main/java/.../auth/domain/User.java, .../Group.java, .../AnonymousUser.java
Added Spring adapter User and Group subclasses (constructors + overrides for getters annotated with @Transient); refactored imports in AnonymousUser.
Persistence wiring / Event listener
nae-user-ce/src/main/java/.../UserMongoEventListener.java, nae-user-ce/.../UserServiceImpl.java
Added UserMongoEventListener to resolve processRoleIds/authorityIds into objects on after-convert; updated user creation sites to instantiate adapter User.
Repository query
nae-user-common/src/main/java/.../UserRepository.java
findAllByProcessRoles__idIn(...) now queries the processRoleIds field and maps ProcessResourceId to strings for the $in filter.
Callsites / Tests / Resources
application-engine/..., src/test/..., src/test/resources/petriNets/*
Replaced direct new User()/new Group() usages with fully-qualified adapter classes across services, tests, XML test resources, and startup code.

Petri net arc abstractions and Spring adapter arcs

Layer / File(s) Summary
Core type change
nae-object-library/src/main/java/.../petrinet/domain/arcs/Arc.java, .../InhibitorArc.java, .../ReadArc.java, .../ResetArc.java
Core arc classes changed to abstract for Arc, InhibitorArc, ReadArc, ResetArc.
Adapter implementations
nae-spring-core-adapter/src/main/java/.../petrinet/domain/arcs/Arc.java, .../InhibitorArc.java, .../ReadArc.java, .../ResetArc.java
Added Spring adapter subclasses that extend core abstract arcs; provided constructors and overridden getSource()/getDestination() annotated with Spring Data @Transient.
Factory wiring
application-engine/src/main/java/.../petrinet/service/ArcFactory.java
Switched getArc(...) instantiation to use Spring adapter arc classes for REGULAR, VARIABLE, RESET, INHIBITOR, READ; updated imports and removed unused import.
Tests / Documentation
(no new tests in this diff)
No arc-specific tests added in this diff.

Small Spring Data / persistence hooks

Layer / File(s) Summary
Annotation import fix
nae-spring-core-adapter/src/main/java/.../workflow/domain/DataGroup.java
Replaced java.beans.Transient with org.springframework.data.annotation.Transient import; existing annotations unchanged.
MongoDB load hook
application-engine/src/main/java/.../petrinet/service/PetriNetEventHandler.java
Added an empty override onAfterLoad(AfterLoadEvent<PetriNet>) to register an after-load handler (no behavior implemented).

Sequence Diagram(s)

sequenceDiagram
    participant MongoDB as MongoDB
    participant Spring as Spring Data Mapping
    participant Listener as UserMongoEventListener
    participant PRS as ProcessRoleService
    participant AS as AuthorityService

    MongoDB->>Spring: read document (AbstractActor)
    Spring->>Listener: onAfterLoad / onAfterConvert(actor)
    Listener->>PRS: findById(processRoleId) [for each id]
    PRS-->>Listener: ProcessRole
    Listener->>AS: findById(authorityId) [for each id]
    AS-->>Listener: Authority
    Listener-->>Spring: actor populated (processRoles & authorities)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'NAE-2418 Verify @Transient handling across persistence layers in na…' is partially related to the changeset, referring to a real aspect (@Transient handling), but incompletely describes the broader scope.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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
Review rate limit: 0/1 reviews remaining, refill in 25 minutes and 49 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 27, 2026
Retoocs
Retoocs previously approved these changes Apr 27, 2026
…e-spring-core-adapter

- created new arc classes in spring core adapter
- refactored existing arc class to be abstract
- added transient to arcs
@renczesstefan renczesstefan dismissed stale reviews from Retoocs and coderabbitai[bot] via 3f362f9 April 28, 2026 10:51
Copy link
Copy Markdown

@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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetEventHandler.java`:
- Around line 21-24: Remove the no-op Spring Data lifecycle hook by deleting the
onAfterLoad(AfterLoadEvent<PetriNet> event) method from the PetriNetEventHandler
class and also remove the unused AfterLoadEvent import; ensure no other code
references onAfterLoad so compilation remains clean.

In
`@nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/arcs/Arc.java`:
- Around line 12-14: The copy constructor public Arc(Arc arc) is too narrowly
typed; change its parameter to the core/base arc type (the base Arc
interface/class used by the superclass) so it can accept core arcs, e.g. public
Arc(BaseArcType arc) { super(arc); }, and update the import for that core/base
Arc type; keep the body calling super(arc) unchanged to delegate copying to the
superclass.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d5fe2af9-b04f-42a0-b2dd-3da8dca5d1d3

📥 Commits

Reviewing files that changed from the base of the PR and between 17e7be8 and 3f362f9.

📒 Files selected for processing (10)
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ArcFactory.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetEventHandler.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/arcs/Arc.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/arcs/InhibitorArc.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/arcs/ReadArc.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/petrinet/domain/arcs/ResetArc.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/arcs/Arc.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/arcs/InhibitorArc.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/arcs/ReadArc.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/domain/arcs/ResetArc.java

…e-spring-core-adapter

- added annotation to user objects, so process list is transient
…e-spring-core-adapter

Refactored `AbstractActor` to manage roles and authorities with additional `processRoleIds` and `authorityIds` fields for better flexibility. Updated related services, repositories, and XML test resources to align with the modified structure. Introduced `UserMongoEventListener` to resolve roles and authorities from IDs after data loading.
@coderabbitai coderabbitai Bot added improvement A change that improves on an existing feature breaking change Fix or feature that would cause existing functionality doesn't work as expected Large Medium labels May 4, 2026
Copy link
Copy Markdown

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
nae-user-common/src/main/java/com/netgrif/application/engine/auth/repository/UserRepository.java (1)

187-191: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Migrate this query to processRoleIds as well to avoid inconsistent results.

This method still filters by processRoles._id, while the new persistence path uses denormalized processRoleIds. With transient role objects, this query path can miss valid users.

Suggested fix
 default Page<User> findDistinctByStateAndProcessRoles__idIn(UserState state, Collection<ProcessResourceId> roleId, Pageable pageable, MongoTemplate mongoTemplate, String collection) {
     Query query = Query.query(
             Criteria.where("state").is(state)
-                    .and("processRoles._id").in(roleId));
+                    .and("processRoleIds").in(roleId.stream().map(ProcessResourceId::toString).toList()));
     return resolveUserPage(pageable, mongoTemplate, collection, query);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@nae-user-common/src/main/java/com/netgrif/application/engine/auth/repository/UserRepository.java`
around lines 187 - 191, The query in findDistinctByStateAndProcessRoles__idIn
still filters on "processRoles._id" which misses users when roles are
denormalized to "processRoleIds"; update the Criteria in that method to query
"processRoleIds" instead (or use an OR Criteria that checks both
"processRoleIds" and "processRoles._id" for backward compatibility) so
resolveUserPage receives a query that finds users by the denormalized role IDs;
ensure the change uses the existing roleId parameter and preserves return via
resolveUserPage.
nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractActor.java (1)

223-233: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix authority ID/object desynchronization in fallback removal path.

If object removal falls back to name-based matching, the removed authority object may not match the originally removed ID, leaving stale entries in authorityIds.

Suggested fix
 public void removeAuthority(Authority authority) {
+    if (authority == null) {
+        return;
+    }
     if (this.authorityIds == null) {
         this.authorityIds = new HashSet<>();
-    } else {
-        this.authorityIds.remove(authority.getStringId());
     }
     if (this.authoritySet == null) {
         this.authoritySet = new HashSet<>();
     } else if (!this.authoritySet.remove(authority)) {
-        this.authoritySet.removeIf(it -> it.getName().equals(authority.getName()));
+        Authority matched = this.authoritySet.stream()
+                .filter(it -> it.getName().equals(authority.getName()))
+                .findFirst()
+                .orElse(null);
+        if (matched != null) {
+            this.authoritySet.remove(matched);
+            this.authorityIds.remove(matched.getStringId());
+        }
+        return;
     }
+    this.authorityIds.remove(authority.getStringId());
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractActor.java`
around lines 223 - 233, The removeAuthority(Authority authority) method can
leave stale IDs in authorityIds when it falls back to name-based removal from
authoritySet; update the fallback path so that when you remove by name (in the
removeIf on authoritySet) you also remove the corresponding authority IDs from
authorityIds (e.g., find entries in authorityIds whose Authority.getStringId()
corresponds to the removed objects or remove IDs whose names match
authority.getName()), ensuring null-safe handling of authorityIds and
authoritySet; modify removeAuthority to synchronize both collections in both the
direct remove(authority) branch and the removeIf(name) fallback so IDs and
objects stay consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractActor.java`:
- Around line 281-289: In addAllProcessRoles, guard against a null roles
argument: check if the incoming Set<ProcessRole> roles is null (or empty) at the
top of the method and return early to avoid calling roles.stream() or
this.processRoles.addAll(roles); ensure existing initialization of
this.processRoleIds and this.processRoles (as already present) remains, then
only perform
this.processRoleIds.addAll(roles.stream().map(ProcessRole::getStringId).toList())
and this.processRoles.addAll(roles) when roles is non-null; reference the method
addAllProcessRoles and the fields processRoleIds/processRoles and class
ProcessRole to locate the code.

In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Group.java`:
- Line 19: The Group class was made abstract but GroupController still
instantiates it with new Group(...), causing a compile error; either revert
Group to a concrete class until the constructor call is migrated, or update the
controller to use the concrete Spring adapter class (the adapter that implements
Group) instead of new Group(...). Locate the Group class declaration (public
abstract class Group extends AbstractActor) and either remove the abstract
modifier or change the instantiation in GroupController (the code that does new
Group(...)) to call the concrete adapter/implementation class that wraps Spring
functionality; ensure constructors/signatures match so compilation succeeds.

In
`@nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserMongoEventListener.java`:
- Around line 23-24: The trace logs in UserMongoEventListener currently print
the entire loaded user document via event.getSource(), which can expose
sensitive fields; change both log.trace calls to avoid logging the full payload
and instead log a minimal identifier (e.g., user id or username) and/or omit the
payload entirely — locate the two calls in UserMongoEventListener where
log.trace("User loaded: {}", event.getSource()) and log.trace("Resolving process
roles of user with id: {}", event.getSource()) are used and replace
event.getSource() with a safe accessor like event.getSource().getId() or
event.getSource().getUsername(), or remove the payload argument so only
non-sensitive context is logged.
- Around line 29-31: In UserMongoEventListener, avoid adding null role/authority
objects into actor collections: when iterating actor.getProcessRoleIds() call
processRoleService.findById(processRoleId) and only add the result to
actor.getProcessRoles() if it is non-null (skip otherwise), and similarly when
iterating actor.getAuthorityIds() call authorityService.getOne(authorityId) and
only add to actor.getAuthoritySet() if non-null; update the loops in the block
that uses AbstractActor actor to perform null checks (or filter nulls) before
calling add to prevent polluted collections and NPEs.

---

Outside diff comments:
In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractActor.java`:
- Around line 223-233: The removeAuthority(Authority authority) method can leave
stale IDs in authorityIds when it falls back to name-based removal from
authoritySet; update the fallback path so that when you remove by name (in the
removeIf on authoritySet) you also remove the corresponding authority IDs from
authorityIds (e.g., find entries in authorityIds whose Authority.getStringId()
corresponds to the removed objects or remove IDs whose names match
authority.getName()), ensuring null-safe handling of authorityIds and
authoritySet; modify removeAuthority to synchronize both collections in both the
direct remove(authority) branch and the removeIf(name) fallback so IDs and
objects stay consistent.

In
`@nae-user-common/src/main/java/com/netgrif/application/engine/auth/repository/UserRepository.java`:
- Around line 187-191: The query in findDistinctByStateAndProcessRoles__idIn
still filters on "processRoles._id" which misses users when roles are
denormalized to "processRoleIds"; update the Criteria in that method to query
"processRoleIds" instead (or use an OR Criteria that checks both
"processRoleIds" and "processRoles._id" for backward compatibility) so
resolveUserPage receives a query that finds users by the denormalized role IDs;
ensure the change uses the existing roleId parameter and preserves return via
resolveUserPage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7bdab57e-4c74-48c2-86db-e1e6bfd916b9

📥 Commits

Reviewing files that changed from the base of the PR and between 3f362f9 and e3f0867.

📒 Files selected for processing (44)
  • application-engine/src/main/java/com/netgrif/application/engine/auth/service/RegistrationService.java
  • application-engine/src/main/java/com/netgrif/application/engine/configuration/security/PublicAuthenticationFilter.java
  • application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java
  • application-engine/src/main/java/com/netgrif/application/engine/startup/runner/SuperCreatorRunner.java
  • application-engine/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/auth/LoginAttemptsTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/auth/SecurityContextTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/auth/UserServiceTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupServiceTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileFieldTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileListFieldTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy
  • application-engine/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy
  • application-engine/src/test/java/com/netgrif/application/engine/MailSenderServiceTest.java
  • application-engine/src/test/java/com/netgrif/application/engine/auth/service/TokenServiceTest.java
  • application-engine/src/test/java/com/netgrif/application/engine/workflow/WorkflowMvcPerformanceTest.java
  • application-engine/src/test/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationServiceTest.java
  • application-engine/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java
  • application-engine/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java
  • application-engine/src/test/resources/petriNets/function_test.xml
  • application-engine/src/test/resources/petriNets/function_test_v2.xml
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractActor.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Group.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/User.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/auth/domain/AnonymousUser.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/auth/domain/Group.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/auth/domain/User.java
  • nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java
  • nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserMongoEventListener.java
  • nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java
  • nae-user-common/src/main/java/com/netgrif/application/engine/auth/repository/UserRepository.java

Comment on lines +281 to +289
public void addAllProcessRoles(Set<ProcessRole> roles) {
if (this.processRoleIds == null) {
this.processRoleIds = new HashSet<>();
}
if (this.processRoles == null) {
this.processRoles = new HashSet<>();
}
this.processRoleIds.addAll(roles.stream().map(ProcessRole::getStringId).toList());
this.processRoles.addAll(roles);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Guard addAllProcessRoles against null input.

roles.stream() and addAll(roles) will throw if roles is null.

Suggested fix
 public void addAllProcessRoles(Set<ProcessRole> roles) {
+    if (roles == null || roles.isEmpty()) {
+        return;
+    }
     if (this.processRoleIds == null) {
         this.processRoleIds = new HashSet<>();
     }
     if (this.processRoles == null) {
         this.processRoles = new HashSet<>();
     }
     this.processRoleIds.addAll(roles.stream().map(ProcessRole::getStringId).toList());
     this.processRoles.addAll(roles);
 }
📝 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
public void addAllProcessRoles(Set<ProcessRole> roles) {
if (this.processRoleIds == null) {
this.processRoleIds = new HashSet<>();
}
if (this.processRoles == null) {
this.processRoles = new HashSet<>();
}
this.processRoleIds.addAll(roles.stream().map(ProcessRole::getStringId).toList());
this.processRoles.addAll(roles);
public void addAllProcessRoles(Set<ProcessRole> roles) {
if (roles == null || roles.isEmpty()) {
return;
}
if (this.processRoleIds == null) {
this.processRoleIds = new HashSet<>();
}
if (this.processRoles == null) {
this.processRoles = new HashSet<>();
}
this.processRoleIds.addAll(roles.stream().map(ProcessRole::getStringId).toList());
this.processRoles.addAll(roles);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractActor.java`
around lines 281 - 289, In addAllProcessRoles, guard against a null roles
argument: check if the incoming Set<ProcessRole> roles is null (or empty) at the
top of the method and return early to avoid calling roles.stream() or
this.processRoles.addAll(roles); ensure existing initialization of
this.processRoleIds and this.processRoles (as already present) remains, then
only perform
this.processRoleIds.addAll(roles.stream().map(ProcessRole::getStringId).toList())
and this.processRoles.addAll(roles) when roles is non-null; reference the method
addAllProcessRoles and the fields processRoleIds/processRoles and class
ProcessRole to locate the code.

…e-spring-core-adapter

Replaced explicit imports with wildcard in `AbstractActor` for conciseness. Also adjusted the `addAllProcessRoles` method to use a more general `Collection` type for improved flexibility in handling process roles.
Copy link
Copy Markdown

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractActor.java`:
- Around line 188-190: When replacing denormalized ID sets in setAuthorityIds
and setProcessRoleIds, also clear or reset the corresponding hydrated object
collections so in-memory state doesn't stay stale: in setAuthorityIds(String)
assign this.authorityIds as before and also clear/reset authoritySet (e.g.,
this.authoritySet = new HashSet<>() or this.authoritySet.clear()) and in
setProcessRoleIds(String) do the same for processRoles; preserve the
null-to-empty behavior for IDs and ensure you reference setAuthorityIds,
authorityIds, authoritySet, setProcessRoleIds, processRoleIds and processRoles
when making the changes so isAdmin and other in-memory checks reflect the new
IDs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 24f773a3-fb6e-42af-b287-66d2ab1d09d3

📥 Commits

Reviewing files that changed from the base of the PR and between e3f0867 and ae51eb2.

📒 Files selected for processing (1)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/AbstractActor.java

} else {
this.authoritySet.removeIf(it -> it.getName().equals(name));
} else {
Authority authority = authoritySet.stream().filter(it -> it.getName().equals(name)).findFirst().orElse(null);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are you afraid of using Optional?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's okay for me to change it :D I changed it.

* @param authoritySet set of authorities to set, null creates empty set
*/
public void setAuthoritySet(Set<Authority> authoritySet) {
this.authorityIds = authoritySet == null ? new HashSet<>() : new HashSet<>(authoritySet.stream().map(Authority::getStringId).toList());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if you use .collect(Collectors.toSet()) it should already create hash set

}

public void setProcessRoleIds(Set<String> processRoleIds) {
this.processRoleIds = processRoleIds == null ? new HashSet<>() : new HashSet<>(processRoleIds);;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you have ; twice here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Corrected.

*/
public void setProcessRoles(Set<ProcessRole> processRoleSet) {
this.processRoles = processRoleSet == null ? new HashSet<>() : new HashSet<>(processRoleSet);
this.processRoleIds = processRoleSet == null ? new HashSet<>() : new HashSet<>(processRoleSet.stream().map(ProcessRole::getStringId).toList());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if you use .collect(Collectors.toSet()) it should already create hash set


/**
* Adds a process role to the actor.
* t
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

remove

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Corrected.

import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Transient;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Imports added but no changes in code. Are the imports used?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Cleaned up.

@renczesstefan renczesstefan requested a review from Retoocs May 4, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Fix or feature that would cause existing functionality doesn't work as expected improvement A change that improves on an existing feature Large Medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants