Fred Pym
Fred Pym

Reputation: 2329

How to eliminate the duplicate try-catch code in similar methods?

I have the following insert/update methods in my service:

@Override
public void insertEntity(Entity entity) {

  try {        
    entityDao.insert(entityMapper.entityToEntityDO(entity));

  } catch (DataIntegrityViolationException ex){

    if(ex.getCause() instanceof SQLIntegrityConstraintViolationException) {
      SQLIntegrityConstraintViolationException violationEx = (SQLIntegrityConstraintViolationException) ex.getCause();
      if(violationEx.getErrorCode() == 1048 && "23000".equals(violationEx.getSQLState())) {
        throw new FieldCannotBeNullException(violationEx.getMessage());
      }
    }

    throw ex;
  }
}

@Override
public void updateEntity(Entity entity) {

  try {        
    entityDao.update(entityMapper.entityToEntityDO(entity));

  } catch (DataIntegrityViolationException ex){

    if(ex.getCause() instanceof SQLIntegrityConstraintViolationException) {
      SQLIntegrityConstraintViolationException violationEx = (SQLIntegrityConstraintViolationException) ex.getCause();
      if(violationEx.getErrorCode() == 1048 && "23000".equals(violationEx.getSQLState())) {
        throw new FieldCannotBeNullException(violationEx.getMessage());
      }
    }

    throw ex;
  }
}

As you can see, the actual logic of insertEntity and updateEntity is very simple. In order to throw a custom Exception, I did some database error code check. Since the two methods all need this kind of checking, the code duplicated in both methods, which is obviously a code smell.

How can I eliminate this kind of code duplication?

Upvotes: 3

Views: 3865

Answers (4)

alexsalo
alexsalo

Reputation: 1495

You can declare your methods to throw the exception, then try/catch in one place where your methods are called. For example:

public void insertEntity(Entity entity) throws DataIntegrityViolationException {} 
public void updateEntity(Entity entity) throws DataIntegrityViolationException {}  
try {
  insertEntity(entity);
  updateEntity(entity);
catch (DataIntegrityViolationException e) {
  // handle exception
}

Upvotes: 0

fariasmaxi
fariasmaxi

Reputation: 11

You can create Interface like this:

public interface ConsumerWithException<T, V extends Exception> {
    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t) throws V;

}

Use it a private method like:

private void action(ConsumerWithException<Entity, DataIntegrityViolationException> doAction, Entity entity){
    try {
        doAction.accept(entity);
    } catch (DataIntegrityViolationException ex){

        if(ex.getCause() instanceof SQLIntegrityConstraintViolationException) {
            SQLIntegrityConstraintViolationException violationEx = (SQLIntegrityConstraintViolationException) ex.getCause();
            if(violationEx.getErrorCode() == 1048 && "23000".equals(violationEx.getSQLState())) {
                throw new FieldCannotBeNullException(violationEx.getMessage());
            }
        }

        throw ex;
    }
}    

Upvotes: 1

Sandeep Kaul
Sandeep Kaul

Reputation: 3267

You can put the code inside the catch block into a separate method.

Alternatively, You can catch Exception and write a handler method to handle the exceptions if in future you expect to handle multiple exceptions there.

Upvotes: 0

G. Fiedler
G. Fiedler

Reputation: 726

Extract the common catch-block to a method which throws DataIntegrityViolationException.

Upvotes: 2

Related Questions