Can ExceptionMapper (Java EE 6) handle NON RuntimeException's? - java

I would like to know if it is possible to have an ExceptionMapper handle subclasses of Exception and not just subclasses of RuntimeException?
Take the following code as an example. If the ExampleException extends RuntimeException then the test passes with no errors. However if the ExampleException extends Exception then the test throws an error. See below of the error output.
The following is four classes:
ExampleException
ExampleExceptionMapper
ExampleRest
ExampleRestTest
Here is the code:
public class ExampleException extends Exception {
public ExampleException(String message) {
super(message);
}
}
#Provider
public class ExampleExceptionMapper implements ExceptionMapper<ExampleException> {
#Override
public Response toResponse(ExampleException ex) {
return Response.ok("Exception!").build();
}
}
#Path("/example")
public class ExampleRest {
#GET
#Path(value = "/throw")
public String throwException() throws ExampleException {
throw new ExampleException("exception");
}
}
#EnableServices(value = "jaxrs")
#RunWith(ApplicationComposer.class)
public class ExampleRestTest {
#Module
public EjbModule module() {
EjbJar ejbJar = new EjbJar("beans");
ejbJar.addEnterpriseBean(new SingletonBean(ExampleRest.class));
final OpenejbJar openejbJar = new OpenejbJar();
openejbJar.addEjbDeployment(new EjbDeployment(ejbJar.getEnterpriseBeans()[0]));
final Properties properties = openejbJar.getEjbDeployment().iterator().next().getProperties();
properties.setProperty("cxf.jaxrs.providers", ExampleExceptionMapper.class.getName());
final EjbModule module = new EjbModule(ejbJar);
module.setOpenejbJar(openejbJar);
return module;
}
#Test
public void testThrowException() {
try {
assertEquals("Exception!", IO.slurp(new URL("http://localhost:4204/ExampleRestTest/example/throw/")));
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
}
Error Stacktrace:
org.apache.cxf.interceptor.Fault: example.ExampleException: exception: exception while invoking public java.lang.String example.ExampleRest.throwException() throws example.ExampleException with params [].
at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:166)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:140)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:167)
at org.apache.openejb.server.cxf.rs.OpenEJBEJBInvoker.invoke(OpenEJBEJBInvoker.java:47)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:94)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:94)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:236)
at org.apache.openejb.server.cxf.rs.CxfRsHttpListener.onMessage(CxfRsHttpListener.java:79)
at org.apache.openejb.server.httpd.OpenEJBHttpRegistry$ClassLoaderHttpListener.onMessage(OpenEJBHttpRegistry.java:99)
at org.apache.openejb.server.httpd.HttpListenerRegistry.onMessage(HttpListenerRegistry.java:69)
at org.apache.openejb.server.httpd.OpenEJBHttpServer.process(OpenEJBHttpServer.java:246)
at org.apache.openejb.server.httpd.OpenEJBHttpServer.processRequest(OpenEJBHttpServer.java:188)
at org.apache.openejb.server.httpd.OpenEJBHttpServer.service(OpenEJBHttpServer.java:103)
at org.apache.openejb.server.httpd.HttpEjbServer.service(HttpEjbServer.java:63)
at org.apache.openejb.server.ServerServiceFilter.service(ServerServiceFilter.java:64)
at org.apache.openejb.server.ServerServiceFilter.service(ServerServiceFilter.java:64)
at org.apache.openejb.server.ServiceStats.service(ServiceStats.java:54)
at org.apache.openejb.server.ServerServiceFilter.service(ServerServiceFilter.java:64)
at org.apache.openejb.server.ServiceLogger.service(ServiceLogger.java:92)
at org.apache.openejb.server.ServerServiceFilter.service(ServerServiceFilter.java:64)
at org.apache.openejb.server.ServicePool.access$201(ServicePool.java:35)
at org.apache.openejb.server.ServicePool$3.run(ServicePool.java:174)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)

that's fixed on trunk (https://issues.apache.org/jira/browse/TOMEE-918)
you can workaround it using ExceptionMapper and ex.getCause()

This is soo weak.
Here is a workaround:
import org.apache.openejb.ApplicationException;
/**
* #FIXME hack for https://issues.apache.org/jira/browse/TOMEE-918
*/
#Provider
public class MyExceptionMapper implements ExceptionMapper<ApplicationException> {
#Override
public Response toResponse(ApplicationException exception) {
final Status status;
final Throwable cause = exception.getCause();
if (cause instanceof javax.ejb.EJBAccessException)
status = Status.FORBIDDEN;
else if (cause instanceof MyException)
status = Status.BAD_REQUEST;
else
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(cause.getMessage()).build();
}
}

