Handling Dao exceptions in service layer - java

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.

Related

Can we handle a exception from dao layer to presentation layer without impacting the service layer(no modification in service layer)

The scenario is like I wrote a MVC-based application:
Controller - Service - DAO layer. Now I got an exception in DAO layer and I want to handle that exception in presentation layer so that service layer needs no change.
Because by using regular try/catch or throws it has to pass through the service layer which I don't want.
Is there any better approach to achieve it?
class Controller{
method1(){}
}
class service(){
method1Serice(){}
}
class DAO(){
method1DAO(){
// exception occurs here
}
You can have the DAO class throw an unchecked exception. (any subclass of RuntimeException will do). You can create your own custom exception or use any of the predefined ones. just make sure the Service doesn't catch Throwable and you can have the Controller catch it.
You can extend your exception class from RuntimeException so that compiler does not complain about exception handling. You can then catch that exception in the presentation layer.
Perhaps you are looking for Controller Based Exception Handling, you can check these in Exception Handling in Spring MVC and also Error Handling for REST with Spring.
#ExceptionHandler(YourException.class)
public String handleException(){
logger.info(message);
return "database_error";
}
Actually I would suggest you handle the exceptions properly in Service-Layer and encapsulate that exception properly to return to the front-user via Controller-Layer.
Normally, checked exceptions are carrying some meaningful messages which can be used to do recovery or let the caller explicitly handle it properly. Try not to directly avoid it since it's there.
As I understand it, a data access object (DAO) is intended for transferring data between the server and the client. I'm assuming that the client is what you refer to as the presentation layer. In other words, the part that the end user interacts with. As such, the DAO should contain fields and accessor methods only, i.e. it should not contain logic. Hence it should not contain methods that may throw exceptions. So I would suggest perhaps re-designing your application. Otherwise, perhaps you can provide more detailed code?

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

Java Exception Translator Utility

I have a typical RESTful web service with two layers. A resource layer and a service layer. The DAO layer seems obsolete with modern object relational mapping libraries.
I am using Google Cloud Endpoints which not surprisingly returns HTTP errors in the form of Java Exceptions. I have a dedicated set of Exceptions the service layer can throw, such as an Object Not Found Exception, from the object relational mapping library, and other internal exceptions. Suffice to say, each internal exception has an HTTP Exception counterpart.
In order for a resource to safely call a service method, the call is surrounded in a series of try catches.
try {
resourceObject = CorrespondingService.method(...);
} catch (InternalExceptionOne internalExceptionOne) {
throw new CorrespondingWebExcpetionOne(internalExceptionOne.getMessage());
} catch (InternalExceptionTwo internalExceptionTwo) {
throw new CorrespondingWebExcpetionTwo(internalExceptionTwo.getMessage());
} catch (InternalExceptionThree internalExceptionThree) {
throw new CorrespondingWebExcpetionThree(internalExceptionThree.getMessage());
}
Since every call to a service method from the resource layer must be wrapped in the same series of try catch statements this creates a lot of repeated code.
I was looking to create a Utility that could act as a WebExcpetionTranslator, but I would have to pass it a method to be run under a try catch. Not sure how to pass a method and parameters, and then how to subsequently call said passed method.
This seems a bit sloppy though? Its there any thing out there that might do this with annotations?
How can I pass a method and arbitrary parameters to a utility method, and subsequently call the passed method with the parameters?
What about annotations? Can you make a custom annotation to handle different exceptions?
P.S. My technology stack is GAE, Objectify, and Google Cloud Endpoints.

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.

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