Delegate HTTP status resolution to PolarisException hierarchy - #5206
Delegate HTTP status resolution to PolarisException hierarchy#5206harshitaajoshi wants to merge 3 commits into
Conversation
…sException hierarchy Fixes apache#5167
flyrain
left a comment
There was a problem hiding this comment.
Thanks @harshitaajoshi for the PR. The refactor seems straightforward. I'm OK with the direction. One minor concern is that, it pushes an HTTP/transport concept (status codes) into polaris-core, which is usually transport-neutral. I'd suggest a dev emailing discussion to gather more inputs before we merging it.
|
Thanks for the review and the approval, @flyrain. That is a fair point about keeping |
vigneshio
left a comment
There was a problem hiding this comment.
Thanks @harshitaajoshi - LGTM... +1 with @flyrain
| * return a more specific status code. | ||
| */ | ||
| public int httpStatusCode() { | ||
| return 500; |
There was a problem hiding this comment.
Note: even if I agree with this method returning raw ints, the Jakarta Jax-RS API is a direct dependency of polaris-core:
polaris/polaris-core/build.gradle.kts
Line 58 in 79cabc5
It is therefore possible to replace the int constants with a call to that API, as follows:
public int httpStatusCode() {
return Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
}There was a problem hiding this comment.
Thanks for the review and the context, @adutra. Good to know that jakarta.ws.rs is already available in polaris-core. I went with raw ints to keep the exception classes minimal, but I can switch to the Response.Status constants if you prefer. Let me know.
There was a problem hiding this comment.
Not that I have a strong preference, but let's use Response.Status constants. I hope everybody will agree.
There was a problem hiding this comment.
Done, switched to Response.Status constants in the latest commit. I kept the literal values in the test assertions so the test does not depend on the same constants as the production code.
There was a problem hiding this comment.
Thanks! I think that this change did improve readability a bit.
flyingImer
left a comment
There was a problem hiding this comment.
Like the direction here. The mapper doesn't need to know about every PolarisException subtype anymore, and that drops eight cross-module imports.
One thing worth coordinating on: 4961 is also open and mergeable, and it adds two new PolarisException subclasses through the same getStatus switch this PR deletes. Whoever lands second will hit a conflict, and the fix that compiles is just dropping those two case arms, not adding httpStatusCode overrides for them. Nothing forces that second step, so both could quietly end up at 500. Left a separate comment on the httpStatusCode default itself for the related point.
One smaller thing: the description still says this keeps jakarta.ws out of polaris-core, but the touched classes now import jakarta.ws.rs.core.Response. I'd rather core stay framework-free in source since nothing else in it uses jakarta today, but the dependency was already declared so this isn't new exposure, and I'm not blocking on it.
| * return a more specific status code. | ||
| */ | ||
| public int httpStatusCode() { | ||
| return Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); |
There was a problem hiding this comment.
The referenced pr 5167 asked for a required method here, and this ships a default returning 500. FileIOUnknownHostException shows why that gap matters: it's the one subclass with no override, the new test pins it at 500, and IcebergExceptionMapper maps the same class to 404 elsewhere in the tree.
I'd just drop the default and make this abstract, since every subclass but that one already overrides it, it'll compile everywhere else and force a real answer here instead of an inherited one. No source outside this repo extends PolarisException today, so I don't think it costs any real compatibility.
There was a problem hiding this comment.
Good point, done.
Made httpStatusCode() abstract and gave FileIOUnknownHostException an explicit 500. That is its current runtime behavior, since PolarisExceptionMapper is the more specific mapper and wins for that class, so this stays a pure refactor. It also matches what #5167 originally asked for.
I did not align it with the 404 in IcebergExceptionMapper because that is a real behavior change and deserves its own issue rather than riding along here.
@adutra @flyrain heads up, this reverses the non abstract default you both approved earlier. The reasoning is that FileIOUnknownHostException was the only subclass leaning on the inherited value and it was silently disagreeing with IcebergExceptionMapper. Easy to revert if you would rather keep the default, just say the word.
On #4961: agreed, whoever lands second should add overrides for the two new subclasses rather than dropping the case arms. Happy to rebase if it lands first.
Description updated.
…atus FileIOUnknownHostException was the only subclass relying on the inherited default. It now returns 500 explicitly, preserving current runtime behavior.
Summary
Today
PolarisExceptionMappermaintains a centralized switch statement that maps everyPolarisExceptionsubtype to an HTTP status code. This creates tight coupling between the mapper and every exception class, and requires updating the mapper whenever a new exception type is added.This PR inverts that relationship by adding an abstract
httpStatusCode()method toPolarisExceptionand implementing it in each subclass with the correct status code. The mapper now delegates toexception.httpStatusCode()instead of maintaining the switch.The method returns a plain
intso the signature stays transport neutral. The implementations referenceResponse.Statusconstants, which is fine becausejakarta.ws.rsis already a declared dependency ofpolaris-core. Every subclass now declares its own status explicitly, includingFileIOUnknownHostException, which returns 500 to match its current behavior.Fixes #5167
Checklist
CHANGELOG.md(if needed)site/content/in-dev/unreleased(if needed)Test plan
testPolarisExceptionStatusCodes) covering all 10PolarisExceptionsubclasses, verifying bothhttpStatusCode()on the exception and the HTTP response from the mapper.ExceptionMapperTestcases continue to pass unchanged../gradlew format compileAlland./gradlew :polaris-core:checklocally with all tests passing.