Related

Custom exception Class is not working while using EXCEPTION.class

I have a custom exception class as shown below;
public class DataSendingError extends Exception {
private static final long serialVersionUID = 1L;
public DataSendingError() {
super();
}
public DataSendingError(String errors) {
super(errors);
}
}
PFB the exception handler class:
#ExceptionHandler(DataSendingError.class)
public ResponseEntity<ErrorMessage> DataSendingErrorCase(DataSendingError ex) {
System.out.println("inside datasend");
ErrorMessage error = new ErrorMessage();
error.setErrorCode(HttpStatus.NOT_FOUND.value());
error.setMessage(ex.getMessage());
return new ResponseEntity<>(error,HttpStatus.NOT_FOUND);
}
#ExceptionHandler(Exception.class)
public ResponseEntity<ErrorMessage> exceptionHandler2(Exception ex) {
System.out.println("inside common");
ErrorMessage error = new ErrorMessage();
error.setErrorCode(HttpStatus.NOT_FOUND.value());
System.out.println("mesage"+ex.getMessage());
error.setMessage(ex.getMessage());
return new ResponseEntity<>(error,HttpStatus.NOT_FOUND);
}
But when I throw a datasending exception, the control is not going inside custom exception but it is going to Exception.class. and e.getmesaage is coming as null.I am throwing the message as shown below:
throw new DataSendingError("Error in processing the request either service is down or invalid input
Is I am doing anything wrong here. Please help me out on this.
Assuming all your exception handlers are in a separate class, is it annotated with #RestControllerAdvice?

Using Vert.x handle errors thrown in request middleware

Say I have some middleware and an error is raised:
public class JWTHandler implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) {
throw new Error("How can I capture this error and send a response.")
ctx.next();
}
}
How can I capture it using some error-handling middleware? Here is a global error handler but it can't reference any request/response pair.
vertx.createHttpServer()
.exceptionHandler(ctx -> {
// I cannot access the request that may have caused the error here
log.error("In the exception handler.");
log.error(ctx.getCause());
})
the only thing I can guess, is something like this:
public class ErrorHandler implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) {
try{
ctx.next();
}
catch(Exception e){
ctx.response().end("We messed up.");
}
}
}
but I doubt that idea is right? What's the right way to do this?
perhaps one or both of these is sufficient?
router.route().failureHandler(ctx -> {
ctx.response().end("We failed here!");
});
router.route().last().handler(ctx -> {
ctx.response()
.setStatusCode(404)
.end("404 - route/resource could not be found.");
});
I think, the correct approach would be to use the ctx.fail(), when throwing an exception
public class JWTHandler implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) {
ctx.fail(new Error("How can I capture this error and send a response.");
}
}
And then you can add a failerHandler and access to the Exception with ctx.failure()
router.route().failureHandler(ctx -> {
ctx.response().end(
ctx.failure().getMessage()
);
});
EDIT:
the failureHandler also catches exceptions that are thrown like you did:
public class JWTHandler implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) {
throw new Error("How can I capture this error and send a response.")
ctx.next();
}
}

Custom Exception Dispatcher in Spring Boot Application for response logic

