Skip to content

[NAE-2442] Fix dataset update from database and action handling#444

Merged
machacjozef merged 4 commits into
release/7.0.0-rev10from
NAE-2442
Jun 5, 2026
Merged

[NAE-2442] Fix dataset update from database and action handling#444
machacjozef merged 4 commits into
release/7.0.0-rev10from
NAE-2442

Conversation

@renczesstefan

@renczesstefan renczesstefan commented May 27, 2026

Copy link
Copy Markdown
Member

Description

Fixes NAE-2442

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 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

  • Bug Fixes

    • Case state is refreshed from storage before executing transition and subsequent event actions, reducing stale-data issues.
  • New Features

    • Action payloads now accept non-string values, allowing richer data types when setting task data.
    • Optional values can carry runtime type information, improving handling of typed nullable values.

Introduced `updateCaseFromDb` in `IWorkflowService` and its implementation in `WorkflowService` to synchronize case data with the database. Updated `EventService` to invoke this method during action execution.
@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@renczesstefan, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 28 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 52b64e2c-930a-4f77-8703-ab9295c1d7b2

📥 Commits

Reviewing files that changed from the base of the PR and between f385ae1 and 0090d65.

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

Walkthrough

Adds updateCaseFromDb to refresh an in-memory Case from the persisted Case and integrates that refresh into EventService run paths; widens ActionApi.setData and ActionApiImpl.setData parameter types to accept non-string values (Map<String, Object>); and adds optional runtime type metadata to Nullable with accessor and factory overload.

Changes

Case state refresh before action execution

Layer / File(s) Summary
Case refresh contract and implementation
application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowService.java, application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java
IWorkflowService declares updateCaseFromDb(Case useCase). WorkflowService implements it to load the persisted Case and merge DataSet entries that are newer in the DB into the provided in-memory Case without persisting.
EventService integration
application-engine/src/main/java/com/netgrif/application/engine/workflow/service/EventService.java
Both runActions overloads now call workflowService.updateCaseFromDb(useCase) when useCase is non-null before executing actions.

Action API setData type widening

Layer / File(s) Summary
ActionApi signature
nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/actions/ActionApi.java
setData inner map value type changed from String to Object in the public adapter interface.
ActionApiImpl signature
application-engine/src/main/java/com/netgrif/application/engine/actions/ActionApiImpl.java
setData implementation signature updated to accept Map<String, Map<String, Object>> and continues to serialize the payload before delegating to dataService.setData.

Nullable runtime type metadata

Layer / File(s) Summary
Nullable type field and factories
nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/Nullable.java
Nullable<T> gains a Class<T> type field, a two-arg constructor, a public getType() accessor, an of(T, Class<T>) factory, and updates of(T) and empty() to use the new constructor.

Sequence Diagram

sequenceDiagram
  participant EventService
  participant WorkflowService
  participant Repository
  EventService->>WorkflowService: updateCaseFromDb(useCase)
  WorkflowService->>Repository: find case by ID
  Repository-->>WorkflowService: persisted Case
  WorkflowService->>WorkflowService: merge newer DataSet entries
  WorkflowService-->>EventService: refresh complete
  EventService->>EventService: execute actions
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

bugfix, api-change, Medium

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main changes: fixing dataset update from database and action handling. It is concise, directly related to the core problem being solved (preventing data loss during multi-action execution), and aligns with the primary objectives of the pull request.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
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

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

Retoocs
Retoocs previously approved these changes May 27, 2026
@coderabbitai coderabbitai Bot added bugfix A change that fixes a bug breaking change Fix or feature that would cause existing functionality doesn't work as expected Medium labels May 27, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@application-engine/src/main/java/com/netgrif/application/engine/workflow/service/EventService.java`:
- Around line 54-56: The refresh (updateCaseFromDb) is being called after
actionsRunner.run(...), causing actions to run against stale state; move the
call to workflowService.updateCaseFromDb(useCase) to immediately before each
actionsRunner.run(...) invocation within EventService so the case is reloaded
from the DB prior to executing actions (apply the same change at the other
occurrence referenced around the second actionsRunner.run(...) block as well).

In
`@application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java`:
- Around line 255-263: updateCaseFromDb currently assigns persisted DataField
objects from findOneNoNet directly into the runtime Case, which can mix
encrypted persisted fields into in-memory state; instead, when a persisted
DataField (from actual.getDataSet()) is newer than the corresponding runtime
field, copy only the safe primitive/value and metadata into the existing runtime
DataField (do not replace the object reference). In practice: in
updateCaseFromDb, for each id where
dataField.isNewerThen(useCase.getDataField(id)), obtain the target DataField =
useCase.getDataField(id) (or create a new non-persisted instance) and call its
setters to copy value, plainValue/decodedValue, timestamp, and other
non-persistence-specific metadata from dataField, rather than doing
useCase.getDataSet().put(id, dataField); this preserves in-memory
decryption/representation and avoids injecting persisted/encrypted objects
returned by findOneNoNet.
🪄 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: 72387161-fb2d-4021-8388-5c4ed913dee0

