Global servlet exception handling in OSGI. How? - java

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
}
}

Related

"no result exception" for Spring #Service's

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.

Use ExceptionMapper to log CLIENT_ERRORs

I am working on an application which uses Dropwizard, which has this implementation of ExceptionMapper: https://github.com/dropwizard/dropwizard/blob/master/dropwizard-jersey/src/main/java/io/dropwizard/jersey/errors/LoggingExceptionMapper.java
Problem with this implementation is that even though this catches both 4** and 5** errors, it only logs 5** errors.
I need to implement ExceptionMapper such that LoggingExceptionMapper is not used at all and my CustomExceptionMapper logs both CLIENT_ERRORs and SERVER_ERRORs.
I am wondering how would my application know that it needs to use CustomExceptionMapper instead of the Dropwizard class?
Also would it suffice to add CLIENT_ERROR to if condition, to log out all errors?
#Override
public Response toResponse(E exception) {
// If we're dealing with a web exception, we can service certain types of request (like
// redirection or server errors) better and also propagate properties of the inner response.
if (exception instanceof WebApplicationException) {
final Response response = ((WebApplicationException) exception).getResponse();
Response.Status.Family family = response.getStatusInfo().getFamily();
if (family.equals(Response.Status.Family.REDIRECTION)) {
return response;
}
if (family.equals(Response.Status.Family.SERVER_ERROR) || family.equals(Response.Status.Family.CLIENT_ERROR) {
logException(exception);
}
return Response.fromResponse(response)
.type(MediaType.APPLICATION_JSON_TYPE)
.entity(new ErrorMessage(response.getStatus(), exception.getLocalizedMessage()))
.build();
}
Or would there be a better way to do this?
JAX-RS spec about ExceptionMapper:
When choosing an exception mapping provider to map an exception, an
implementation MUST use the provider whose generic type is the nearest
superclass of the exception.
How would my application know that it needs to use CustomExceptionMapper instead of the Dropwizard class?
You can throw a custom exception from your application and create an ExceptionMapper for that specific exception.
Would it suffice to add CLIENT_ERROR to if condition, to log out all errors?
Yes, 4xx and 5xx family has all the error responses.

Spring boot exception handling for specific annotated methods

Our spring boot controllers have methods called by ajax as well as the standard methods rendering CRUD templates. We'd like to be able to annotate all our ajax methods with a single annotation so that regardless of what type of exception is thrown, we can return a response the ui can handle.
I've been looking at the ControllerAdvice and ExceptionHandler annotations, but I don't think either can be used the way we intend. ControllerAdvice can only cover entire controllers, so any exception handling would also cover the non-ajax methods. Similarly, the ExceptionHandler annotation would handle exceptions from both types of methods.
The current idea is to split the two types of methods, ajax and CRUD, into separate controllers. Is there another way to do this?
I don't think this is that much easy/straightforward in Spring (or at least to my current spring knowledge).
We'd like to be able to annotate all our ajax methods with a single
annotation
Apart from separating ajaxMethods into another controller, I can think of another way of doing this.
1.Declare your own exception class like myAjaxException.
2.Don't handle this exception in controller, just throw it when you encounter any exception inside your ajax methods.
try{
//....
}catch(Exception ex){
throw new myAjaxException("this is myAjaxException blah blah blah");
}
3.Intercept myAjaxException by implementing HandlerExceptionResolver as below.
Any Spring bean declared in the DispatcherServlet’s application
context that implements HandlerExceptionResolver will be used to
intercept and process any exception raised in the MVC system and not
handled by a Controller.
public class AjaxExceptionResolver implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
if (ex instanceof myAjaxException) {
//return response to UI
}
}

How to call a Servlet/Filter before a JSP is executed in CQ5?

In a Spring MVC application we have a Controller that would execute before calling the JSP. The Controller would prefetch some values from the database and set them in the model and forward the control to JSP.
How do I implement this feature in CQ 5? I want the SlingFilter to execute before the JSP is executed. And the JSP is not a page component but a component that appears in the side kick.
Note:
I can do this by writing my own SlingSerlvet that would prefetch my required values and use the RequestDispatcher to forward to the JSP.
But by this method I would have to go through a URL like "/bin/.*". And this is again at a page level I want this kind of functionality at component level.
So to answer your specific question, if you want a filter to be executed before a component is called you would create a filter that is listening to Component level filter scope.
See
http://sling.apache.org/documentation/the-sling-engine/filters.html
You would then have your filter change the incoming request to a SlingServletRequest and determine if the target resource is the one that you are looking for.
However this filter would be executed on every single component that is being included on a page. The reverse process of this that may be useful to you is the ResourceDecorator.
http://sling.apache.org/documentation/the-sling-engine/wrap-or-decorate-resources.html
These are executed when the resource is identified, prior to the servlet and filter calls, which would allow you to verify if a resource is a type that you are interested in, and then allows you to add additional information to the resource object.However this is, once again a service that would be applied to every resource that is identified.
However, if what you are looking for is a filter that is only executed for a specific path, then no. Sling doesn't do that. You mentioned Spring MVC and Spring MVC works on a completely different concept of MVC then what Slings version of MVC does.
EDIT
So in a traditional web app, the servlet would be at a fixed position and all filters are applied prior to the call to that servlet. In Sling you are dynamically wiring servlets together to generate the resulting page. So each time that you are in a servlet and call directly or indirectly the request dispatcher, it's executing the resolution process again and applying a series of filters again before the new servlet is executed.
To prevent a high level filter that needs to applied only to the main request being applied on every single internal dispatch, they came up with the idea of contexts, or chains of filters that are applied at different times and associated with different types of includes.
Here is a basic filter that will log a message when it's called. I did this from memory so you'll need to dink with it.
#SlingFilter(scope = SlingFilterScope.COMPONENT, order = Integer.MIN_VALUE)
public class SampleFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(SampleFilter.class);
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
Resource res = slingRequest.getResource();
if (!(res == null || ResourceUtil.isNonExistingResource(res))) {
LOG.error("this servlet is called before resource {} at path {}", res.getName(),res.getPath());
}
chain.doFilter(request, response);
}
}
The important part of this is scope = SlingFilterScope.COMPONENT take a look at the page I had listed earlier and try out different combinations of slignfilterscope and you'll see how it's being applied at different times. scope = SlingFilterScope.REQUEST would be once at a top level on a per page basis.
JE Bailey's answer is correct as far as Filters are concerned, but I suspect your problem might be solved in a different way that better fits Sling's view of the world.
Sling promotes the use of OSGi services for business logic, and scripts should be a thin layer above that. Moving your logic to OSGi services and calling those from your scripts is the recommended way.
You might also have a look at Sling Models which can include processing steps (with #PostConstruct) before the rendering scripts kick in.
But by this method I would have to go through a URL like "/bin/.*".
You can also register a servlet against a resource type, as well as by path, e.g. (from the Sling documentation):
#SlingServlet(
resourceTypes = "sling/servlet/default",
selectors = "hello",
extensions = "html",
methods = "GET")
public class MyServlet extends SlingSafeMethodsServlet {
#Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
...
}
}
If you remove the "selectors", "extensions" and "methods" parameters on the annotation, this servlet would bind against all calls to sling/servlet/default without requiring binding against a set path.

The best way of exception handling in an app with web services

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

Categories

Resources