I have a Spring Boot application that has the following approximate structure:
project
Api
ApiImpl
Application
Api is an interface that looks like this:
public interface Api {
public String methodOne(...) throws ExceptionOne, ExceptionTwo, ExceptionThree;
...
public int methodN(...) throws ExceptionOne, ExceptionThree, ExceptionFour;
}
ApiImpls is the request controller (in reality there is a second layer, but this should suffice for this example). There, I do something like the following right now:
#Controller
public class ApiImpl {
public String methodOne(...) {
try {
// do stuff that can yield an exception
}
catch(ExceptionOne e) {
// set proper response code and return values
}
catch(ExceptionTwo e) {
// set proper response code and return values
}
catch(ExceptionThree e) {
// set proper response code and return values
}
}
}
Basically, this behaviour yields a lot of repetition (might as well name my exceptions D, R, and Y...), but is otherwise very suited to handling the internal application logic.
My question is: How can I implement a custom Exception Dispatcher that would handle this in Java? Ideally, I would want something like this answer here, but unfortunately simply throwing the current exception like in that C++ code is not possible in Java, as far as I know. For brevity, what I would like to accomplish is something like the following:
#Controller
public class ApiImpl {
public String methodOne(...) {
try {
// do stuff that can yield an exception
}
catch(ExceptionOne e) {
handle()
}
}
private void handle() { // maybe Throwable or Exception subclass as parameter
// handle the correct exception type, set correct response code, etc.
}
}
Are there any good approaches to doing this so as to minimize code repetition?
Here is a preliminary attempt I tried to get this working:
public class Thrower {
public Thrower(int e) throws ExceptionOne, ExceptionTwo, ExceptionThree {
if(e == 0) {
throw new ExceptionOne();
}
if(e == 1) {
throw new ExceptionTwo();
}
if(e == 2) {
throw new ExceptionThree();
}
}
}
class ExceptionOne extends Exception {}
class ExceptionTwo extends Exception {}
class ExceptionThree extends Exception {}
public class ExceptionHandler {
private void handle(Exception ex) throws Exception {
try {
throw ex;
}
catch(ExceptionOne e) {
e.printStackTrace();
System.out.println("Exception one");
}
catch(ExceptionTwo e) {
e.printStackTrace();
System.out.println("Exception two");
}
catch(ExceptionThree e) {
e.printStackTrace();
System.out.println("Exception three");
}
}
public void causesException(int which) throws Throwable {
try {
Thrower t = new Thrower(which);
}
catch(Exception e) {
handle(e);
}
}
public static void main(String[] args) throws Throwable {
ExceptionHandler eh = new ExceptionHandler();
eh.causesException(0);
eh.causesException(1);
eh.causesException(2);
}
}
This works as expected, and I can handle the different exception types as needed (shown here using a constructor, but the principle would be the same). However, this feels extremely clunky.
If you are looking for globally handling all Controller Layer exceptions (in Spring MVC architecture), you can do that at one place for all controllers (option1 below) by using #ExceptionHandler methods which is a ControllerAdvice from Spring.
Option(1): Configure Exceptions in Separate Class
#ControllerAdvice
class MyProjectExceptionHandler {
#ExceptionHandler(value = ExceptionOne.class)
public R exceptionOne(ExceptionOne exe) {
//set proper response code and return values
}
#ExceptionHandler(value = ExceptionTwo.class)
public R exceptionTwo(ExceptionTwo exe) {
//set proper response code and return values
}
}
Option(2): Configure Exceptions in Controller Class itself
If you are looking for handling the exceptions within the Controller class itself, then you can do that as below:
#Controller
public class ApiImpl {
public String methodOne(...) {
}
#ExceptionHandler(ExceptionOne.class)
public R exceptionTwo(ExceptionOne exe) {
//set proper response code and return values
}
//other exceptions
}
You can look more on this at here

Trying to exclude an exception using #Retryable - causes ExhaustedRetryException to be thrown

I'm trying to use #Retryable on a method that calls the REST template. If an error is returned due to a communication error, I want to retry otherwise I want to just thrown an exception on the call.
When the ApiException occurs, instead of it being thrown and ignored by #Retryable, I get an ExhaustedRetryException and a complaint about not finding enough 'recoverables', i.e, #Recover methods.
I thought I'd see if just having the recoverable method present might make it happy and still perform as hoped for. Not so much. Instead of throwing the exception, it called the recoverable method.
#Retryable(exclude = ApiException include = ConnectionException, maxAttempts = 5, backoff = #Backoff(multiplier = 2.5d, maxDelay = 1000000L, delay = 150000L))
Object call(String domainUri, ParameterizedTypeReference type, Optional<?> domain = Optional.empty(), HttpMethod httpMethod = HttpMethod.POST) throws RestClientException {
RequestEntity request = apiRequestFactory.createRequest(domainUri, domain, httpMethod)
log.info "************************** Request Entity **************************"
log.info "${request.toString()}"
ResponseEntity response
try {
response = restTemplate.exchange(request, type)
log.info "************************** Response Entity **************************"
log.info "${response.toString()}"
} catch (HttpStatusCodeException | HttpMessageNotWritableException httpException) {
String errorMessage
String exceptionClass = httpException.class.name.concat("-")
if(httpException instanceof HttpStatusCodeException) {
log.info "************************** API Error **************************"
log.error("API responded with errors: ${httpException.responseBodyAsString}")
ApiError apiError = buildErrorResponse(httpException.responseBodyAsString)
errorMessage = extractErrorMessage(apiError)
if(isHttpCommunicationError(httpException.getStatusCode().value())) {
throw new ConnectionException(exceptionClass.concat(errorMessage))
}
}
errorMessage = StringUtils.isBlank(errorMessage) ? exceptionClass.concat(httpException.message) : exceptionClass.concat(errorMessage)
throw new ApiException(httpMethod, domainUri, errorMessage)
}
if (type.type == ResponseEntity) {
response
}
else response.body
}
#Recover
Object connectionException(ConnectionException connEx) {
log.error("Retry failure - communicaiton error")
throw new ConnectionException(connEx.class.name + " - " + connEx.message)
}
Any insights would be appreciated. Is it a bug or operator error?
This is using Spring Boot 1.3.6 and Spring-Retry 1.1.3.
Your include/exclude syntax looks bad - that won't even compile.
I just wrote a quick test and it works exactly as expected if you have zero #Recover methods...
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Retryable;
#SpringBootApplication
#EnableRetry
public class So38601998Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(So38601998Application.class, args);
Foo bean = context.getBean(Foo.class);
try {
bean.out("foo");
}
catch (Exception e) {
System.out.println(e);
}
try {
bean.out("bar");
}
catch (Exception e) {
System.out.println(e);
}
}
#Bean
public Foo foo() {
return new Foo();
}
public static class Foo {
#Retryable(include = IllegalArgumentException.class, exclude = IllegalStateException.class,
maxAttempts = 5)
public void out(String foo) {
System.out.println(foo);
if (foo.equals("foo")) {
throw new IllegalArgumentException();
}
else {
throw new IllegalStateException();
}
}
}
}
Result:
foo
foo
foo
foo
foo
java.lang.IllegalArgumentException
bar
java.lang.IllegalStateException
If you just add
#Recover
public void connectionException(IllegalArgumentException e) {
System.out.println("Retry failure");
}
You get
foo
foo
foo
foo
foo
Retry failure
bar
org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is java.lang.IllegalStateException
So you need a catch-all #Recover method...
#Recover
public void connectionException(Exception e) throws Exception {
System.out.println("Retry failure");
throw e;
}
Result:
foo
foo
foo
foo
foo
Retry failure
bar
Retry failure
java.lang.IllegalStateException