📥 Commits

Reviewing files that changed from the base of the PR and between 837a70b and e86a370.

📒 Files selected for processing (3)
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/EventService.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java
  • application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowService.java

machacjozef
machacjozef previously approved these changes May 27, 2026
Refactored `setData` method in `ActionApi` to use `Map<String, Map<String, Object>>` for flexible data handling. Adjusted `WorkflowService` to use the `findOne` method for better database case update synchronization.
@renczesstefan renczesstefan dismissed stale reviews from machacjozef and Retoocs via ce8003c May 27, 2026 13:29
@renczesstefan

Copy link
Copy Markdown
Member Author

@coderabbitai pls review once more and approve if it is OK

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the PR diff
gh pr diff 444 --repo netgrif/application-engine

Length of output: 5982


🏁 Script executed:

#!/bin/bash
# Look at the changed files
fd -e java -t f | xargs grep -l "updateCaseFromDb\|setData" 2>/dev/null | head -20

Length of output: 2289


🏁 Script executed:

#!/bin/bash
# Check isNewerThen method on DataField
rg -n "isNewerThen" --type java -C 5

# Check findOne implementation
rg -n "findOne" application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java -A 5

# Check getDataField for null safety
rg -n "getDataField" --type java -C 3 | head -60

# Check callers of setData with old/new signature
rg -n "setData" --type java -C 2 | grep -v "\.class\|//\|\.xml" | head -60

Length of output: 24185



@renczesstefan I've reviewed all the changes thoroughly. Here's my assessment:


Review Summary

1. WorkflowService.updateCaseFromDb (new method)

  • Uses findOne which throws IllegalArgumentException if the case is not found — so actual is never null. ✅
  • Version-based conflict resolution via isNewerThen is correct: fields modified by the running action will have a higher in-memory version than the persisted DB version, so they won't be overwritten. ✅
  • Minor: useCase.getDataField(id) could theoretically return null for a field present in the DB but absent in the in-memory case, which would cause an NPE inside isNewerThen. However, this is the same pre-existing pattern already in DataService.updateDataset (lines 869–874) — this PR doesn't introduce new risk.
  • Minor: updateCaseFromDb duplicates DataService.updateDataset logic. Worth a follow-up refactor, but not a blocker.

2. EventService.runActions / runEventActions

  • The placement of updateCaseFromDb (after actionsRunner.run(...), before processing SetDataEventOutcome) is correct. ✅
  • null guard on useCase is present. ✅
  • Each action iteration now triggers a DB read — acceptable given the correctness requirement.

3. setData signature widening (Map<String, Map<String, String>>Map<String, Map<String, Object>>)

  • Breaking change from a Java generic perspective, but since NAE actions are Groovy-based (dynamic typing), existing action scripts are unaffected. ✅
  • Both ActionApi interface and ActionApiImpl are consistently updated. ✅

The changes correctly fix the data-loss issue caused by stale in-memory state during multi-action execution. No blocking issues found.

[approve]

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 27, 2026
Introduced `type` field and updated constructors to allow runtime type tracking in `Nullable`. Added `getType` method and adjusted factory methods accordingly.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/utils/Nullable.java`:
- Around line 29-33: The equals()/hashCode() implementations in class Nullable
must include the type field so instances with different type parameters (e.g.,
Nullable.of(null, String.class) vs Nullable.of(null, Integer.class)) are
distinguished; update Nullable.equals(Object) to compare this.type (via
Objects.equals or equivalent) along with value, and update Nullable.hashCode()
to incorporate type (e.g., Objects.hash(value, type)) so sets/maps treat
differently-typed nullables as distinct; ensure getType() remains consistent
with these changes.
- Around line 82-83: The empty() helper currently returns a Nullable with both
value and type null, causing Nullable.of(...).filter(...) to lose its type
metadata; update the filter(...) implementation in class Nullable to preserve
the instance's type when the predicate fails by returning a new Nullable<>(null,
this.type) instead of calling empty(), so getType() still returns the original
Class metadata; alternatively, add/choose an empty(Class<T> type) factory and
have filter call that to preserve the type.
🪄 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: ba7acd6b-e89c-46d0-8096-5fbe18df305a

📥 Commits

Reviewing files that changed from the base of the PR and between ce8003c and f385ae1.

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

Added `empty(Class<T>)` factory method for runtime type-safe `Nullable` instances and updated methods to incorporate type handling in equality checks and hash code computation.
@machacjozef machacjozef merged commit 39e1172 into release/7.0.0-rev10 Jun 5, 2026
6 of 7 checks passed
@machacjozef machacjozef deleted the NAE-2442 branch June 5, 2026 12:35
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 bugfix A change that fixes a bug Medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants