Exception Converter Suite
An ExceptionConverterSuite
allows multiple Exception Converters to be grouped together, so that when a task is executed and an exception is thrown, it can be converted into the appropriate Failure object.
If an Exception
does not have an ideal ExceptionConverter
, then it will be converted to the base Failure
object using the FallbackExceptionConverter.
This class exposes three methods:
observe
Executes an asynchronous task and returns a Failure
when an Exception
is thrown.
observeSync
Executes a synchronous task and returns a Failure
when an Exception
is thrown.
convert
Directly converts a passed Exception
into a Failure
object.
Observing a task and converting Exceptions
Using the observe
or observeSync
method of the ExceptionConverterSuite
, we can run a task that returns an Either monad containing a Left
(failed) or Right
(success) value. If any exception occurs while running the task, then a Left
object will be returned containing the respective Failure
object of the exception.
There are various approaches to converting an Exception
into a Failure
object, each with its own advantages:
Method A: Using the default exception converters
Default exception converters can be configured when instantiating a ExceptionConverterSuite
object:
// Create an exception converter suite that converts a `SocketException`
// into a `NetworkFailure`
final exceptionConverterSuite = ExceptionConverterSuite(
exceptionConverters: [SocketExceptionConverter.new],
);
final result = await exceptionConverterSuite.observe<void>(
task: (messageLog) async {
// Some code to execute
...
// Simulate exception
throw const SocketException('test');
},
);
// A `Left` object containing a `NetworkFailure`
print('result: $result');
Method B: Using the argument exception converters
Exceptions converters can also be passed to the observe
, observeSync
and convert
methods when calling them:
final exceptionConverterSuite = ExceptionConverterSuite();
final result = exceptionConverterSuite.observeSync<void>(
// Provide an exception converter as an argument
exceptionConverters: [const SocketExceptionConverter()],
task: (messageLog) {
// Some code to execute
...
// Simulate exception
throw const SocketException('test');
},
);
// A `Left` object containing a `NetworkFailure`
print('result: $result');
Method C: Not using exception converters
In some cases, creating a custom exception converter may be unnecessary, particularly if an exception only occurs in a specific location. In these situations, you can manually convert an exception into a failure instead:
final exceptionConverterSuite = ExceptionConverterSuite();
final result = exceptionConverterSuite.observeSync<void>(
task: (messageLog) {
try {
// Simulate exception
throw const SocketException('test');
} on SocketException {
return const Left(NetworkFailure());
}
},
);
// A `Left` object containing a `NetworkFailure`
print('Convert result: $result');
Logging a Task
A task can automatically be logged by providing a MessageLog
(from the Codenic Logger) to the observe
and observeSync
method calls. This allows you to construct log messages by passing it data and assigning a message which will automatically be displayed at the end of the task's execution.
Automatic logging is done when any of the following events occur:
Event A: Directly returning a Left value
When a Left
value is returned, then a logger.warn
will be called to print the messageLog
:
exceptionConverterSuite.observeSync<void>(
messageLog: MessageLog(id: 'test-message-log'),
task: (messageLog) {
messageLog?.data.addAll({'lorep': 2});
messageLog?.message = 'Test warning message';
return const Left(NetworkFailure());
},
);
Log output:

Event B: Directly returning a Right value
When a Right
value is returned, then a logger.info
will be called to print the messageLog
:
exceptionConverterSuite.observeSync<void>(
messageLog: MessageLog(id: 'test-message-log'),
task: (messageLog) {
messageLog?.data.addAll({'lorep': 2});
messageLog?.message = 'Test info message';
return const Right(null);
},
);
Log output:

Event C: catching an exception via a Exception Converter
When an exception is thrown, an ExceptionConverter
can catch that exception and decide whether to print the logs.
Using our SocketExceptionConverter example, this calls logger.wtf
to print the messageLog
when a SocketException
is thrown:
exceptionConverterSuite.observeSync<void>(
exceptionConverters: const [SocketExceptionConverter()],
messageLog: MessageLog(id: 'test-message-log'),
task: (messageLog) {
messageLog?.data.addAll({'lorep': 2});
messageLog?.message = 'Test exception converter message';
throw SocketException('test');
},
);
Log output:

Last updated