How to catch exception in Join point which was thrown from #Around

Following up with this comment of my previous question. I'm trying to throw an exception from the #Around advice, and catch it within the callee class and/or method. But I'm getting this error:
Stacktraces
java.lang.Exception: User not authorized
com.company.aspect.AuthorizeUserAspect.isAuthorized(AuthorizeUserAspect.java:77)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:616)
...
The Aspect code is:
#Aspect
public class AuthorizeUserAspect {
#AuthoWired
private UserService service;
#Pointcut("#annotation(module)")
public void authorizeBeforeExecution(AuthorizeUser module) {}
#Around(value = "authorizeBeforeExecution(module)", argNames="module")
public Object isAuthorized(ProceddingJoinPoint jp, AuthorizeUser module) throws Throwable {
// Check if the user has permission or not
service.checkUser();
if ( /* User has NOT permission */ ) {
throw new MyCustomException("User not authorized"); // => this is line 77
}
return jp.proceed();
}
}
and the Struts's based UI action code is:
#Component
public class DashboardAction extends ActionSupport {
#Override
#AuthorizeUser
public String execute() {
...
}
private void showAccessDenied() {
...
}
}
The question is How or Where I can catch that exception to execute showAccessDenied()?
To handle uncaught exceptions like MyCustomException you need to define a global exception handler in Struts 2. Please check this guide: http://struts.apache.org/2.3.4.1/docs/exception-handling.html
For user interface I'd recommend writing a short code for catching any uncaught exceptions.
class EventQueueProxy extends EventQueue {
#Override
protected void dispatchEvent(AWTEvent newEvent) {
try {
super.dispatchEvent(newEvent);
} catch (Throwable t) {
String message = t.getMessage();
if (message == null || message.length() == 0) {
message = "Fatal: " + t.getClass();
}
JOptionPane.showMessageDialog(null, message, "Unhandled Exception Caught!", JOptionPane.ERROR_MESSAGE);
}
}
}
And then in the ui class:
public static void main(String args[]) {
EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue();
queue.push(new EventQueueProxy());
//your code goes here...
}
Note, it will show the dialog window with an error information each time uncaught exception appears. This is just the suggestion for your ui, for the particular case of your ploblem, do use try for firing method(s) that authorizes a user and catch for firing method(s) that should be executed if the user is not authorized. in such case authorization method should throw an exception if an authorization fails. Then the error will not be printed but the particular method will be fired instead.
That's what I'd add to your code:
#Component
public class DashboardAction extends ActionSupport {
#Override
try {
#AuthorizeUser
public String execute() {
...
}
} catch (Exception e) {
private void showAccessDenied() {
...
}
}
}

Categories

Resources