Question

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 -

  1. Are all application exceptions described above supposed to be thrown directly by EJB to client?
  2. If System Exceptions are wrapped inside javax.ejb.EJBException before throwing to the client, then is javax.ejb.EJBException considered as System Exception?
Was it helpful?

Solution 2

  1. 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.

  1. 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.

OTHER TIPS

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)!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top