A very lightweight library, that simplifies the usage of custom listeners. It is inspired
by the PropertyChangeSupport but it has the advantage of a custom listener implementation
like type safety.
Minimum Java-Version: 8 | Compile Java-Version: 8 | Latest Library Version: 0.9.0
As soon as you are going to create a listener interface for your view, model, controller or any other part of your application, you have to write a lot of boilerplate code to manage and notify this listeners, like...
- manage a collection to store the listeners
- add new listeners to that collection (after checking that it is not part of it, yet)
- removing old listeners from that collection (after checking that it was part of it)
- iterate over the whole collection to notify these listeners with the specific params
- catch exceptions thrown by the listeners to avoid errors
- make sure the notification is done in the correct thread
- ...
This is where the ListenerSupport library comes in place. The ListenerSupport simplifies the
management of your listeners. Adding, removing and notifying them is now only ONE method call.
On top of that, you can...
- define
Executors that will be used to do this notification (e.g. do a notification in the UI-Thread). - define
FailureStrategies that will be called, when any listener throws an exception on notification call.
- Add JCenter to your artifact repositories
// using gradle
repositories {
jcenter()
}- Add the ListenerSupport to your dependencies
// using gradle
dependencies {
compile 'de.codecrafters.listenersupport:listenersupport:<version>'
}The following example will the listener interface definition below.
public interface MyListener {
void onSomethingHappened( final String something );
}To create a ListenerSupport for any listener definition, you simply use the
ListenerSupport class.
myListenerSupport = ListenerSupport.createFor( MyListener::onSomethingHappened );This simple call will create a ListenerSupport that enables you to add and remove
listeners of type MyListener and provides a notifyListeners()-method which takes the same arguments
as the MyListener#onSomethingHappened method.
As described in the "ListenerSupport Creation" section, after the creation you are able to use type safe methods to add, remove and notify listeners.
So if we use the example above, the myListenerSupport will provide the following methods (among others):
myListenerSupport#addListener( MyListener )
myListenerSupport#removeListener( MyListener )
myListenerSupport#notifyListeners( String )
The most interesting of these methods is the notify method, which has exactly the same arguments as the
method that shall be called (in this case it's the MyListener#onSomethingHappened method).
To define in which thread the notification is done, or if the notifications are done serial or in
parallel you can give an Executor that will be used. Simply pass the Executor that shall be used
for notification as second parameter to the ListenerSupport#createFor() method.
myListenerSupport = ListenerSupport.createFor( MyListener::onSomethingHappened, NotifyExecutors.uiThreadExecutor() );If no Executor is passed, it'll notify the listeners in the thread from which the notify() method
was called.
As there can be errors thrown by listeners that are notified, there is the possibility
to register a FailureStrategy to the ListenerSupport. That FailureStrategy is
called whenever a listener has thrown a Throwable.
There are already multiple FailureStrategies available to be used:
| Name | Artifact |
|---|---|
| JavaLoggingFailureStrategy | de.codecrafters.listenersupport:failurestrategy-javalogger |
| Log4jFailureStrategy | de.codecrafters.listenersupport:failurestrategy-log4j |
| PrintStackTraceFailureStrategy | none (set if no other available) |
| Slf4jFailureStrategy | de.codecrafters.listenersupport:failurestrategy-slf4j |
| SystemErrorFailureStrategy | de.codecrafters.listenersupport:failurestrategy-systemerrorwriter |
If you want to apply any of these failure strategies, just add it as runtime dependency to your project. It'll be
automatically used for every ListenerSupport you create.
If you have multiple failure strategies in your classpath you can define the default one by creating a property file
called "failurestrategyloader.properties" and set the name of the strategy that shall be the default for the
property called "strategyName".
If you need to set the failure strategy different for any ListenerSupport just use the
ListenerSupport#setFailureStrategy() method.
If you want to have all failure strategies available just use the de.codecrafters.listenersupport:failurestrategy-all
artifact. This one also contains a factory called FailureStrategies that simplifies the creation for all failure
strategies.
If the available failure strategies are not fulfilling your needs, you could of cause create your custom strategy.
A FailureStrategy implementation that will log the thrown errors using the java.util.logging.Logger. The used
log level is ERROR.
A FailureStrategy implementation that will log the thrown errors using the org.apache.logging.log4j.Logger. The
used log level is ERROR.
A FailureStrategy implementation that will print the thrown errors using the Throwable#printStackTrace() method.
A FailureStrategy implementation that will log the thrown errors using the org.slf4j.Logger. The used log level
is ERROR.
A FailureStrategy implementation that will print the thrown errors using the System.err print stream
(like Throwable#printStackTrace(System.err)) after printing the class information of the listener which has thrown
this error.
