Throwing the status exception - java

I have a core module that has such relationships
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-mail')
in service in method I would like to throw an exception (or otherwise) from the status code (for example, NOT FOUND 404) in case the user is not found.
getById(Long id) {
//if the user with specified id does not exist
//for example, cast an exception throw new UserNotFoundException(new List<FieldError>); with a list of error fields
}
the problem is that this module has no dependency
compile('org.springframework.boot:spring-boot-starter-web')
and cannot use objects such as ResponseEntity or HttpStatus.
I want to achieve a result such as that here https://github.com/JonkiPro/REST-Web-Services/blob/master/src/main/java/com/service/app/rest/controller/advice/ErrorFieldsExceptionHandler.java, but without org.springframework.web.
I could be advised on how I can throw an exception with the status and error list object as response?

Let's exercise the good old Single Responsibility Principle.
The Service layer is not concerned about HTTP STATUS. Throwing some sort of HttpStatus404Exception from the Service layer is not a good choice. How about if someone wants to use the Service layer in a batch processor which connects directly to the database? In this case the HttpStatus404Exception is totally out of place.
Throw a UserNotFoundException (which could extend a NotFoundException) and let the Controller layer (in your case a WebController layer) handle the exceptions gracefully.

Related

Axon framework: Handling database exceptions in state-stored aggregates

I am new to Axon framework and am trying to implement an application using CQRS with state-stored aggregates. The application relies on a database constraint (using H2 for now) to enforce uniqueness on a name attribute. I would like to catch this exception and rethrow it as a user-friendly domain exception.
Per the Axon documentation:
Exception Handling says "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class"
Message Intercepting documentation says "A function annotated with #ExceptionHandler will be regarded as a handler interceptor which will only be invoked for exceptional results. Using annotated functions to this end for example allow you to throw a more domain specific exception as a result of a thrown database/service exception."
But I cannot get this to work. I have tried adding exception handlers as follows:
#ExceptionHandler
public void handle(ConstraintViolationException ex) throws Exception {
if (ex.getMessage().contains("UNQ_COMPANY_ID") || ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new DomainException("Plan name and company id must be unique");
}
throw ex;
}
but this method is not called. I have tried putting the exception handler method on the aggregate and on a separate command handler class, tried adding resultType=ConstraintViolationException.class, and tried catching other types of exceptions including Exception, RuntimeException, AxonServerRemoteCommandHandlingException, etc. but this method is never called.
I can see the error in the log output:
org.axonframework.axonserver.connector.command.AxonServerRemoteCommandHandlingException: An exception was thrown by the remote message handling component: org.hibernate.exception.ConstraintViolationException: could not execute statement
Is it possible to catch database exceptions in state-stored aggregates? If it is, can someone point me towards what I am doing wrong?
The statement "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class" makes me wonder whether I need to create a custom repository class (rather than using the default GenericJpaRepository) but that seems like a lot more work than should be necessary.
Thank you!
Update: I was able to roughly accomplish what I want by adding a UnitOfWork parameter to the #CommandHandler method and using it to registering a rollback callback on it as follows:
uow.onRollback(unit -> {
DefaultUnitOfWork duow = (DefaultUnitOfWork) unit;
Throwable ex = duow.getExecutionResult().getExceptionResult();
while (ex != null) {
if (ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new RuntimeException("Plan name must be unique");
}
ex = ex.getCause();
}
});
But this seems kind of verbose, as well as limiting me to throwing unchecked exceptions only. This also doesn't feel like the right way to do this though because I assume the purpose of the #ExceptionHandler annotation is to eliminate need for code like the above.
This is doable of course.
Actually, the best pointer I could give you if the code-samples repo where you can see a sample about distributed exceptions.
In general, as you could see in your shared log, the 'original' exception is wrapped into an AxonServerRemoteCommandHandlingException meaning you will have to handle that. Doing that, you can pretty much add anything to the details field of this class, adding the indication you had a ConstraintViolationException for example (or an ERROR_CODE, like HTTP protocol does) and you are fine to unwrap it on the other side.
What might be the "gotcha" you require, is to know that an #ExceptionHandler annotated method should reside in the object handling the message. So if you want to react to a failing command handling operation (which would be the case in your sample), you will need to place the exception handler in the Aggregate, next to the Command Handler.
That fact you get an AxonServerRemoteCommandHandlingException to me suggests the exception is caught on the command dispatching end. So, prior to dispatching a command on the CommandGateway/CommandBus.
However, whether this is the problem at hand, isn't clear to me right now, since the sample only shows the exception handler and not where it resides. Please share whether my assumption on the placement of the exception handler is correct. If not, we'll dive into this deeper to get to the cause.

