RestEasy custom action on every request - java

I would like to invoke some custom method when a REST call has finished, looking up annotations on the originating method and the generated response.
I know you can use the PostProcessInterceptor or MessageBodyWriterInterceptor for this task but they do not get invoked in case of an exception.
My current solution is such that every method throws a special exception which is then handled by a custom ExceptionMapper, but there I have no information about the original request and where it came from.
Is there a global wide handler you can bind to in order to get the information about the original request in case of an exception?
And yes I know about this question: RestEasy Post Process Interceptor chain not traversed when response created by ExceptionMapper

To answer my own question.
One can inject the original request into the ExceptionMapper and react or perform a custom action accordingly.
#Provider
public class MyExceptionMapper implements ExceptionMapper<Throwable> {
#Context
private HttpServletRequest request;
#Override
public Response toResponse(Throwable exception)
{
// trigger event
triggerOnExceptionEvent(request, exception);
}
...
}

Related

Custom #ControllerAdvice in Spring for exception handling

I am trying to map exceptions from my rest controllers to responses which have a body, and to do it in a central place.
I have tried this:
#Order(Ordered.HIGHEST_PRECEDENCE)
#ControllerAdvice
public class RestErrorResponseExceptionHandler extends ResponseEntityExceptionHandler {
#Override
protected ResponseEntity<Object> handleExceptionInternal(
Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
super.handleExceptionInternal(ex, body, headers, status, request);
return ResponseEntity.status(status).body(Error.from(status));
}
}
The problem is that the handler is never triggered.
If I define a custom method with #ExceptionHandler in my rest controllers, or extend something that has #ExceptionHandler, then all works well, but that introduces some bad design.
It is my understanding that Spring will first try to look in controller for exception handling methods, then it will check for registered handlers.
I am trying to verify the behaviour via WebMvcTest, and responses I'm getting are not the Error objects that I'm expecting.
Is there something I'm missing?
The ControllerAdvice is a configuration that have to be registered by Spring. You have to move your class in the config package or you can register it by annotation.
In my case, I work with a controllerAdvice like this one :
#ControllerAdvice
public class GlobalControllerExceptionHandler {
#ExceptionHandler(MyException.class)
public ResponseEntity<String> reponseMyException(Exception e) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("my message");
}
}
Spring Framework provides following ways to help us achieving robust exception handling.
Controller Based – We can define exception handler methods in our controller classes. All we need is to annotate these methods with #ExceptionHandler annotation. This annotation takes Exception class as argument. So if we have defined one of these for Exception class, then all the exceptions thrown by our request handler method will have handled.
These exception handler methods are just like other request handler methods and we can build error response and respond with different error page. We can also send JSON error response, that we will look later on in our example.
If there are multiple exception handler methods defined, then handler method that is closest to the Exception class is used. For example, if we have two handler methods defined for IOException and Exception and our request handler method throws IOException, then handler method for IOException will get executed.
Global Exception Handler – Exception Handling is a cross-cutting concern, it should be done for all the pointcuts in our application. We have already looked into Spring AOP and that’s why Spring provides #ControllerAdvice annotation that we can use with any class to define our global exception handler.
The handler methods in Global Controller Advice is same as Controller based exception handler methods and used when controller class is not able to handle the exception.
HandlerExceptionResolver – For generic exceptions, most of the times we serve static pages. Spring Framework provides HandlerExceptionResolver interface that we can implement to create global exception handler. The reason behind this additional way to define global exception handler is that Spring framework also provides default implementation classes that we can define in our spring bean configuration file to get spring framework exception handling benefits.
SimpleMappingExceptionResolver is the default implementation class, it allows us to configure exceptionMappings where we can specify which resource to use for a particular exception. We can also override it to create our own global handler with our application specific changes, such as logging of exception messages.
Make sure of 2 things and your code will work.
Your #ControllerAdvice class is available in component-scan path.
Make sure the methods in your #ControllerAdvice have structure somewhat like this-
#ExceptionHandler(value = { RequestProcessingException.class })
public #ResponseBody ResponseEntity<ErrorMessageBO> hotelConfigServiceExceptionHandler(HttpServletRequest request, RequestProcessingException e) {
logger.error("Exception with tracking Id: {}, dev message: {} and Message:", RequestContextKeeper.getContext().getRequestId(), e.getDeveloperMessage(),e);
return new ResponseEntity<ErrorMessageBO>(new ErrorMessageBO(e.getErrorCode(), e.getMessage(),RequestContextKeeper.getContext().getRequestId(),e.getDeveloperMessage()), HttpStatus.OK);
}

How can i preserve the request headers in error response prepared through JAX-RS ( Apache-CXF implementation) ExceptionMapper

