I have multiple #Service's in my Spring boot application which mainly make API calls to some external services.
Do Spring offers a custom Exception for a kind of a "404" exception? i.e. the item not found / there's no result for the requested key.
I'm aware of NoSuchElementException class but it doesn't seem to really fit here.
I guess I could create my own NoResultException but I'd like to follow the convention (if there's such)
Thanks!
There is no such exception provided by the Spring framework for the case of 404, or any other HttpStatus, for that matter.
You should ideally handle that in your service layer based on the API response and throw a custom exception which denotes the 404 case according to your domain. You can have a #ControllerAdvice which handles the specific exception and provides a custom response accordingly.
What you can use is HttpStatusCodeException. More details int the documentations. Example constructor is
HttpStatusCodeException(HttpStatus statusCode, java.lang.String statusText)
where you can provide your code, for example 404 and message. Thrown in service will be translated into the right http response.
Related
There are multiple ways to send custom message in error response of rest api call.
Which is the best way out of these :
1.One way is to use io.swagger.annotations like
#ApiResponses(value = { #ApiResponse(code = 500, message = "error message", response=ErrorDescription.class) })
above method signature.
2.Another way is to define #ControllerAdvice over global exception hanlder.
Which is the better way of two.
Thanks
Your first approach with the swagger annotation won't handle your errors in your application. It's just for documentation purposes so that you can see how your API behaves in an error case. With this annotation, you customize your swagger-ui.html page for your REST endpoint and map the error code to a specific response object and add a custom description for your clients.
To really handle e.g. exceptions with self-defined response types and message you can use #ControllerAdvice and define the result types and messages. In addition, I would also use the Swagger annotation to write some text about the error case and tell the client which response object he can expect.
The following blog post might help you for writing your #ControllerAdvice clas: http://niels.nu/blog/2016/controller-advice-exception-handlers.html
Is it fine to throw an exception on the server side when the requested resource was not found?
the client receives a 404 not found. My concern is whether it is fine/wrong to throw an exception on the server side when this happens.
It's hard to assume what your are trying to do with the level of details you added to your question.
However, if you handle the exceptions properly, there may be nothing wrong with that approach. Have a look at the approaches used by some frameworks:
JAX-RS
You can throw a WebApplicationException, that will be mapped a response. You can define your own subclasses of WebApplicationException or use the existing ones. The NotFoundException, for example, will be mapped to a response with the 404 status code. For more details on the existing exceptions, refer to this answer.
You also can create your own ExceptionMapper to map any exception to a desired response.
Spring MVC
You can map exceptions to responses by annotating an exception class with #ResponseStatus.
It also gives you the possibility to implement a HandlerExceptionResolver or extend one of the existing implementations, such as the AbstractHandlerExceptionResolver.
Another approach would be using a ResponseEntityExceptionHandler annotated with #ControllerAdvice and define the handled exceptions by annotating the implemented method with #ExceptionHandler
Basically it is not ideal to throw reserved status codes of exception. You should handle this exceptions internally and prepare your own code with meaning full message that client should know the actual problem.
I would say add a filter to capture 404 and add custom information about the 404 details.
In case of pure REST implementation, any resource-id missing and malformed URL will return 404.
As far as REST contract, both cases are correct to have 404 response. But more details on what type of resource is missing will help the client side consuming it to take appropriate actions.
Related discussion:
return-404-when-a-rest-resource-is-not-found
From perspective of semantics: Exception should be thrown if condition is such that condition is unrecoverable and devs must be notified about it.
Server cannot resolve auth request in the beginning of a session - this is serious enough situation and exception is appropriate.
User didn't fill out obligatory field and tried sending a form. This problem can be fixed and an exception would be a bad design.
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.
I have an application which consists of SOAP and REST web services and a simple HTTP access. All of them convert incoming requests and send them to a handler. The most painful thing is exception handling. In order to return the right response, I have to wrap every method with try-catch block and create a response there.
I thought that I could create a filter which could do it. But how can the filter recognise the source of it (soap, rest frontend) so I knew that I should return a SOAP or other response?
It depends on the WS framework you use. All I know have some sort of interceptors/aspects that you can inject and handle exceptions in one place. For instance in apache-cxf there is even a special outbound error chain where you can plug your own interceptors.
Obviously try-catch in every method is a bad idea.
In layer of below Web-Service Layer, you have to create your custom Exception and in Web-Service layer you have to use try-catch approach for achieve occurred exception and in catch block log and convert it to your custom web service layer exception. I show this approach in following:
#WebService
public class EmployeeWS
{
#WebMethod
public void add(Employee em) throws CustomWebServiceException
{
try
{
// call facade layer method
}
catch(Exception e)
{
logger.error(e.getMessage());
throw new CustomWebServiceException(e);
}
}
}
Alternative using try catch in any Web-Method,you can use AOP approch(for sample Spring AOP) or interceptor approach in Web-Service frameworks(for sample SOAPHandler<T> in JAX-WS).
Note: In JAX-WS standard, you can't throw a RuntimeException because Exception must specify in final WSDL and if you throw a RuntimeException your web service client don't achieve your CustomException, in another your Web-Methodneed to throws in itself signature.
You can see selected Web-Service faramework documents for more information.
It sounds that you are not using any framework because that was typical frameworks provide. For example Spring allows you to decouple the code from exception handling and define your custom exception handlers.
In your case you generally have 2 solutions.
(1) You can use Decorator pattern: wrap each service with decorator where each method is implemented as
try {
call real method
} catch() {
send error to client
}
Since it is very verbose you can save time using Dynamic proxy (feature that was introduced in java 5). So, you can dynamically wrap each service (if your services have defined interface).
(2) You can solve it using servlet API's error page:
javax.servlet.ServletException
/servlet/ErrorDisplay
for more details see http://java.sun.com/developer/technicalArticles/Servlets/servletapi2.3/
You can customize your class!! Do it!
Take easy on diagnostic errors, like insert a protocol number, message Log, message client, etc...
http://java.globinch.com/enterprise-java/web-services/jax-ws/jax-ws-exceptions-faults-annotation-exception-and-fault-handling-examples/#Pre-Requisites
I have a RESTful web service that responds to /user/{userId} with a marshalled XML representation of a User domain object (using JAXB). What's an appropriate way of communicating back to the client additional details about their request, particularly if it doesn't return the information they're expecting? In a non-distributed Java application, you might have a catch block that deals with data access, or security exceptions. In the event that /user/{userId} doesn't return anything (e.g. the web services persistence mechanism isn't working, there is a security restriction, etc...) how do I include meaningful information in the response to the client?
I don't think DTOs are what I need because I'm not looking for different representations of a domain object. Rather, I'm looking for information about what happened during the request that may have prevented it from returning the information the client expected. Would it be appropriate to enclose the domain object within some kind of ResponseObject that holds the relevant metadata? The downside to this approach is that I'd rather not have my service layer interfaces all have ResponseObject as their return type because I may very well provide a non-RESTful implementation that doesn't have the same metadata requirements.
What's an appropriate way of communicating back to the client additional details about their request, particularly if it doesn't return the information they're expecting.
In the event that /user/{userId} doesn't return anything (e.g. the web services persistence mechanism isn't working, there is a security restriction, etc...) how do I include meaningful information in the response to the client?
This is what the HTTP Status Code is used for in a RESTful service.
To indicate that a requested userId doesn't correspond to an actual user, you can return a 404 Not Found.
To indicate an internal error within your application (such as not being able to connect to the database), you can return 500 Internal Server Error.
The option you are describing - wrapping your returns in a ResponseObject which then includes the true "response status" - sounds an awful lot like SOAP.
The beauty of REST, or at least what people claim, is that you can use the already-existing HTTP response status code to model almost all statuses of your actual response.
If it's really error situation (security problems, no DB connection or even user with provided ID not found), then just throw an Exception. Client receives fault and can behave according to information contained in it.
Which implementation do you use? In Apache CXF, for example, you can define exception handler and render XML for exception yourself, and there you are free to include any meta-info you like.
I would capture the information using exceptions, then map those exceptions to an HTTP response with the appropriate status code. You can achieve this by creating an implementation of ExceptionMapper if you're using JAX-RS, or you can subclass StatusService if you're using Restlet.
http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features
http://wiki.restlet.org/docs_2.0/13-restlet/27-restlet/331-restlet/202-restlet.html