Catching all exceptions and returning an exception with list of messages

I'm wondering if there is any elegant way to catch all exceptions (specifically custom runtime exceptions) and return an exception containing a list of the messages.
Instead of having a String message, the big exception would then contain String[] message for example.
Scenario:
A REST request is made to the back-end with a JSON object containing a bunch of fields. I want to validate these fields on the backend and return a list of errors if any exceptions occur.
If both the name and lastname field are not acceptable input, I don't want to throw an exception on the invalid name and have the user change the name and submit again only to get an error message that the lastname is invalid too.
Hence why I want to collect all invalid input and return a list of these in the form of an exception.
Spring collects JSR-303/JSR-349 bean validation failures into a BindException:
Thrown when binding errors are considered fatal. Implements the BindingResult interface (and its super-interface Errors) to allow for the direct analysis of binding errors.
Instead of developing your own mechanism for bean validation you might want to read 3. Validation, Data Binding, and Type Conversion and follow the standards.
With Spring Boot, you can use the following annotation to handle any kind of Exception for a class or a method :
#ExceptionHandler(YourExceptionHandler.class)
And you can create a class that let you regroup all your custom exception management like this (if you want to gather it) :
#ControllerAdvice
class GlobalControllerExceptionHandler {
#ResponseStatus(HttpStatus.CONFLICT) // 409
#ExceptionHandler(DataIntegrityViolationException.class)
public void handleConflict() {
// Nothing to do
}
}
You can also implement the interface HandlerExceptionResolver to manage all Exceptions that ARE NOT handled by the Controllers (all the others runtime Exceptions)
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex);
}
Everything is explained in details here : https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
EDIT: I just read that you added up scenario. Actually, for your special case, you should just parse the object, and return one exception (like bad object format, along with a 400 HTTP status code error, with a custom message containing all the fields that are invalid. I guess.

Can we handle a exception from dao layer to presentation layer without impacting the service layer(no modification in service layer)

The scenario is like I wrote a MVC-based application:
Controller - Service - DAO layer. Now I got an exception in DAO layer and I want to handle that exception in presentation layer so that service layer needs no change.
Because by using regular try/catch or throws it has to pass through the service layer which I don't want.
Is there any better approach to achieve it?
class Controller{
method1(){}
}
class service(){
method1Serice(){}
}
class DAO(){
method1DAO(){
// exception occurs here
}
You can have the DAO class throw an unchecked exception. (any subclass of RuntimeException will do). You can create your own custom exception or use any of the predefined ones. just make sure the Service doesn't catch Throwable and you can have the Controller catch it.
You can extend your exception class from RuntimeException so that compiler does not complain about exception handling. You can then catch that exception in the presentation layer.
Perhaps you are looking for Controller Based Exception Handling, you can check these in Exception Handling in Spring MVC and also Error Handling for REST with Spring.
#ExceptionHandler(YourException.class)
public String handleException(){
logger.info(message);
return "database_error";
}
Actually I would suggest you handle the exceptions properly in Service-Layer and encapsulate that exception properly to return to the front-user via Controller-Layer.
Normally, checked exceptions are carrying some meaningful messages which can be used to do recovery or let the caller explicitly handle it properly. Try not to directly avoid it since it's there.
As I understand it, a data access object (DAO) is intended for transferring data between the server and the client. I'm assuming that the client is what you refer to as the presentation layer. In other words, the part that the end user interacts with. As such, the DAO should contain fields and accessor methods only, i.e. it should not contain logic. Hence it should not contain methods that may throw exceptions. So I would suggest perhaps re-designing your application. Otherwise, perhaps you can provide more detailed code?

How to handle different roles for multiple elements for a single user?

First of all, I'm new to spring-boot and spring-security.
I've read a lot of documentations (especially on http://www.spring.io) but I don't find a lot of information. I'm also working with JsonWebTokens, so all my authentication process is based on this. I followed this excellent tutorial to implement JsonWebToken authentication with spring-security : http://blog.jdriven.com/2014/10/stateless-spring-security-part-2-stateless-authentication/
So here is my problem :
I am working on a bug tracking application. For each project, multiples users may have different role (reporter, developer, admin, etc.). In the aforementioned tutorial, the authority is grant for the whole restful API, and the user only have one role for the entire API. However, in my case, I need to check first if the user has the good role for the good project (project is sent through http query parameter) and I have no clue how to handle this. To summarize, a user could call an URI like /tickets/close/{id} on a project, but not on another.
At the moment, my WebSecurityConfigurerAdapter overrides the configure() method like :
http
...
.antMatchers("/admin/**").hasAuthority("ROLE_ADMIN")
.anyRequest().hasAuthority("ROLE_USER").and()
...
But it obviously don't take care of the query parameter in that case.
What you're after is not "different roles" for a user, rather authorizing a user for access to an object or set of objects.
Read through Domain ACLs, your users would be authorized differently for different projects, and the project would be the parent authorizing object for the issues, and issues would inherit from projects.
Since your security rules needs to consider your application domain, I would implement the security rules within your controllers. If your controllers detect that a user is trying to access a forbidden resources, you would respond by an ResponseEntity with a 503 error.
What I usually do is to throw a custom exception from my controller and define an Exception Handler. That exception handler would handle the 503 response. Here is an exemple :
#ControllerAdvice
public class ExceptionHandlerConfig {
#ExceptionHandler(ValidationException.class)
public ResponseEntity<Error> handleInvalidFileFormatException(HttpServletRequest request, RuntimeException ex) {
Error error = new Error(0, new Date(), request.getRemoteAddr(), request.getRemoteHost(),
request.getHeader("User-Agent"), ex.getMessage(), ExceptionUtils.getFullStackTrace(ex));
if (ex instanceof ValidationException) {
return new ResponseEntity<Error>(error, HttpStatus.BAD_REQUEST);
}
LOGGER.error("Error while processing request.", ex);
return new ResponseEntity<Error>(errorService.save(error), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
This is a custom ValidationException handler that generates a 500 HTTP response with the error message wrapped in a JSON object. You would reuse that for yourself with a custom SecurityException and flag the ResponseEntity with a 503 rather than a 500.
Best of luck.
Edit : ACL would definately be the best choice to keep the proper segregate of your business logic from the security aspect. However it might be complicated to setup if you are not familiar with Spring Security Advanced concepts.

Should Service layer throw an exception?

I don't like throwing exceptions for some reason, maybe because of the performance hit I don't know, wondering if I should re-think this issue.
Should my service layer (uses Dao's + business logic etc.) be throwing exceptions?
public ModelAndView createProduct(#Valid ProductForm productForm, ..) {
ModelAndView mav = new ModelAndView(...);
if(bindingResult.hasErrors()) {
return mav;
}
// throw exception if user doesn't have permissions??
productService.create(product, userPermissions);
}
So my options in the create method of the ProductService:
if the user doesn't have permissions, throw an exception
return some sort of a Response object that will have the new product Id if it was a success, along with a success/failure flag and a error collection.
Things to keep in mind:
I may re-use this service layer in a non-web app, also in a restful web service.
What is considered best practice?
Depends of what you mean by service and exception, but in the context you've got I'll assume a java exception from a HTTP endpoint.
The answer is no. Services should expose errors in a general way. In the case of Restful service, errors should be propagated as HTTP status with error codes. The service shouldn't leak implementation details to consumers. It's a natural boundary.
The Consumer should handle those error situations and decide the most appropriate what to communicate that. It may well choose to generate an exception. But these exceptions are disjoint from the original issue/eception that caused the service to return an error code.
Going further I would say #yahir is right in what he says also. HTTP service would expose HTTP errors, and it may well just be using another service underneath that returns another kind of errors, but it's job will be to handle or map them appropriately.
Ask yourself what other options do you have, sometimes exceptions are necessary. The only other thing you could do is return a status of failure or success and handle appropriately.
I'd say the service layer should behave just like any other method exposed to client code. After all, that's exactly what it is.
Clients that will use it through RPC, will expect exactly this behavior.
Other cilents, such as REST, should anyway access the services layer through some other wrapping layer (e.g. Controller layer). One of this wrapping layer duties is transforming the response to be client-consumable.

Categories

Resources