I am implementing JAX-RS using apache CXF. I have created an ExceptionMapper to handle bad requests like this:
public class ClientErrorExceptionMapper implements ExceptionMapper<ClientErrorException> {
#Override
public Response toResponse(final ClientErrorException exception) {
return Response.status(Response.Status.BAD_REQUEST).entity("Invalid request: Invalid URI.").build();
}
}
I am not sure how this works internally but i suppose that framework would throw an exception in case user is making an invalid request and this handler will prepare an error message to be send back. My problem is that i wish to preserve some custom headers that user sends in the request, so that i send that back with the response. But using this exception mapper, i cant see any option to get the original request headers. I can set any new header in the response, but i wish to preserve the request headers - like i do in a normal request.
So is there any way in JAX-RS where i can preserve or efficiently refer to the custom headers in current request ?
What we have resorted to is using a thread local variable to save the RequestContext when the request arrives and then in the ExceptionMapper we can obtain request specific information.
Ugly but it works. I think we have a generic filter in the filter list that catches all requests before dispatch.

How to use Jersey's internal routing mechanism to extract a class/method reference?

I have a Jersey 1.8 application running. Jersey is running as a Servlet.
I need to write a servlet filter that given a plain request/response, is able to figure out which REST resource/method will respond to the request and extract values from annotations.
For example, imagine I have the following resource:
#Path("/foo")
#MyAnnotation("hello")
public class FooResource {
#GET
#Path("/bar")
#MyOtherAnnotation("world")
public Response bar(){
...
}
}
When a request GET /foo/bar comes in, I need my servlet filter to be able to extract the values "hello" and "world" from MyAnnotation and MyOtherAnnotation before Jersey's own servlet processes the request.
This filter logic should be able to work for all requests and all resources registered.
Is there a way to access Jersey's internal routing mechanism to obtain a class/method reference where Jersey will dispatch the request?
I'm open to other suggestions as well, but ideally nothing like trying to hack my own routing mechanism by reading the #Path annotations myself.
#Provider
#Priority(Priorities.AUTHORIZATION)
public class MyFilter implements ContainerRequestFilter
#Context // request scoped proxy
private ResourceInfo resourceInfo;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
if (resourceInfo.getResourceClass().isAnnotationPresent(MyAnnotationion.class) ||
resourceInfo.getResourceMethod().isAnnotationPresent(MyOtherAnnotation.class)) {
to register the filter use
bind(AuthFilter.class).to(ContainerRequestFilter.class).in(Singleton.class);

Spring: Response time

I have a SOAP webservice(spring ws)and need to save the response time of every request that I receive. I could create a servlet filter that measures time difference between HTTP Request and HTTP Response. But, I need to log the response time together with some values that I read from soap request envelope, and since at that time request is raw and needs to be unmarshalled, that's an expensive and redundant operation to unmarshall for every request.
So is there a way to calculate it using SpringWS? like in a payloadInterceptor?
Yes, implementing an EndpointInterceptor is the best fit for this task, as it gives you access to the SOAP messages through the MessageContext. See the Reference Documenation.
I think you can use two tools.
AspectJ with its annotation #Before and #AfterReturning. The pointcut could be the method that receives the request (#WebMethod).
#Before("call([package, class and method that receives the request]")
public void before(JoinPoint joinPoint) throws Throwable {
...
}
#AfterReturning(pointcut = "call([package, class and method that receives the request])", returning = "result")
public void after(JoinPoint joinPoint, Object result) throws Throwable {
...
}
The JoinPoint object has the information of the method's parameters
Override the method handleMessage of a custom class that implements the SOAPHandler class. This method will be executed every time a SOAP request is received.
I hope this can give you ideas to resolve your problem.

How to intercept custom HTTP header value and store it in Wicket's WebSession?

I need to grab a certain custom HTTP header value from every request and put it in WebSession so that it will be available on any WebPage later on. (I believe the Wicket way to do this is to have a custom class extending WebSession that has appropriate accessors.)
My question is, what kind of Filter (or other mechanism) I need to be able to both intercept the header and access the WebSession for storing the value?
I tried to do this with a normal Java EE Filter, using
CustomSession session = (CustomSession) AuthenticatedWebSession.get();
But (perhaps not surprisingly), that yields:
java.lang.IllegalStateException:
you can only locate or create sessions in the context of a request cycle
Should I perhaps extend WicketFilter and do it there (can I access the session at that point?), or is something even more complicated required?
Of course, please point it out if I'm doing something completely wrong; I'm new to Wicket.
I'd guess you need to implement a custom WebRequestCycle:
public class CustomRequestCycle extends WebRequestCycle{
public CustomRequestCycle(WebApplication application,
WebRequest request,
Response response){
super(application, request, response);
String headerValue = request.getHttpServletRequest().getHeader("foo");
((MyCustomSession)Session.get()).setFoo(headerValue);
}
}
And in your WebApplication class you register the custom RequestCycle like this:
public class MyApp extends WebApplication{
#Override
public RequestCycle newRequestCycle(Request request, Response response){
return new CustomRequestCycle(this, (WebRequest) request, response);
}
}
Reference:
Request cycle and request cycle
processor

Categories