Skip to content

Guard EntityFactory against null ResultSet and -1 id sentinel#142

Merged
dmccoystephenson merged 1 commit into
mainfrom
fix/entity-factory-robustness
Jun 13, 2026
Merged

Guard EntityFactory against null ResultSet and -1 id sentinel#142
dmccoystephenson merged 1 commit into
mainfrom
fix/entity-factory-robustness

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Summary

EntityFactory implemented the same "get next id from a sequence, then INSERT" pattern as EnvironmentFactory but omitted two safety checks the latter performs, leaving two defects on the live entity-creation path (POST /api/v1/entities/{name} and DebugController):

  1. Unguarded null ResultSet → NPE. getNextEntityId() called rs.next() without checking rs. DbInteractions.query(...) returns null on failure, so a failed/locked query threw NullPointerException instead of returning -1. Fixed with if (rs == null) return -1; (matches EnvironmentFactory).
  2. Unchecked -1 sentinel → bad INSERT. createEntity() never checked id == -1 before building the INSERT, so on failure it would write a row with entity_id = -1. Fixed with an if (id == -1) guard that logs and throws EntityCreationException (matches EnvironmentFactory).

Tests

Adds EntityFactoryTest (mocks DbInteractions, mirroring the repository tests' @SpringBootTest + @MockBean style):

  • success path returns the entity;
  • null-ResultSet → throws, and asserts no update/INSERT is attempted;
  • nextval returns no row (-1) → throws, and asserts no update/INSERT is attempted;
  • INSERT failure → throws.

Both guard tests were confirmed to fail without the fix (NPE on the null case; the -1 case attempts the INSERT and trips the never().update(...) verification).

Test plan

  • ./mvnw test220/220 pass (was 216; +4), JDK 21
  • Regression demonstrated: reverting EntityFactory.java to main makes the two guard tests fail
  • Python client — n/a (no src/main/python change)

Closes #138

🤖 Generated with Claude Code

EntityFactory omitted two safety checks that EnvironmentFactory performs:

- getNextEntityId() called rs.next() without a null guard, so a failed
  nextval query (DbInteractions.query returns null on failure) threw NPE
  instead of returning -1. Added `if (rs == null) return -1;`.
- createEntity() never checked the -1 sentinel before building the INSERT,
  so on failure it would INSERT a row with entity_id = -1. Added an
  `if (id == -1)` guard that logs and throws EntityCreationException, matching
  EnvironmentFactory.

Adds EntityFactoryTest (mocks DbInteractions): success path plus the two
guarded cases, which assert no INSERT (dbInteractions.update) is attempted.
Both guard tests fail without the fix (NPE / INSERT-with-(-1)).

Closes #138

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dmccoystephenson dmccoystephenson merged commit 5c9ee7d into main Jun 13, 2026
1 check passed
@dmccoystephenson dmccoystephenson deleted the fix/entity-factory-robustness branch June 13, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EntityFactory is missing the null-ResultSet guard and id==-1 check that EnvironmentFactory has

1 participant