简体   繁体   中英

How to write an exception factory in Java

We are currently developing a framework for internal use. We are now at the point that we want to use standardized exception IDs and messages. The developer just has to provide an ID and a default message and the framework looks up the associated message(if possible) or uses the default message(if the message could not be retrieved). The first idea was to write an exception factory which enforces the developer to provide an error ID and then lookup the message in the factory method. The problem with this approach is, that an additional frame is added in the stacktrace(the factory method where the exception is created). Thats not very nice. Almost every solution which tries to hide the creation has this issue. The second idea was to couple the message lookup and our exception class and write an abstract exception class which takes the error ID in the constructor and handles the message lookup. But thats also not very nice cause it lacks loose coupling. Third idea was let the developer write the lookup of the message every time.. also bad..

Do you have any ideas?

PS I think thats the first time I need macros in Java..

the different approaches in code:

1.

throw createException(new ErrorId("123"), TechnicalException.class, "defaultmsg"); //uses reflection, also not very nice but works

or

throw createTechnicalException(new ErrorId("123", "defaultmsg"); //write a method for every type of exception

2.

public TechnicalException(ErrorId errorId, String defaultmsg) {
    super(defaultmsg);
    //get msg here and set on a new field cause detailMessage is not accessible. Also overwrite toString();
}

throw new TechnicalException(new ErrorId("123"), "defaultmsg");

3.

ErrorId errorId = new ErrorId("123");
String msg = someProvider.getMessage(errorId);
throw new TechnicalException(errorId, msg);

It's possible to edit the stack trace, removing unneeded elements. If all exceptions' constructors need the same data, use single createException, else use createCustomException methods.

This removes unnecessary stack trace elements.

public static <T extends Throwable> T adjustStackTrace(T ex, int removedElements) {
    //use an explicit constraint for removedElements
    if (removedElements < 1) {
        throw new IllegalArgumentException("removedElements may not be less than 1");
    }
    final StackTraceElement[] stack = ex.getStackTrace();
    //or an implicit constraint
    removedElements = Math.max(removedElements, stack.length);

    final StackTraceElement[] newStack = new StackTraceElement[stack.length - removedElements];
    System.arraycopy(stack, removedElements, newStack, 0, stack.length - removedElements);
    ex.setStackTrace(newStack);
    return ex;
}

a method for a custom excepton:

public static TechnicalException createTechnicalException(Object... someExceptionSpecificData) {
    StringBuilder sb = new StringBuilder();
    sb.append("...").append("..."); //create a message

    //process the someExceptionSpecificData
    Object[] someNewData = someExceptionSpecificData;

    TechnicalException ex = new TechnicalException(sb.toString(), someNewData);

    ex = adjustStackTrace(ex, 1 /*remove StackTraceElement, related to this method call*/);
    return ex;
}

Or you can use a single method and pass desired exception class:

public  Exception createException(Class<?> exClass, Object... someExceptionSpecificData) {...}

usage example:

public void useExceptionFactory() {
    throw ExceptionFactory.createTechnicalException();
}

public void adjustEvenMore() {
    //adjust even more to hide the implementation of your library
    throw ExceptionFactory.adjustStackTrace(ExceptionFactory.createTechnicalException(),1);
}

This example is based on net.sf.oval.internal.util.Assert from OVal framework, see http://oval.sourceforge.net/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM