This is a small example that shows how the same message bean implementation is used in a logging and in an exception handling context.
This post is part of a series of articles that provide information about smartics Exceptions, an exception library for Java.
For a short introduction to smartics Exceptions please refer to our blog post What is smartics-exceptions all about?.
Quick and Dirty
Here is a code sippet that creates an instance of a service via Java’s ServiceLoader
:
public final T create() throws ResourceException {
final Iterator<T> iterator = ServiceLoader.load(type).iterator();
final StringBuilder buffer = new StringBuilder(64);
T instance = null;
while (iterator.hasNext()) {
try {
if (instance != null) {
final String implementation =
iterator.next().getClass().getName();
buffer
.append("\nDuplicated implementation rejected: ")
.append(implementation);
continue;
}
instance = iterator.next();
}
catch (final ServiceConfigurationError e) {
buffer
.append("\nError encountered: ")
.append(e.getMessage());
}
}
if (buffer.length() > 0) {
LOG.warn(
"Problems encountered while fetching implementations of '"
+ type.getName() + "':" + buffer);
}
if (instance == null) {
throw new ResourceException(
"Cannot create instance of implementation of '"
+ type.getName() + "'.");
}
return instance;
}
The implementation is straight forward: text messages are coded as string literals for logging (LOG.warn(...)
) and providing information about an exception context (throw new ResourceException(...)
). To move these text messages to resource bundles, smartics Exceptions can help.
Using smartics-exceptions
The code using smartics-exceptions is like this:
public final T create() throws ResourceException {
final Iterator<T> iterator = ServiceLoader.load(type).iterator();
final TypeProblemMessageBean.Builder builder =
new TypeProblemMessageBean.Builder().with(type);
T instance = null;
while (iterator.hasNext()) {
try {
if (instance != null) {
final String implementation =
iterator.next().getClass().getName();
builder.withDuplicate(implementation);
continue;
}
instance = iterator.next();
}
catch (final ServiceConfigurationError e) {
builder.withError(e.getMessage());
}
}
if (builder.hasReportedProblems()) {
LOG.warn(builder.toMessage());
}
if (instance == null) {
throw new ResourceException(new TypeProblemMessageBean(type));
}
return instance;
}
As you can see the code uses a message bean implementation to collect information about a logging event. The same implementation is used to provide information to a raised exception.
Moving the texts out of the code requires some more work than shown in the above snippet. You have to write a message bean implementation (in this case even with a builder that replaces the string buffer from the quick and dirty example) and add the resource bundle. Please refer to Message-based I18N exceptions for details on this.