Instead of writing more comments (superfluous superfluous), I will give some of my thoughts + one of the general solutions with which I came.
http://docs.oracle.com/javaee/6/tutorial/doc/bnbpj.html
This puts this question in a simple context. When people are not accustomed to exceptions (e.g. script / functional programmers), they write about using only RuntimeExceptions ..., which makes you pollute the external interface with unmanaged errors that occur in the user interface. (I do not think this is very convenient if you consider the program code in the long run ... maintainability)
http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html
If the client can take some alternative action to recover from the exception, make it a checked exception. If the client cannot do anything useful, make the exception unchecked. By usefulness, I mean taking measures to recover from an exception, and not just to register an exception.
(There are messages about registering templates with Exceptions, but I'm not going to go there on this, since this is moving away)
Unchecked exceptions are hard to spot, and they easily access your "close to source". (If they are not checked, they will be invisible to the client code and slip through).
I was questioned by this problem with some legacy code throwing a lot of unchecked exceptions that now lead to a crash in the user interface. (due to unreliable services)
Everyone probably has their own opinion on what to do, but I'm trying to create a common template for detecting errors (excluded exceptions) close to the user interface and presenting them as tooltips (JSF by the way) instead of guiding the user to the page "error.xhtml" (entered in web.xml).
// For the above scenario, I came up with this solution.
It seems to work very well.
- Create annotation of interceptor and interceptor binding.
- Annotate classes or methods that you want their bubbling EJBExceptions to be sanitized.
- Do not intercept everything, otherwise you get unnecessary processing / overhead. Just use it where you really need it, at the BackingBean / ManagedBean level.
Interceptor Binding Annotations
@Inherited @InterceptorBinding @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface InterceptEJBExceptions {}
Interceptor
@Interceptor @InterceptEJBExceptions public class EjbExceptionInterceptor { @AroundInvoke public Object interceptBubblingExceptions(final InvocationContext context) throws Exception { try { return context.proceed(); } catch (MySpecificEJBException msejbe) { Object[] args = { msejbe.getErrorCode(), msejbe.getMethodSignature(), msejbe.getParameters()};
beans.xml
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> <interceptors> <class>xxx.xxx.xxx.exception.interceptor.EjbExceptionInterceptor</class> </interceptors> </beans>
Using java classes
@RequestScoped // Class must be in EE context // @InterceptEJBExceptions // Have the annotation at class level to intercept all method calls in this class public class MyBB { @InterceptEJBExceptions // Only intercept when this method gets called public String myEjbExceptionThrowingActionListener(Object obj) { // Some code that may throw an EJBException } }
MySpecificEJBException . There will be an exception class extending an EJBException . Build the class the way you like to transfer useful information for later logging and to display clean error messages on the screen instead of throwing an exception on the screen with or without the error page defined in web.xml (which you should also have as backup copy).
Remember to include the original exception in the class!
Create more custom Exceptions that extend the EJBException as needed, and throw them as you wish (they are not marked as RuntimeExceptions). Then simply add the catch block to the interceptor and make a message about registration and / or error displayed for this case.
Generally:
Use proven Exceptions where you can respond to errors.
In Java 7, you can use the following syntax to group exceptions that can be handled similarly.
try {...} catch (SomeException | OtherException e) {...}
If you have many test Exceptions, you can / should possibly group them into categories (extend an even more general exception). You can then catch groupings based on this exception (in addition to / instead of catch-clauses grouping).
- Turn these exceptions into EJB / RuntimeExceptions that pollute you with code (if you really have nothing to do). They should then be captured and handled by a common EjbExceptionInterceptor. The interceptor will catch an exception => show an error message / pop-up message, but the user will remain on one page without losing the data on which he / she worked.
- Avoid throwing the usual RuntimeException. They signal an error in the code (my opinion), and the aforementioned interceptor will allow them to fail on the error page. It will also disconnect the user from the page on which he is currently located.
- These errors should always be fixed with high priority (for example, NullPointerException will do this).
- Also: do not throw exceptions about almost everything, it will be poor programming. If your code can do something with an error before hand (for example, use overloaded methods or default values ββto prevent the use of null parameters), then do this, do not miss the problem to the client (call method). This is just lazy programming + using RuntimeExceptions to hide these errors is simply irresponsible! Trial Tests!
I could not find a real solution for error handling (like a template), but there is a lot of debate about what is right and what is wrong. We have 2 types of Throwables, so why don't they use them as constructively?
Instead of continuing this discussion, I hope it will be a real solution and a trick.
I would be grateful for all constructive comments and suggestions for improvement.