Corn Exception Handlers

    Corn exception module small but very handy that may change your exceptions handling experience in Java. It brings facilities to help writing more dry exception handling codes, i18n support for exception messages, reusable commands and event publishing for both exception throwing and catching.It's published in the maven central repository, so you can use corn-exception by adding the dependency below. 

pom.xml

<dependency>
    <groupId>net.sf.corn</groupId>
    <artifactId>corn-exception</artifactId>
    <version>${version}</version>
</dependency>
 
    If you don't prefer to use maven, you can always download and use jar files from the project files from the sourceforge.net web site.  

Exception Building 

    It's easy and well known how to throw exceptions in Java language. This easy task becomes complicated when it comes to support internalization for your error messages and defining enterprise policies for your exceptions. Luckily, ExceptionBuilder comes help to simplify this tasks. Below is the most simplest form of ExceptionBuilder usage.

ExceptionBuilder.with(IllegalArgumentException.class).message("Sample exception").throwIt();

   Although the exception throwing code is very simple and self explanatory, its good to know that the builder takes default actions and notifies exception listeners behind the scene. The code below shows a command implementation to log exceptions to a generic log file.


private static ExceptionCommand logCommand = new ExceptionCommand() {
        @Override
        public void execute(Exception e) {
            loggerGeneric.log(e.getMessage());
        }
};
 
    The code below defines a listener which notifies some people when critical business exception occurs.

private static ExceptionListener notifyCriticalBusinessExceptionsListener = new ExceptionListener() {
        @Override
        public Runnable action(final Exception exception, final boolean thrown) {
            return new Runnable() {
                @Override
                public void run() {
                    sendMail((thrown ? "Thrown:" : "Caught:") + exception.getMessage());
                }
            };
        }
        @Override
        public boolean isSubject(Class<? extends Exception> exceptionClass, boolean thrown) {
            return CriticalBusinessException.class.isAssignableFrom(exceptionClass)
        }
};

    The code below attaches the defined listener above as common listener to exception builder and puts logCommand to default commands stack.

//Some where in your app begins
ExceptionBuilder.addCommonListener(notifyCriticalBusinessExceptionsListener );
ExceptionBuilder.addDefaultCommand(logCommand);

    As a result the exception builder processes common listeners and default commands each time exception thrown. This is a good way to define application wide controllers, sometimes you may need your class specific commands and/or listener. The code below shows using commands and listener specifically to an exception throwing.

ExceptionBuilder.with(IllegalArgumentException.class).message("Sample exception").execute(logCommand).notify(exListener).throwIt();

    Another handy functionality of the builder is preparing messages from a message template. The builder automatically fulfills message templates with given parameters for you:
 
ExceptionBuilder.with(IllegalArgumentException.class).fill("Says \" %1! %2!\"", "Hello", "world").throwIt();

    Exception builder comes with a default message bundles support, that reads "ExceptionMessages.properties" file in the root of the classpath. You can put your message templates or messages in this file and it's language variants like "ExceptionMessages_fr.properties". If you don't like the default bundle file name, you can change it by using setDefaultBundleName method. Messages or message templates can be decoded as the code below:

ExceptionBuilder.with(YourException.class).decode("msgKey", "Serhat").throwIt();

    The code above uses the system default locale and the code below enforces to usage of a specific locale:

ExceptionBuilder.with(YourException.class).decode("msgKey", Locale.forLanguageTag("tr"), "Serhat").throwIt();

    In the case you want to get your message from a specific bundle, you can specify it as the code below:    

ExceptionBuilder.with(YourException.class).useBundle("com.foo.SampleBundle").decode("msgKey").throwIt();

Exception Catching

    Command execution and events publishing facilities are also exist for exception catching. Default commands and common listeners can be registered to the catcher as below:

//Some where in your app begins
ExceptionCatcher.addCommonListener(notifyCriticalBusinessExceptionsListener );
ExceptionCatcher.addDefaultCommand(logCommand);

    The code below shows the simplest usage of the catcher:

try {
  ...
} catch (AnException e) {
  ExceptionCatcher.trap(e).process();
}

    Although the common listeners and default commands are always in place, sometimes it's necessary to execute scope specific commands or notify listeners:

try {
  ...
} catch (AnException e) {
  ExceptionCatcher.trap(e).execute(command1).notify(listener1).process();
}


Exception Events Bus

    Both builder and catcher are capable to publish events which are controlled by the exceptions event bus. The event bus permits only a single thread execution by default because of the performance considerations. This can be change by using ExceptionEventsBus class methods or defining its configuration in "ExceptionEventsBus.properties" file in the root of the classpath. A sample configuration file content is shown below:

//concurrently executed thread size
threadConcurrentSize=2
//Maximum pool size
threadMaxPoolSize=20000
//Thread max waiting time in the pool before executing it //Wait for ever value is 0
threadKeepAliveTimeInMS=0
//Enable/disable thread execution timeout
//Enabling it cause keep alive time also valid for thread execution
enableThreadExecutionTimeout=false