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.