Just a bit of background on EJB3.1 exceptions before bringing up my question -
Application exceptions comprise of
User defined checked or unchecked exceptions which have
#ApplicationException annotation
All checked exceptions
java.lang.Exception & it's subclass exceptions
except java.rmi.RemoteException & it's subclass exceptions
System exceptions comprise of
java.rmi.RemoteException and it's subclass exceptions
All unchecked exceptions
java.lang.RuntimeException and it's subclass exceptions
java.lang.Error and it's subclass exceptions
Below is a statement I have read in this book
In EJB System exceptions are not excepted by the client, when encountered such exceptions are not passed to the client as is but are wrapaped in a javax.ejb.EJBException.
My questions -
Are all application exceptions described above supposed to be thrown directly by EJB to client?
If System Exceptions are wrapped inside javax.ejb.EJBException before throwing to the client, then is javax.ejb.EJBException considered as System Exception?
IndoKnight, what a perfect wrap up you gave of how Exception semantics within the Java EE framework.. work.
Here's the two only lines a "bean provider", that is you and me, need to know about exceptions in Java EE:
Your bean is totally free to recover from any type of exception or error as you see fit, with respect to other constraints the bean might be under. If you recovered from an exception, then congratulations - there's no problem anymore =)
A relevant constraint could for example be that "enterprise beans that use container-managed transaction demarcation must not use any transaction-management methods that interfere with the container's transaction demarcation boundaries" to quote the Java EE 7 tutorial page 48-2 (would you like to programmatically set the rollback of a container managed transaction, use EJBContext.setRollbackOnly()).
You are also discouraged, as with any type of Java application, to handle Throwable or Error thrown from a really low level. RuntimeException is theoretically counted in this category, as it so famously signals a "developer error" that's like "totally totally unexpected" - yet we all know it isn't.
Basically, an unexpected exception (runtime exceptions + other shit that we assume originate from someone else) is assumed to be unhandleable by your code and should be handled by the server instead. The server is required to handle the "unhandleable" exception (see the EJB 3.2 specification, page 204) by printing something about it in the log (I'll get into the details a bit later!).
More specifically..
You asked (and here is what I believe or hold true):
Are all application exceptions described above supposed to be thrown
directly by EJB to client?
Yes. And the transaction (if one is active) shall not be rolled back unless you explicitly state that it should by using the rollback attribute of the ApplicationException. Java code throwing exceptions is a very natural thing. Java EE has no intention of demolishing this programming model. So go ahead, throw checked exceptions however you like, forcing the clients to try-catch those or mark runtime exceptions as being application exceptions and throw those too. Happy throwing!
If System Exceptions are wrapped inside javax.ejb.EJBException before
throwing to the client, then is javax.ejb.EJBException considered as
System Exception?
Yes, but not for the reason you provide. To be clear, there is no type called SystemException. It is just fancy wording to describe those kind of exceptions that the majority of beans out there didn't figure could happen, and most likely, they originate from the EJB container. Your code should definitely not throw an EJBException. Doing so would probably only thwart the mind of the Server. Nor can you annotate the exception as being #ApplicationException since you don't own the code, it is provided by the Java EE API. You could extend EJBException, but it wouldn't make any sense to disguise your code as being part of the server's codebase. Most importantly, since EJBException extends RuntimeException, I think it is safe to categorize the EJBException as a "system-level exception".
Watch out for the Devil
Some remote clients will receive the RemoteException instead of the EJBException.
Interceptors that you might not even be aware of in a huge enterprise project, could swallow exceptions thrown from your method making an active transaction commit even though you never had plans to let him do that.
I bet you think that a suppressed exception is always retrievable using Throwable.getCause(). Do note that the EJB 3.2 specification does not say that the container has to or should spare a reference to the suppressed cause. In fact, the only thing the container has to do is log the exception. Then, if the bean is not a singleton, the bean instance must be discarded and never used again. Also, if the bean is a message-driven bean, only then is the original exception required to be "wrapped". How-to "wrap" the exception is not specified. Super portable cool code should probably have a look at both the Throwable.getCause() method and Throwable.getSuppressed() too. Don't blindly expect in your handling code to always find the original exception.
Asynchronous methods (public session bean methods annotated #Asynchronous) that return void cannot propagate an exception to his client. Thus they must not declare or throw application exceptions (see the EJB 3.2 specification page 82). Do note that when you invoke an asynchronous method, it might be the case that the server cannot provide threading resources to service your request and if so, he is required to throw an.. EJBException (page 48)!
Yes, more or less that's how they work. For further details on EJB's behaviors check out the following blog post: Link
Also from this question:
An application exception shall be thrown when there is a
business-logic error, as opposed to a system error.
There is an important difference: application exceptions do not
automatically cause a transaction to rollback. The client has an
opportunity to recover after an application exception is thrown.
Application exceptions are sent to the client without being repackaged
as an EJBException. Therefore, you can use them to report validation
errors or business logic problems, and they will reach the client.
javax.ejb.EJBException extends RuntimeException so yes, it is a System Exception.
Common scenario associated with this: if you've got an uncaught RuntimeException in your application code it will roll-back. It's pretty useful default behavior.
Related
In what use case would a custom Error class be required?
I know there are many specialised subclasses of Error in Java API (e.g. LinkageError, ServiceConfigurationError, ThreadDeath, VirtualMachineError) but I think these are only required by the Java runtime and mostly are not required in the application code of a Java developer.
I am well aware about creating custom Exception classes and their usage scenarios, but I'm not sure about Error.
As the documentation describes:
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.
Exceptions, on the other hand, are designed to be caught. Unchecked RuntimeExceptions should be caught judiciously (because the code that raised it is indicating something unexpected happened) but the JVM itself is in no danger; if the caller believes it can recover from the RuntimeException, it's safe to do so.
Therefore if there is something in your program that no "reasonable application" would ever want to handle, an Error is appropriate. This is very, very rare however.
Look at some of the existing subclasses, like LinkageError and VirtualMachineError and it's subclasses InternalError, OutOfMemoryError, StackOverflowError, and UnknownError - these are raised when the JVM has failed and there's nothing it can do to recover, not even let the user try to handle it.
If you have an additional case where your code could fail catastrophically and you want to similarly force the application to terminate, use an Error (probably an AssertionError). The vast majority of the time, however, a RuntimeException of some sort is sufficient, as it allows a user to at least try to correct the problem while the program is running.
I am new to JBoss. As part of My Application I am using JBoss.We are also using EJB's as a part of the project also. A exception like StaleObjectStateException is raised . So , the EJB uses this exception to rollback a transaction. So, Please tell me how to stop StaleObjectStateException from being logged.Log4j is used here.
StaleObjectStateException being a runtime exception, shouldn't be caught in normal cases
But the only way for you to stop it from coming to logs, is to catch the exception in your code and eat up.
However, IMHO it should be of prime importance to figure out why you are getting this exception.
org.hibernate.StaleObjectStateException is a Hibernate exception that usually indicates that some other thread of control has updated the state of your entity bean in the database.
You must catch it before it is thrown from an EJB and deal with it somehow.
Any RuntimeException that is thrown from an EJB call automatically results in transaction rollback.
You should also read the javadoc for org.hibernate.StaleStateException to ensure that some of the other scenarios it describes do not apply to you.
I have been reading the JLS and I encountered the section 11.1.3. Asynchronous Exceptions from which I quote:
Most exceptions occur synchronously as a result of an action by the
thread in which they occur, and at a point in the program that is
specified to possibly result in such an exception. An asynchronous
exception is, by contrast, an exception that can potentially occur at
any point in the execution of a program.
And
Asynchronous exceptions occur only as a result of:
[...]
An internal error or resource limitation in the Java virtual machine that prevents it from implementing the semantics of the
Java programming language. In this case, the asynchronous exception
that is thrown is an instance of a subclass of VirtualMachineError.
Is it possible to catch such exceptions for logging purposes or notification (because I believe such thing is unrecoverable)? How can I achieve such thing?
You can catch such exceptions just like any other exception. The only problem is that they may occur at any place in your program, so catching them reliably is hard. You would basically have to wrap the run method of all threads and the main method in a try..catch block, but you can't do that for threads you don't control (like the Swing EDT, or threads for timers etc.).
Also catching any subclass of Error is usually not recommended, because the JVM may be in an unstable state, which might lead to a further failure (for example in the case of OutOfMemoryError, you might not even have enough memory to to the exception handling). However, logging would be a valid reason for catching Errors in my eyes.
My suggested solution would be to use an uncaught exception handler for this by setting it as the default exception handler. In this handler you will get all exceptions and errors, if they are not caught anywhere in the code, and you can try to log them.
There is no point of catching these exceptions (Subclasses of VirtualMachineError) as you have no indecattion in which state the pogram is at the point, the Doc saies about Virtual Machine Errors:
A Java virtual machine implementation throws an object that is an
instance of a subclass of the class VirtualMethodError when an
internal error or resource limitation prevents it from implementing
the semantics described in this chapter. This specification cannot
predict where internal errors or resource limitations may be
encountered and does not mandate precisely when they can be reported.
so assuming you get in an OutOfMemoryError or an UnknownError there isnt much you can do about it, and once your vritualmashine doesnt work properly you cant provide the user anyhelp as your program isnt working properly as well, besides you have no idea at what time, point, and reason it happends since its not a code error that was caused from your program.
Since there is no need to try/catch or specify un-checked exceptions, how are they are reported to the user?
how are they are reported to the user?
What is the best practice to handle
un-checked exceptions?
In our application, we barely use any exception at all: neither checked nor unchecked (we consider checked exceptions to be a Java idiosynchrasy unrelated to the problem domain we're dealing with, so we wrap most checked exceptions inside cleaner APIs, using state testing methods).
The way we deal with it is simple: it's a desktop application, if we catch an uncaught exception, we offer the user the possibility to send us a report. All the user has to do is click on "Report" and we get the full stack traces and other infos sent to one of our servers.
You can set up an application-wide uncaught exception handler like this:
Thread.setDefaultUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() {
public void uncaughtException( final Thread t, final Throwable e ) {
...
// Here we offer our user the possibility to 'report' the exception, YMMV
}
}
Typically there are zero exception happening in our software: we don't use checked exception for flow control (unless when we're using brain-dead APIs from the nineties, where this was common practice).
Some frameworks, like Spring, also have a pretty strong preference towards the "no checked exceptions" mentality.
So exceptions for us are really exceptionnal, hence the popup warning the user that the app crashed and offering them the possibility to send us the report.
If you are writing a container or a framework or a UI framework, then the best place to handle them is centrally, propagate them all the way to central handler and report the error to user in a usable way,
If using a UI, provide a way for user to report that exception.
Details:
We generally use a practice when using UI is that have a central exception handler.
In case of a web UI, we have on handler that shows the user that something has gone wrong in the system, The error page also has a form with hidden fields that has stack trace along with a description (optional) field asking the user to describe what she/he was doing when error occured. The for submits the error information, with stacktrace to the system (which can be a mail or simply stored in db)
In a desktop UI, could be the same, only thing that will be different is where you put your exception handling code.
Error reporting example
Error reporting example http://www.flickr.com/photos/aniketn/4785197367/
You actually can catch unchecked exceptions. It's just that they're usually things you can't solve when you do catch them - for example, NullPointerException. There's generally not a way to smoothly and gracefully resume whatever you were doing when the NullPointerException occurred.
If you don't handle them, they will propagate all the way up through your program and it will abort, dumping a stack trace of the exception.
The best practice is to deal with the ones where you can provide some better handling than the default. For example, if you call an external library function, you could wrap it in a try/catch block and if the library throws a NullPointerException you could give the user a friendly error message (a GUI "library X failed to do Y - did you specify a valid Z?") instead of a stack trace on the command line. But in the general case, the reason they're unchecked is because even if you knew about them, there'd be nothing for it but to throw up your hands.
When bubbling out of the main(...) method, the JVM prints the stack trace to System.out and exits that thread. For single-thread programs, that would also exit the program.
In general, every thread you run should have a wrapper catching Throwable so you can at least log it to your files.
I keep getting this "suggestion" from many fellow developers over and over again. In my experience I've found that EJBExceptions are well-suited for "end of the world" from the bean instance perspective (like when something is so wrong that the bean instance cannot recover by itself). If an instance can recover, I think it's better to throw an application exception.
Here is the pattern that I meet over and over again:
private SomeResource resource;
ejbCreate:
resource = allocateResource(...);
omMessage:
try {
...
} catch (JMSException e) {
throw new EJBException(e);
}
ejbRemove:
freeResource(resource);
IMHO this is a antipattern that causes resource leaks.
EDIT: Specifically, the EJB specification says that if a bean throws a runtime exception (and EJBException is a runtime exception) from the business method, then the bean is discarded without calling ejbRemove on it.
Is this a relevant example against throwing an EJBException?
What are the relevant cases when EJBException should be thrown?
The throwing of EJBException is recommended by the EJB spec (14.2.2 in the EJB 3) in the cases where the EJB cannot recover from an exception it encounters. The spec also says that the EJB can reasonably allow (unchecked) System Exceptions to propagate to the container.
I agree with your reading of the spec that in such cases life-cycle callback methods will not be invoked by the container, and hence your concern that any resource-tidy up that would normally happen in the ejbRemove() callback will not happen and so there's a danger of resource leakage.
My experience is that very many tricky problems arise because of a lack of defensive coding. "Situation X cannot occur in a well behaved system, and if it does then the whole system is broken, so I'll not code for that eventuality." Then we get some "interesting" alignment of the stars and operator errors and the "can't happen" happens several times in quick succession and unanticipated side-effects kick in leading to really difficult to diagnose problems.
Hence I would say:
Do everything you can to leave the Bean instance in a state where the next invocation of a business method might be able to work. This might mean catching exceptions and closing resources that are in error. In this case you may then chose to tell the callers, "sorry guv, that request didn't work, but maybe if you retry later ..." I do that by throwing a TransientException checked exception.
If you have no important housekeeping in ejbRemove then you can allow SystemExceptions to propogate - but I'm not sure that this is friendly. You depend upon a library and it throws a NullPointerException. Is is actually more robust to catch and rethrow TransientException?
If you do have important housekeeping, then I think you do need to catch all exceptions and at least attempt the cleanup. You may then choose to rethrow EJBException or a system exception so that the instance is destroyed, but at least you've tried to do the housekeeping.
The container can still commit the current transaction even though the EJB method has thrown an application exception. If your EJB method can throw an application exception then you should consider using EJBContext.setRollbackOnly() like this:
public void method() throws ApplicationException {
try {
...
} catch (ApplicationException e) {
_context.setRollbackOnly();
throw e;
}
}
Throwing an EJBException or a system (unchecked) exception means that the container will automatically rollback the transaction. See: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html
If your system's EJBs do not routinely trap and handle application exceptions then code that throws them can result in a partially complete operation committing its changes.
This can lead to hard-to-find bugs because the "user myth" of an EJB method with CMP is that it maps to a transaction, which is atomic. The partially complete business logic is atomically committed to the database. This is extremely confusing when it happens in practice. Joel's article on leaky abstractions: http://www.joelonsoftware.com/articles/LeakyAbstractions.html explains why.
If your system has EJBs that do not handle application exceptions correctly the logical answer is to fix them so that they do. Until the problem is fixed, your team might have a rational reason for not wanting application exceptions thrown from EJBs.
Whether or not is leaks resources depends on how those resources are administered. The discarded bean gets garbage collected giving up its reference to the resource which gets garbage collected in turn when no more references point to it. If the resource is also kept in a collection with a path to root, it will leak unless the container has a pool manager that can detect idle resources and recycle it.
I agree with you that the bean should handle any exceptions it can by itself and let the result be known to the caller. For me the anti pattern in the situation you describe is using exceptions to pass object state. Exceptions should be exceptions, not used as return values.