I have a question about how to handle EJBExceptions in some special cases.
General situation
In our application an EJB (3.0) DataAccessObjects(DAO) are responsible for all database access, these are used in other parts of the application.
Exceptions in the database layer are expected, for instance because of Optimistic Locking or Database constraint violations. The exceptions often thrown outside of the DOA class, because they occur on commit of the automatic JTA transaction. The calling class then receives this exception wrapped in an EJBException.
In most cases ignoring or logging and rethrowing the EJBException is best, as our JMS will trigger automatic retries for MessageDrivenBeans. In two cases, we don't want the exception to be propaged, as they have unwanted side effects.
Handling in JSF
In our JSF website we use the following pattern to display user friendly messages:
#ManagedBean
#ViewScoped
public class MyDataController {
#EJB
private MyDataDao myDataDao ;
public void addData(){
FacesMessage msg;
try {
Data data = new Data();
// Data gets filled
myDataDao.addData(data);
msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Succes",
data.getName());
}
catch (EJBException e) {
LOGGER.warn("Failed to add data"newCompanyName, e);
if (ExceptionUtils.getRootCause(e) instanceof SQLIntegrityConstraintViolationException) {
msg = new FacesMessage(FacesMessage.SEVERITY_FATAL, "Failed",
data.getName());
}
else {
msg = new FacesMessage(FacesMessage.SEVERITY_FATAL,
"Failed to add data for unknown reason", data.getName());
}
}
}
}
Handling in Schedules tasks
In a related case, we call the database from a timed task (created using #Schedule). However this task is destroyed when (two consecutive?) exceptions occur while running it (at least in Weblogic). For us it is very important that this task keeps running even if exceptions during handling occur.
We have achieved this by catching and logging all EJBExceptions, as explained in this answer and in this answer. (Actually in our case we decided to catch all exceptions).
Problem
The above solutions mostly work as intended. However, we recently found that Errors are wrapped in an EJBException as well. For instance an OutOfMemoryError. In this case it caused the error to be swallowed, disabling the normal mechanism in Weblogic that would restart the application in case of an OutOfMemoryError.
Effectively this has downgraded Errors to Exceptions.
Question
The only solution I have is to check the recursively check the exception and its causes for instances of type Error, and if that is the case, rethrow the EJBException.
What is the correct way to handle the EJB exceptions in these situations?
Related
I am new to Axon framework and am trying to implement an application using CQRS with state-stored aggregates. The application relies on a database constraint (using H2 for now) to enforce uniqueness on a name attribute. I would like to catch this exception and rethrow it as a user-friendly domain exception.
Per the Axon documentation:
Exception Handling says "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class"
Message Intercepting documentation says "A function annotated with #ExceptionHandler will be regarded as a handler interceptor which will only be invoked for exceptional results. Using annotated functions to this end for example allow you to throw a more domain specific exception as a result of a thrown database/service exception."
But I cannot get this to work. I have tried adding exception handlers as follows:
#ExceptionHandler
public void handle(ConstraintViolationException ex) throws Exception {
if (ex.getMessage().contains("UNQ_COMPANY_ID") || ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new DomainException("Plan name and company id must be unique");
}
throw ex;
}
but this method is not called. I have tried putting the exception handler method on the aggregate and on a separate command handler class, tried adding resultType=ConstraintViolationException.class, and tried catching other types of exceptions including Exception, RuntimeException, AxonServerRemoteCommandHandlingException, etc. but this method is never called.
I can see the error in the log output:
org.axonframework.axonserver.connector.command.AxonServerRemoteCommandHandlingException: An exception was thrown by the remote message handling component: org.hibernate.exception.ConstraintViolationException: could not execute statement
Is it possible to catch database exceptions in state-stored aggregates? If it is, can someone point me towards what I am doing wrong?
The statement "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class" makes me wonder whether I need to create a custom repository class (rather than using the default GenericJpaRepository) but that seems like a lot more work than should be necessary.
Thank you!
Update: I was able to roughly accomplish what I want by adding a UnitOfWork parameter to the #CommandHandler method and using it to registering a rollback callback on it as follows:
uow.onRollback(unit -> {
DefaultUnitOfWork duow = (DefaultUnitOfWork) unit;
Throwable ex = duow.getExecutionResult().getExceptionResult();
while (ex != null) {
if (ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new RuntimeException("Plan name must be unique");
}
ex = ex.getCause();
}
});
But this seems kind of verbose, as well as limiting me to throwing unchecked exceptions only. This also doesn't feel like the right way to do this though because I assume the purpose of the #ExceptionHandler annotation is to eliminate need for code like the above.
This is doable of course.
Actually, the best pointer I could give you if the code-samples repo where you can see a sample about distributed exceptions.
In general, as you could see in your shared log, the 'original' exception is wrapped into an AxonServerRemoteCommandHandlingException meaning you will have to handle that. Doing that, you can pretty much add anything to the details field of this class, adding the indication you had a ConstraintViolationException for example (or an ERROR_CODE, like HTTP protocol does) and you are fine to unwrap it on the other side.
What might be the "gotcha" you require, is to know that an #ExceptionHandler annotated method should reside in the object handling the message. So if you want to react to a failing command handling operation (which would be the case in your sample), you will need to place the exception handler in the Aggregate, next to the Command Handler.
That fact you get an AxonServerRemoteCommandHandlingException to me suggests the exception is caught on the command dispatching end. So, prior to dispatching a command on the CommandGateway/CommandBus.
However, whether this is the problem at hand, isn't clear to me right now, since the sample only shows the exception handler and not where it resides. Please share whether my assumption on the placement of the exception handler is correct. If not, we'll dive into this deeper to get to the cause.
I have an Scheduler in spring boot that fulfils a specific business task every X minutes. It works fine until it suddenly stops and does not engage anymore. There is no exception in the logs or any other logs. I need to restart the program for the scheduler to work again.
Sometimes the task of the scheduler goes wrong, and I throw an exception. To be able to handle those exceptions specifically, I wrote a custom ErrorHandler in Spring for the scheduler that resolves a seperate task for logging purposes. It is linked correctly to the scheduler and processes the task.
This issue can come up when an unhandled exception gets thrown inside of an ErrorHandler. I am not sure about the specifics, however a Runtime Exception thrown by an ErrorHandler (or a method inside of it) that gets propagated outside of it basically kills the scheduled thread for that task. Furthermore NOTHING gets written to the logs (no Exception message, nada).
The "easiest" way to resolve this is by wrapping the entirety of the method in a try/catch block catching Exception - although depending on why you have that Error Handler that might be a bad idea. This does not solve the underlying issue at hand, but it keeps the thread alive and allows you to log the issue.
Example:
public class MyErrorHandler implements ErrorHandler {
#Override
public void handleError(Throwable t) {
try {
//handle intended exception (ex. write to database or logs)
} catch (Exception e) {
//handle exception that was thrown while trying to handle the intended exception.
}
}
I have an EJB with container-managed transactions. I have a method in it (used as a REST call) that calls something from another EJB I've injected using JNDI (not sure if that matters) and it returns an Exception that extends RuntimeException (so it causes a transaction rollback), which translates as a 404 response through an ExceptionMapper.
I want that exception to be what returns from my REST call and I don't mind it being in the logs at all, but I do not want my log to be spammed with the EJBExceptionRolledBackException stacktrace that it causes (the stacktrace gets printed three times for some reason). I believe two out of these three stacktraces get logged before the server even gets back to the final method for the REST call.
Either way, as long as I figure out how to suppress one of these logging actions I'll figure out a way to stop all three. Does anyone have an idea how to suppress this kind of logging?
As it said in the EJB Specification every SystemException must be logged by the container implementation. You can try to catch it or mark as ApplicationException but if you mark it it won't rollback the transaction. I suggest this:
#Stateless
#TransactionManagement(TransactionManagementType.BEAN)
public class MyBean {
#Resource
private UserTransaction tx;
public void myMethod() throws MyApplicationException {
try {
tx.begin();
// call needed methods
tx.commit();
} catch(Exception e) {
// silently rollback;
// exceptions from `UserTransaction` omitted for readability
tx.rollback();
throw new MyApplicationException(e);
}
}
}
Now in your client code of that EJB you can react to MyApplicationException and return whatever you want or log it or don't. By using container managed transactions will ensure that errors are logged by specification (and they are wrapped to another exceptions as bean instances are being destroyed). Also you can mark transaction as rollback-only. Be sure to use this carefully. If you don't want logs from container you need to control all of your flow by yourself.
I am developing a restful webservices using java. I am handling all runtime and other possible exception scenarios to send meaningful response to client.
When something like out of memory occurs, how do i make sure client gets meaningful response from the server?
Am using CXF and ExceptionMapper.
In Spring, you can catch your exceptions and map them to meaningful HTTP status codes. Following code might work for you (maps YourException to HTTP 500):
#ControllerAdvice
public class ExceptionProcessor {
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
#ExceptionHandler({YourException.class})
public void serverError(HttpServletRequest req, Exception exception) {
// ...
// Print exception to server log
exception.printStackTrace();
}
}
It's not an exception; it's an error: java.lang.OutOfMemoryError
You can catch it as it descends from Throwable:
try {
// create lots of objects here and stash them somewhere
} catch (OutOfMemoryError E) {
// release some (all) of the above objects
}
However, unless you're doing some rather specific stuff (allocating tons of things within a specific code section, for example) you likely won't be able to catch it as you won't know where it's going to be thrown from.
If the root cause of your problem is a memory leak, then the chances are that catching and recovering from the OOM will not reclaim the leaked memory. You application will keep going for a bit then OOM again, and again, and again at ever reducing intervals.
There is probably at least one good time to catch an OutOfMemoryError, when you are specifically allocating something that might be way too big:
I'm using HandlerExceptionResolver for this:
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
#Override
#ExceptionHandler(value = Exception.class)
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
Your error processing goes here
}
}
So every exception, goes in resolveException, and I write appropriate message (In my case JSON) to the response.
There is also a good article http://www.journaldev.com/2651/spring-mvc-exception-handling-exceptionhandler-controlleradvice-handlerexceptionresolver-json-response-example
The problem with OutOfMemoryError is that it may happen in any thread, including threads that do not run your REST services code. In a server context, it is considered a bad practice to catch any Error. You should let it bubble up the call stack to be handled by the server code.
Instead of catching it, it would be better to investigate why you run out of memory and fix the cause. It could be that your server simply doesn't have enough memory allocated, or that you have a memory leak somewhere. You need to analyze the problem, for instance by analyzing the resulting heap dump(s), and ensure that it doesn't happen anymore.
In a managed environemnt like a Java EE server, it is dangerous and generally fallacious to assume you can recover from OutOfMemeoryError by catching it. Most often, you can't even catch it because it happens in a thread you don't control.
I am writing a web application using Spring 3 framework. Consider a situation where I have N number of controllers. Each controller delegates the request to exposed services and gets the response and return to users.
I would like to know if there is a better to way catch unexpected runtime exceptions thrown out of the controller code. I do not want to write something like the following for each of my controller methods. Or is it the only way?
try {
//call the service
} catch(ServiceException serviceEx) {
//do process for know exception
} catch(Exception ex) {
//return generic error message.
}
I know that we can use Spring Exception resolver. But I do not want to show different error page when unexpected error happens. I want to show some generic error message on UI as part of my widget?
Edit:
I also don't want my users to see the exception stacktrace when trying to perform some operations.
Sundar
I think catching RuntimeExceptions is bad practice. Originally RuntimeExceptions where thought as inicators to programming errors (e.g. NullPointerException to indicate that a null check is missing). Whereas checked exceptions where meant to indicate errors that the program can recover from (e.g. FileNotFoundException).
The problem today is that many frameworks use RuntimeExceptions where checked exceptions should be used. Therefore it is difficult to differentiate between cases where a program can handle the exception and where a programming error (bug) is encountered.
This is my personal view of this things for enterprise development. I know that most people mandate for dropping checked exceptions and handle everything as unchecked exception (as in Scala).
In my opinion you should only catch exceptions in your code from which you can recover. All other exceptions (checked or unchecked) should be caught by one über exceptionhandler which will log the exception and show the user some generic error page (possibly with an id that you can use to find what the exception was).
For example, in struts2 you would that this like so:
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="unrecoverableException"/>
</global-exception-mappings>
I never use spring mvc but this article seems to give you the options for an über exceptionhandler:
http://doanduyhai.wordpress.com/2012/05/06/spring-mvc-part-v-exception-handling/
You can catch runtime unexpected exceptions using this approach.
try {
...
} catch ( Exception e ) {
throw new RuntimeException("msg",e);
}
I think RuntimeException is designed for situations like breach of contract or some unrecoverable fault. Most of the time, you should just let the container or some outer infrastructure to handle it for you. Or you have to write a lot of redundant code to deal with them and it's kind of against the design philosophy of Spring.
In your case, may be you can leverage some filter or interceptor to catch those unexpected RuntimeException if you really need to transfer them to some other generic messages.