Repository navigation
Fix project API bugs carried over from the Java 8 code - #3
Merged
Merged
Conversation
- POST ignores client-supplied id/createdDate/lastModifiedDate instead of silently overwriting an existing project - PATCH no longer reports a conflict against the project being updated (e.g. re-sending its current externalId) - PATCH with "sdlcSystem": null returns 400 instead of a 500 NPE - A unique-constraint violation from a concurrent duplicate returns 409 instead of 500 - POST/PATCH responses carry the stored SDLC system instead of the client's id-only stub - Enable JPA auditing so @CreatedDate/@LastModifiedDate are populated - Stop enabling the H2 console in every deployment; spring-boot-h2console still turns it on automatically when devtools is active - Map NotFoundException to 404 in one handler and log it at INFO Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MLyPXGHeCc1fvTeB8JnT2
- Reject externalId/name longer than the 255-char columns and blank externalId on PATCH with 400 instead of 409/500 - Map only unique-constraint violations to 409; other integrity errors keep the default handling - Remove spring-boot-starter-data-rest, which exported the repositories at /projects and /sdlcSystems and bypassed every controller check - Rely on JPA auditing for timestamps: drop the manual lastModifiedDate update and field initializers; updateProject now returns Project, which removes an unreachable 400 branch - Log routine 404/409s at DEBUG - Make the unchanged-externalId test independent of test order - Document that the H2 console is a devtools-only feature Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MLyPXGHeCc1fvTeB8JnT2
… audit dates - PATCH externalId uses the same blank rule as @notblank on POST, and an explicit null is rejected with 400 instead of being silently ignored - Audit timestamps are truncated to seconds to match the datetime columns, so responses show what is stored - Unique-violation detection walks the whole cause chain - SdlcSystemService.getSdlcSystem throws NotFoundException, like ProjectService.getProject, removing the controller-side lookup helper Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MLyPXGHeCc1fvTeB8JnT2
- PATCH applies the changes to the loaded project and validates it with the entity's own constraints (@notblank, @SiZe, @NotNull), replacing the hand-copied @AssertTrue/@SiZe rules that had drifted from POST - Turn off open-in-view so the project PATCH loads is detached and a rejected change can never be flushed later in the request - Comment why the duplicate pre-check stays alongside the unique-key handler - Tests: POST and PATCH agree on unusual externalIds; a rejected PATCH leaves the project unchanged Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MLyPXGHeCc1fvTeB8JnT2
- ProjectService.updateProject loads, applies, validates and conflict-checks the project in one transaction, rolling back on any rejection (including the checked NotFoundException); correctness no longer depends on the open-in-view setting, and the extra SELECT from merging a detached copy is gone - @DynamicUpdate writes only changed columns, so concurrent PATCHes of different fields no longer overwrite each other - The conflict query doesn't flush pending changes first, so the explicit 409 check runs against the stored state - An sdlcSystem reference without an id is a 400, not "SdlcSystem 0 not found" - Drop the no-op @Valid on the PATCH body; clearer handler naming - Tests: concurrent field updates are both kept, rejected PATCH rolls back (each verified to fail without its fix), service unit tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MLyPXGHeCc1fvTeB8JnT2
…me 409 - Only query for a duplicate when the PATCH changes externalId or the SDLC system - Test that a unique violation raised at commit is recognised as one (the path concurrent PATCHes take) - Concurrency test removes the project it creates from the shared database Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MLyPXGHeCc1fvTeB8JnT2
…ve ids - The FlushMode COMMIT hint moves to a dedicated existsByExternalIdAndSdlcSystemIdAndIdNot query used only by updateProject, so other callers of the shared finder keep auto-flush - Only an absent sdlcSystem id (0) is a 400; a negative id is looked up and reported as 404 like any other unknown system Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MLyPXGHeCc1fvTeB8JnT2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the bugs that came up while reviewing #1, all of them already present in the original Java 8 code, plus what six review rounds on this PR turned up.
Behaviour changes
id201id,createdDateandlastModifiedDateare read-only in JSON, so a new project is always createdexternalId/sdlcSystem409against itself200{"sdlcSystem": null}/{"externalId": null}500NPE / silently ignored400externalId, orexternalId/nameover 255 chars (POST too)500/409400; PATCH validates the patched entity with the same constraints as POSTsdlcSystemgiven without anid404 SdlcSystem 0 not found400500409; only UNIQUE violations are mapped, anything else keeps default handling@DynamicUpdate, single transaction)sdlcSystemin POST/PATCH responses@CreatedDate/@LastModifiedDate@EnableJpaAuditingwas missing)datetimecolumns/projects,/sdlcSystems(Spring Data REST)spring-boot-starter-data-restdropped)/h2-consoleDesign
ProjectService.updateProject(id, update)loads the project, applies the change, validates it, checks for a duplicate and commits. Any rejection rolls back, including the checkedNotFoundException.externalIdor the SDLC system changed. It uses a dedicated query that doesn't flush pending changes first.spring.jpa.open-in-view=false.NotFoundExceptionto 404,ConflictExceptionand unique violations to 409, and bean-validation failures to 400. All are logged at DEBUG.SdlcSystemService.getSdlcSystemthrowsNotFoundException, likeProjectService.getProject.Intentional:
lastModifiedDate.Test plan
./mvnw clean teston JDK 25: 41 tests passmaincode. The concurrency test was checked to fail without@DynamicUpdate, and the rejected-PATCH test to fail withoutrollbackFor./h2-consolereturns 404; a POST with"id": 1creates a new project and leaves project 1 unchanged🤖 Generated with Claude Code
https://claude.ai/code/session_012MLyPXGHeCc1fvTeB8JnT2