How to hide RuntimeException details from EJB client? - java

I have a JEE5 application that exposes services using (local) session beans.
When an internal fault occurs during service execution, a RuntimeException is thrown and encapsulated by JBoss(5.0.1) in a javax.ejb.EJBTransactionRolledbackException.
The problem is that client applications receiving this EJBTransactionRolledbackException can access detailled informations about the cause runtime exception, exposing internal architecture of my application. And I don't want that.
Instead, I would like JBoss to always encapsulate RuntimeException thrown by exposed session beans into a single (and simple) TechnicalException (with no cause).
What's the best way to achieve this ? (Using interceptors ? Using JBoss configuration ?)

Finally, based on previous answer and my personal researches, I retained the folowing solution.
I've created an interceptor dedicated to manage server faults :
public class FaultBarrierInterceptor {
#AroundInvoke
public Object intercept(final InvocationContext invocationContext) throws Exception {
try {
return invocationContext.proceed();
} catch (final RuntimeException e) {
final Logger logger = Logger.getLogger(invocationContext.getMethod().getDeclaringClass());
logger.error("A fault occured during service invocation:" +
"\n-METHOD: " + invocationContext.getMethod() +
"\n-PARAMS: " + Arrays.toString(invocationContext.getParameters()), e);
throw new TechnicalException();
}
}}
The thrown technical exception extends EJBException and does not expose the cause RuntimeException:
public class TechnicalException extends EJBException {}
I use this interceptor in all public services :
#Stateless
#Interceptors({FaultBarrierInterceptor.class})
public class ShoppingCardServicesBean implements ShoppingCardServices { ...
This is an implementation of the Fault Barrier pattern.
Any runtime exception is catched, logged and a fault is signaled to the client (without internal details) using a TechnicalException. Checked exceptions are ignored.
RuntimeException handling is centralized and separated from any business methods.

Any RuntimeException extends java.lang.Exception.
The EJB spec provides handling for 2 types of exceptions (Application and System)
If you'd like to throw a System Exception, you would usually do it like so:
try {
.... your code ...
}catch(YourApplicationException ae) {
throw ae;
}catch(Exception e) {
throw new EJBException(e); //here's where you need to change.
}
To hide the internal details of your system exception, simply replace:
throw new EJBException(e);
with:
throw new EJBException(new TechnicalException("Technical Fault"));
Hope this is what you were looking for.
Cheers

Related

JPA Exception Handling in Spring WebApp

I am working on a Spring web application having DAO, Service, Controller, View layers. JPA is being used for database access. The approach that I am using for JPA exception handling is as below.
public class DBException extends RuntimeException {
implemented constructors to call appropriate RuntimeException constructors.
}
public MyDAOClass {
public void save(Object object) {
try {
entityManager.persist(object);
}catch(PersistenceException e) {
throw new DBException("Error occurred in save", e);
}
}
}
public class MyServiceClass {
public void serviceMethod() {
dao.save(object);
}
}
public class MyRestController {
public void controllerMethod() {
service.save();
}
#ExceptionHandler(DBException.class)
public String handleDBException(DBException e, HttpServletRequest req) {
implemented code to log & handle exception.
}
}
I wanted to have more information in the exception, that's the reason to create custom DBException and also I don't wanted to propagate PersistenceException to other layers.
Is this correct approach for exception handling ?
Should I log the exception in all layers or logging it at the end at controller is good ?
I am catching PersistenceException and rethrowing DBException. Since DBException is a RuntimeException I think spring transaction should rollback in event of exception ?
Thanks.
Is this correct approach for exception handling ?
Yes, you should never propagate exceptions that are specific to layer to the layer above it. If you are expecting the clients of the data layer to recuperate from the exception then create a new custom checked exception and throw it from the catch block in save method.
Should I log the exception in all layers or logging it at the end at
controller is good ?
Logging should be done only at one place, since logging at multiple levels can confuse the programmer examining the stack trace about the original source of exception. In this case I think its best to log the SQLException in the catch block of save method, since you are rethrowing a RuntimeException, the caller of save method may not necessarily catch the exception and log it.
I am catching PersistenceException and rethrowing DBException. Since
DBException is a RuntimeException I think spring transaction should
rollback in event of exception ?
Yes, Spring transactions rollback in case of RuntimeException. This is because the caller code cannot do much in case of RuntimeException, since it represents unrecoverable condition. This behaviour is defined in the Docs.
More about best practices for exception handling here

Three-tier architecture and exceptions

It's considered good practice to have an exception for each layer of application (i.e. PresentationException, ServiceException, PersistenceException etc). But what if my service-layer directly calls DAO methods (methods of persistence layer) without additional operations.
Like this:
public class MyService {
private IPersonDAO dao = new PersonDAO();
public void deletePerson(int id) {
dao.deletePerson(id);
}
}
Should I wrap this DAO method invocation with a try-catch block and rethrow possible exceptions as ServiceException? Should each DAO method throw only PersistenceException?
Well your Dao exceptions are irrelevant to service layer and service layer has nothing to do with dao layer exceptions. Right approach would be to catch dao exception and rethrow new custom exception to service layer.
If you need to debug the exceptions and you want exact cause, you can use getCause() and getSuppressed() methods.
Should I wrap this DAO method invocation with try-catch block and rethrow possible exception as ServiceException? Should each DAO method throw only PersistenceException?
---> Yes wrap it. You can throw other exceptions from dao layer. See example below :
public class MyDao {
public Entity getMyEntity(int id) throws ObjectNotFoundException, PersistenceException {
try {
// code to get Entity
// if entity not found then
throw new ObjectNotFoundException("Entity with id : " + id + "Not found.");
} catch(Exception e) { // you can catch the generic exception like HibernateException for hibernate
throw new PersistenceException("error message", e);
}
}
}
Yes. Its recommended, as you mentioned, to have exceptions for layers; as they can tell what's the problem from the service perspective instead of an DB.
Yes, you should wrap those exceptions in any case, as your service layer clients would otherwise be forced to also deal with the database layer. This would make things overly complicated. Note that the bit of work required to be done in the service layer is meaningless small when compared to the work that would be required to deal with database exceptions in the layer above the service layer.

JAX-WS Client throws SOAPFaultException instead of custom exception

I have a JAX-WS based application that I am developing. I generate WSDL from the server using wsgen and then build the client library using wsimport. I am writing my own custom exceptions to throw with my method calls. The code is structured as follows.
Custom Exception Class:
#WebFault(faultBean = "com.mysite.FaultBean")
public class MyCustomException extends Exception {
private FaultBean faultInfo;
//Getters/Setters/Constructors...
}
Custom Fault Bean:
public class FaultBean {
private String message;
private List<String> messages;
//Getters/Setters/Constructors...
}
I then throw MyCustomException from my methods in my web service endpoint. When I call one of my web service methods and it throws an exception the client is getting a SOAPFaultException instead of MyCustomException. Why is the custom exception not getting used?
So, after a bit of investigation it turns out the exceptions that were being thrown as a SOAPFaultException were not coming from where I thought they were. They actually were not thrown as MyCustomException. So, to solve this for all cases I took advantage of Spring AOP and created an Around aspect to wrap all of my calls to the web service implementation layer.
In this aspect I catch any exception thrown and wrap it in a MyCustomException before rethrowing it. My client can then handle the exception properly.

Handling Dao exceptions in service layer

If my Dao layer throws Dao specific exceptions, then does handling them in my service layer consitute a leakage of concerns? If yes, then should I make the exceptions generic and independent of any layer to address it, or is there some other way?
The same question is applicable to UI layer handling exceptions thrown by service layer.
When we create a layered application, there is always a user layer and another used layer. For this case UI layer -> uses service Layer -> uses DAO layer.
Now its very subjective and open to interpretations. But the objective should be a good degree of decoupling. To achieve this, one way out is the define generic layer specific exceptions say PersistentException, ServiceException etc. These exception will wrap the actual layer specific exception.
For example say if there is some error on database side (Constraint violation etc), wrap that in PersistentException and let service layer handle that (as to how to convey this to UI layer in a generic way)
Now since the integration between service layer and DAO layer is contractual (interface based), the DAO layer is free to change the implementation to anything as long as it obeys the interface contract. So if you change the implementation which throws some new exceptions, those new exceptions can be wrapped in PersistentException and Service layer remains unaffected.
Yes. its a good idea to create your own independant exceptions for each layer.
For example, if you are using a particular DAO implementation, you should wrap the implementation specific exception to your own generic exception and throw it forward to Service Layer.
However, you need to be sensitive in creating your own hierarchy of exception such that it shouldn't be an overhead to application development as well as its able to maintain the information required in the Service Layer. Most of the times, custom error codes with generic exception suffice this.
Something like this can be used to simulate implementation specific exception and thrown to Service layer.
class AppDAOException extends Exception {
public final static int _FAIL_TO_INSERT = 1;
public final static int _UPDATE_FAILED = 2;
public final static int _SQL_ERROR = 3;
private int errorCode;
public AppDAOException(int errorCode) {
this.errorCode = errorCode;
}
public getErrorCode() {
return errorCode;
}
}
Throwing from DAO implementation:
try {
//code here
} catch (some.impl.SQLSyntaxException e) {
throw new AppDAOException (AppDAOException._SQL_ERROR );
}
About leakage of concern:
You may not want your service layer to bother about all the exceptions - such as:
} catch(NoRowExistsException e) {
return null;
} finally {
//release resources
}
So the call has to be taken based on application needs.
Your DAO layer already leaks into the service layer when you do operations like:
userDAO.persist(user);
Exceptions, being a part of the API just like operation should be considered in the same way.
try {
userDAO.persist(user);
} catch (DAOException e) {
// looks fine to me
}
Leakage can happen with runtime exceptions, or when you rethrow exceptions
try {
userDAO.persist(user);
} catch (SQLException e) {
// sql implementation exposed
}
But even this sounds better than "layer independent" exceptions
Good question..!!
Handling exceptions at the UI layer (for example, actions layer if you are using struts) is the good approach.Making exceptions generic is not a good way to deal with this issue. Every layer should have however their specific exceptions as generic. for example, DAO layer may have custom exception handlers like DavaSavingException, IOException etc..
So the approach is throw exception from DAO to service layer and again throw it to UI layer and catch in UI specific classes.
However things are too diplomatic depending upon your applications/needs.

