EJBs are a part of enterprise applications which are normally based on distributed environments. So, apart from the normal exceptions that can occur, there can be exceptions like communication failure, security permissions, server down, etc.
EJB container considers exceptions in two ways −
Application Exception − If business rule is violated or exception occurs while executing the business logic.
System Exception − Any exception, which is not caused by business logic or business code. RuntimeException, RemoteException are SystemException. For example, error during EJB lookup. RuntimeException, RemoteException are SystemException.
When Application Exception occurs, EJB container intercepts the exception, but returns the same to the client as it is. It does not roll back the transaction unless it is specified in the code by EJBContext.setRollBackOnly() method. EJB Container does not wrap the exception in case of Application Exception.
When System Exception occurs, EJB container intercepts the exception, rollbacks the transaction and start the clean up tasks. It wraps the exception into RemoteException and throws it to the client.
Application exceptions are generally thrown in Session EJB methods as these are the methods responsible to execute business logic. Application exception should be declared in throws clause of business method and should be thrown in case business logic fails.
@Stateless public class LibraryPersistentBean implements LibraryPersistentBeanRemote { ... public List<Book> getBooks() throws NoBookAvailableException { List<Book> books = entityManager.createQuery("From Books").getResultList(); if(books.size == 0) throw NoBookAvailableException ("No Book available in library."); return books; } ... }
System exception can occur at any time like naming lookup fails, sql error occurs while fetching data. In such a case, such exception should be wrapped under EJBException and thrown back to the client.
@Stateless public class LibraryPersistentBean implements LibraryPersistentBeanRemote { ... public List<Book> getBooks() { try { List<Book> books = entityManager.createQuery("From Books").getResultList(); } catch (CreateException ce) { throw (EJBException) new EJBException(ce).initCause(ce); } catch (SqlException se) { throw (EJBException) new EJBException(se).initCause(se); } return books; } ... }
At client side, handle the EJBException.
public class EJBTester { private void testEntityEjb() { ... try{ LibraryPersistentBeanRemote libraryBean = LibraryPersistentBeanRemote)ctx.lookup("LibraryPersistentBean/remote"); List<Book> booksList = libraryBean.getBooks(); } catch(EJBException e) { Exception ne = (Exception) e.getCause(); if(ne.getClass().getName().equals("SqlException")) { System.out.println("Database error: "+ e.getMessage()); } } ... } }