-
Notifications
You must be signed in to change notification settings - Fork 292
Conversation
Update the following libraries: - jackson-datatype-problem to 0.21.0 - problem to 0.21.0 - problem-spring-web to 0.23.0 Code fixes and refactoring of exception handling
Codecov Report
@@ Coverage Diff @@
## master #946 +/- ##
============================================
+ Coverage 54.13% 54.18% +0.05%
- Complexity 1760 1775 +15
============================================
Files 318 335 +17
Lines 9589 9572 -17
Branches 872 874 +2
============================================
- Hits 5191 5187 -4
+ Misses 4083 4067 -16
- Partials 315 318 +3
Continue to review full report at Codecov.
|
# Conflicts: # src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work @lmontrieux, thank you! It makes sense for us to fully understand Zalando problem approach
@@ -89,48 +72,4 @@ public SubscriptionController(final FeatureToggleService featureToggleService, | |||
final StatsMode statsMode = showTimeLag ? StatsMode.TIMELAG : StatsMode.NORMAL; | |||
return subscriptionService.getSubscriptionStat(subscriptionId, statsMode); | |||
} | |||
|
|||
@ExceptionHandler(FeatureNotAvailableException.class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same as for previous PR, maybe we should exceptions related to this particular controller in the controller
|
||
@RestController | ||
public class PartitionsController { | ||
public class PartitionsController extends NakadiProblemControllerAdvice { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does every controller extend NakadiProblemControllerAdvice
? I thought once NakadiProblemControllerAdvice
is @ControllerAdvice
it should work transparently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adyach I think @lmontrieux extended this class because it defines the method create
used to generate the Problem
response.
We would have to write some "catch/rethrow" here if we are not extending such class. What do you think? I prefer catch/rethrow instead of inheritance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think spring wants you to use runtime exceptions everywhere, keep controller code linear without error handling and catch all in the controller advisor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I have a global @ControllerAdvice
for the handlers that relate to all controllers, and a few @ControllerAdvice
with higher priority, for those controller-specific cases. Once we merge the previous PR on this work (moving problem creation to controller), some more controller-specific handlers will also more to the specific @ControllerAdvice
classes (such as StorageNotFoundException
)
import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; | ||
|
||
|
||
public interface NakadiProblemHandling extends ProblemHandling { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we have this interface? it could be moved to NakadiProblemControllerAdvice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why should we extend ProblemHandling? do we use everything from there? for example I see validation trait there, I remember ValidationProblem.java
in EventTypeController.create(), which we create by ourselves, but in case we have validation trait I expect to be created for us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good point. I changed the approach, I think it is cleaner and more spring boot-like now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job, you have made controllers super lean !
return status; | ||
} | ||
} | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably this is an exceptional situation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use 418 I'm a teapot
? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, it should never happen that the status code is not a real status code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would through runtime exception here, and if it happens we will have 500 at the end, which should be correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -110,16 +110,13 @@ private ResponseEntity postEventInternal(final String eventTypeName, | |||
return response(result); | |||
} catch (final JSONException e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that catch blocks here are only for logging purposes, we do logging in top level controller, do you think we can remove them?
if (featureToggleService.isFeatureEnabled(DISABLE_EVENT_TYPE_CREATION)) { | ||
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); | ||
} | ||
|
||
if (errors.hasErrors()) { | ||
return Responses.create(new ValidationProblem(errors), request); | ||
throw new ValidationException(errors); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to follow common approach (no matter which one you choose), because a couple of lines above I see you return response entity in exceptional situation, and here you throw an exception
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it looks like it does not make much sense to throw exception from where you can already form proper response
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, actually I was trying to avoid creating Problem
in the controllers, and delegate that to ControllerAdvice classes instead. I agree with the first comment however, that the strategy should be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is not necessarily to create Problem
here, you can create ResponseEntity
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should create Problem
s for every error
if (errors.hasErrors()) { | ||
return Responses.create(new ValidationProblem(errors), request); | ||
throw new ValidationException(errors); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
if (!adminService.isAdmin(AuthorizationService.Operation.ADMIN)) { | ||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); | ||
} | ||
if (errors.hasErrors()) { | ||
throw new ValidationException(errors); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
|
||
@Priority(10) | ||
@ControllerAdvice(assignableTypes = CursorOperationsController.class) | ||
public class CursorOperationsHandler implements AdviceTrait { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does it implement AdviceTrait?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to use AdviceTrait.create(..)
# Conflicts: # src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java # src/main/java/org/zalando/nakadi/controller/CursorsController.java # src/main/java/org/zalando/nakadi/controller/EventPublishingController.java # src/main/java/org/zalando/nakadi/controller/EventTypeController.java # src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java # src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java # src/main/java/org/zalando/nakadi/controller/StoragesController.java # src/main/java/org/zalando/nakadi/controller/SubscriptionController.java # src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java # src/main/java/org/zalando/nakadi/controller/TimelinesController.java # src/test/java/org/zalando/nakadi/controller/NakadiProblemHandlingTest.java
when appropriate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, though I would call *Handlers
as *ExceptionHandlers
build.gradle
Outdated
@@ -188,8 +190,9 @@ dependencies { | |||
// end::dependencies[] | |||
|
|||
// tag::wrapper[] | |||
task wrapper(type: Wrapper) { | |||
gradleVersion = '2.3' | |||
wrapper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need this section ? we have defined it in gradle-wrapper.properties
} | ||
|
||
private String generateErrorTraceId() { | ||
public String generateErrorTraceId() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private ?
|
||
@ExceptionHandler(NotFoundException.class) | ||
public ResponseEntity<Problem> notFound(final NotFoundException ex, final NativeWebRequest request) { | ||
LOG.error(ex.getMessage(), ex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug ?
@ExceptionHandler(UnableProcessException.class) | ||
public ResponseEntity<Problem> handleUnableProcessException(final RuntimeException exception, | ||
final NativeWebRequest request) { | ||
LOG.error(exception.getMessage(), exception); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug ?
@adyach I've addressed all comments. As we discussed offline, I went through all exception handlers, with the following guideline:
|
👍 |
deploy validation please |
👍 |
👍 |
# Conflicts: # src/main/java/org/zalando/nakadi/controller/SubscriptionController.java # src/main/java/org/zalando/nakadi/controller/advice/NakadiProblemExceptionHandler.java
👍 |
1 similar comment
👍 |
Upgrade zalando problems libraries
Description
This PR:
Review