Better Exception Handling in JPA

I used EJB3/JPA when persisting my entities and I am happy on how it is able to manage my DB related
task.
My only concern is on the exception handling. My sample code when saving entity always comes in this flavor.
Most of the tutorials that I read on the net comes in this flavor also with no regards to exception handling.
#Stateless
public class StudentFacade{
#PersistenceContext(unitName = "MyDBPU")
private EntityManager em;
public void save(Student student) {
em.persist(student);
}
}
But I dont know whats the best way of exception handling in an EJB app?
What should be the best way when handling exception?
Is this how others is handling the exception? A try catch block on your session facade?
#Stateless
public class StudentFacade{
#PersistenceContext(unitName = "MyDBPU")
private EntityManager em;
public void save(Student student) {
try {
em.persist(student);
} catch(Exception e) {
//log it or do something
}
}
}
or letting the method throw an exception?
public void save(Student student) throws Exception {
em.persist(student);
}
I dont know if my understanding is correct since I am still learning EJB.
Thanks
The idea of exception handling is doing some logic at a single point in case of any failure.
The try catch will be used at the final point where you need to handle exception or you need to convert an exception to another exception
Say your app has many layers namely Action, Facade, Persist
Delegate exception
In this case any exception that is thrown on Facade can be thrown to the above action layer.
In action the particular exception will be caught and handled with proper error message.
//This is in Facade Layer
public void save(Student student) throws AppException{
//exceptions delegated to action layer
//call to Persist Layer
}
Converting General Exception to App exception
Say in persistence you get and DBException like sqlException. This exception should not be send as such to Action or Facade layer, so we catch the particular exception and then throw a new exception (a user defined exception for application)
//This is in Persist Layer
public void save(Student student) throws AppException{
//converting general exception to AppException and delegating to Facade Layer
try{
em.persist(student);//call to DB. This is in Persist Layer
}catch(Exception e){
throw new AppException("DB exception", e)
}
}
In action Layer
You will catch your exception in action and then handle exception there
//This is in Action layer
public void callSave(Student student){
try{
//call Facade layer
}catch(AppException e){
//Log error and handle
}
}
If you want you method to throw the exception got from em.persistance(...), then don't surround that statement with that try/catch block (cause that will catch every exception that's in that block).
The way you approach this problem depends on the application, whether there already exists some legacy code or not. In the case there is legacy code, I suggest you use the same approach (even in for some cases it's not speed optimal) to maintain consistency.
Otherwise I'd suggest following exceptions' "rule of thumb" - they should be treated in the first place where you have all the information you need about them to take an action, else throw them so someone else can handle. (If you throw them away make sure to throw the most specific form of exception that you could throw (not the general Exception)). Handling exceptions when using JPA is no different then handling Java exceptions in general.
I hope this was simple enough information about exceptions without starting a "religious conversation".
If your combination is ejb with jpa, then all jpa exceptions are runtime exceptions.
ejb handling 2 types of exceptions 1) Application Exception 2) System Exception
Application Exceptions checked exceptions basically we are using business validation and business rules.
System Exceptions are runtime exceptions, so that if any runtime excpetion happend ejb container will interfer and convert the runtime exception as remote exception.
For ex:
in dao layer
public void store(Cargo cargo) {
entityManager.persist(cargo);
}
All jpa exceptions are runtime exceptions only.
in ejb service layer:
public TrackingId bookNewCargo(UnLocode originUnLocode,
UnLocode destinationUnLocode,
Date arrivalDeadline) {
Cargo cargo = new Cargo(trackingId, routeSpecification);
cargoRepository.store(cargo);
return cargo.getTrackingId();
}
in the ejb layer if any runtime exception happend, ejb container will interfere and convert into remote exception.
In the interface layer:
public String register() {
try {
String trackingId = bookingServiceFacade.bookNewCargo(
originUnlocode,
destinationUnlocode,
arrivalDeadline);
} catch (Exception e) {
throw new RuntimeException("Error parsing date", e);
}
so that like this jpa --> ejb --> interface

Categories

Resources