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
Related
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.
Is there a way to somehow globally handle unchecked exceptions in osgi (karaf) that were thrown in servlets?
What I mean is something like in Spring, where there is #ControllerAdvice where you can specify methods for each exception type and handle it.
I would like to unify the exception handling in my rest api that exposes osgi services.
Doing REST in OSGi
You mention REST and Servlets in this question. If you're using REST in OSGi then the JAX-RS Whiteboard is the easiest way to do things. If you want to use raw Servlets, then the Http Whiteboard is the way to go. Both models make it easy to handle exceptions.
Update
In an effort to make it easier for people to see how this works, I've created a working example on GitHub which covers Servlets and JAX-RS error handling.
Using the HTTP Whiteboard
The HTTP whiteboard allows servlets to be registered as OSGi services and then used to handle requests. One type of request handling is to act as an error page.
Error pages are registered with the osgi.http.whiteboard.servlet.errorPage property. The value of this property is one or more Strings containing either:
A fully qualified class name for an exception that should be handled
A three digit error code
The OSGi specification describes this in an example, and other pages list the attributes that you can use to work out what went wrong.
For example this servlet will be called for IOException, NullPointerException and for status codes 401 and 403:
#Component
#HttpWhiteboardServletErrorPage(errorPage = {"java.io.IOException", "java.lang.NullPointerException", "401", "403"})
public class MyErrorServlet extends HttpServlet implements Servlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws Exception {
Throwable throwable = (Throwable) request
.getAttribute("javax.servlet.error.exception");
Integer statusCode = (Integer) request
.getAttribute("javax.servlet.error.status_code");
// Do stuff with the error
}
}
N.B. I have used OSGi R7 Component Property Type annotations to make this simpler to read. It will work with older versions of DS and the Http Whiteboard equally well.
Using the JAX-RS whiteboard
The JAX-RS Whiteboard allows you to use any of the JAX-RS extension types as a whiteboard service. In this case you want an ExceptionMapper.
In this example we add a handler for IOException
#Component
#JaxrsExtension
public class MyExceptionMapper implements ExceptionMapper<IOException> {
Response toResponse(IOException e) {
// Create a response
}
}
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?
I have a typical RESTful web service with two layers. A resource layer and a service layer. The DAO layer seems obsolete with modern object relational mapping libraries.
I am using Google Cloud Endpoints which not surprisingly returns HTTP errors in the form of Java Exceptions. I have a dedicated set of Exceptions the service layer can throw, such as an Object Not Found Exception, from the object relational mapping library, and other internal exceptions. Suffice to say, each internal exception has an HTTP Exception counterpart.
In order for a resource to safely call a service method, the call is surrounded in a series of try catches.
try {
resourceObject = CorrespondingService.method(...);
} catch (InternalExceptionOne internalExceptionOne) {
throw new CorrespondingWebExcpetionOne(internalExceptionOne.getMessage());
} catch (InternalExceptionTwo internalExceptionTwo) {
throw new CorrespondingWebExcpetionTwo(internalExceptionTwo.getMessage());
} catch (InternalExceptionThree internalExceptionThree) {
throw new CorrespondingWebExcpetionThree(internalExceptionThree.getMessage());
}
Since every call to a service method from the resource layer must be wrapped in the same series of try catch statements this creates a lot of repeated code.
I was looking to create a Utility that could act as a WebExcpetionTranslator, but I would have to pass it a method to be run under a try catch. Not sure how to pass a method and parameters, and then how to subsequently call said passed method.
This seems a bit sloppy though? Its there any thing out there that might do this with annotations?
How can I pass a method and arbitrary parameters to a utility method, and subsequently call the passed method with the parameters?
What about annotations? Can you make a custom annotation to handle different exceptions?
P.S. My technology stack is GAE, Objectify, and Google Cloud Endpoints.
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.