Author: scolebourne Date: Sat Oct 24 16:27:30 2009 New Revision: 829400 URL: http://svn.apache.org/viewvc?rev=829400&view=rev Log: Tidy up contexted exception classes, better Javadoc, final variables, etc.
Modified: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java Modified: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java?rev=829400&r1=829399&r2=829400&view=diff ============================================================================== --- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java (original) +++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java Sat Oct 24 16:27:30 2009 @@ -20,31 +20,25 @@ import java.util.Set; /** - * Provides an easier and safer way for developers to provide context when - * generating checked exceptions. Often, additional information, besides what's - * embedded in the exception cause, is needed for developers to debug and correct - * a bug. Often, this additional information can reduce the time it takes - * to replicate and fix a bug. - * - * <p>ContextedException is easier as developers don't need to be concerned - * with formatting the exception message to include additional information - * with the exception. Additional information is automatically included - * in the message and printed stack trace. This often thins out exception - * handling code.</p> - * - * <p>ContextedException is safer as the additional code needed to embed additional - * information in a normal exception tends to be tested less and is more vulnerable - * to errors such as null pointer exceptions.</p> - * - * <p>An unchecked version of this exception is provided by ContextedRuntimeException.</p> - * - * <p>To use this class write code as follows:</p> - * + * <p> + * An exception that provides an easy and safe way to add contextual information. + * </p><p> + * An exception trace itself is often insufficient to provide rapid diagnosis of the issue. + * Frequently what is needed is a select few pieces of local contextual data. + * Providing this data is tricky however, due to concerns over formatting and nulls. + * </p><p> + * The contexted exception approach allows the exception to be created together with a + * map of context values. This additional information is automatically included in the + * message and printed stack trace. + * </p><p> + * An unchecked version of this exception is provided by ContextedRuntimeException. + * </p> + * <p> + * To use this class write code as follows: + * </p> * <pre> * try { - * - * ... - * + * ... * } catch (Throwable e) { * throw new ContextedException("Error posting account transaction", e) * .addLabeledValue("accountNumber", accountNumber) @@ -53,8 +47,8 @@ * } * } * </pre> - * - * <p>The output in a printStacktrace() (which often is written to a log) would look something like the following: + * </p><p> + * The output in a printStacktrace() (which often is written to a log) would look something like the following: * <pre> * org.apache.commons.lang.exception.ContextedException: java.lang.Exception: Error posting account transaction * Exception Context: @@ -66,109 +60,124 @@ * at org.apache.commons.lang.exception.ContextedExceptionTest.testAddLabeledValue(ContextedExceptionTest.java:88) * ..... (rest of trace) * </pre> + * </p> * * @see ContextedRuntimeException * @author D. Ashmore * @since 3.0 - * */ public class ContextedException extends Exception implements ExceptionContext { + /** The serialization version. */ private static final long serialVersionUID = 8940917952810290164L; - private ExceptionContext exceptionContext = new DefaultExceptionContext(); + /** The context where the data is stored. */ + private final ExceptionContext exceptionContext; /** * Instantiates ContextedException without message or cause. - * <p>DefaultExceptionContext used to store and format context information.</p> + * <p> + * The context information is stored using a default implementation. */ public ContextedException() { + super(); + exceptionContext = new DefaultExceptionContext(); } /** * Instantiates ContextedException with message, but without cause. - * <p>DefaultExceptionContext used to store and format context information.</p> - * @param message The exception message + * <p> + * The context information is stored using a default implementation. + * + * @param message the exception message, may be null */ public ContextedException(String message) { super(message); + exceptionContext = new DefaultExceptionContext(); } /** * Instantiates ContextedException with cause, but without message. - * <p>DefaultExceptionContext used to store and format context information.</p> - * @param cause Exception creating need for ContextedException + * <p> + * The context information is stored using a default implementation. + * + * @param cause the underlying cause of the exception, may be null */ public ContextedException(Throwable cause) { super(cause); + exceptionContext = new DefaultExceptionContext(); } /** * Instantiates ContextedException with cause and message. - * <p>DefaultExceptionContext used to store and format context information.</p> - * @param message The exception message - * @param cause Exception creating need for ContextedException + * <p> + * The context information is stored using a default implementation. + * + * @param message the exception message, may be null + * @param cause the underlying cause of the exception, may be null */ public ContextedException(String message, Throwable cause) { super(message, cause); + exceptionContext = new DefaultExceptionContext(); } - + /** * Instantiates ContextedException with cause, message, and ExceptionContext. - * @param message The exception message - * @param cause Exception creating need for ContextedException - * @param context Context used to store additional information - * @since 3.0 + * + * @param message the exception message, may be null + * @param cause the underlying cause of the exception, may be null + * @param context the context used to store the additional information, null uses default implementation */ public ContextedException(String message, Throwable cause, ExceptionContext context) { super(message, cause); - if (context != null) { - this.exceptionContext = context; + if (context == null) { + context = new DefaultExceptionContext(); } + exceptionContext = context; } - + + //----------------------------------------------------------------------- /** * Adds information helpful to a developer in diagnosing and correcting * the problem. For the information to be meaningful, the value passed * should have a reasonable toString() implementation. - * - * <p>Note: If the value provided isn't Serializable, one solution would be + * <p> + * Note: If the value provided isn't Serializable, one solution would be * to provide its toString() if it has a meaningful implementation or - * individual properties of the value object instead.</p> - * @param label a textual label associated with information - * @param value information needed to understand exception. May be <code>null</code>. - * @return this - * @since 3.0 + * individual properties of the value object instead. + * + * @param label a textual label associated with information, null not recommended + * @param value information needed to understand exception, may be null + * @return this, for method chaining */ public ContextedException addLabeledValue(String label, Serializable value) { - this.exceptionContext.addLabeledValue(label, value); - + exceptionContext.addLabeledValue(label, value); return this; } - + /** - * Convenience method to retrieve a value from the underlying ExceptionContext. - * @param label a textual label associated with information - * @return value information needed to understand exception. May be <code>null</code>. - * @since 3.0 + * Retrieves a contextual data value associated with the label. + * + * @param label the label to get the contextual value for, may be null + * @return the contextual value associated with the label, may be null */ public Serializable getLabeledValue(String label) { - return this.exceptionContext.getLabeledValue(label); + return exceptionContext.getLabeledValue(label); } - + /** - * Convenience method to retrieve currently defined labels from the underlying ExceptionContext. - * @return labelSet - * @since 3.0 + * Retrieves the labels defined in the contextual data. + * + * @return the set of labels, never null */ public Set<String> getLabelSet() { - return this.exceptionContext.getLabelSet(); + return exceptionContext.getLabelSet(); } - + /** - * Provides message pertaining to exception. + * Provides the message explaining the exception, including the contextual data. + * * @see java.lang.Throwable#getMessage() - * @return message - * @since 3.0 + * @return the message, never null */ @Override public String getMessage(){ @@ -179,6 +188,6 @@ * {...@inheritdoc} */ public String getFormattedExceptionMessage(String baseMessage) { - return this.exceptionContext.getFormattedExceptionMessage(baseMessage); + return exceptionContext.getFormattedExceptionMessage(baseMessage); } } Modified: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java?rev=829400&r1=829399&r2=829400&view=diff ============================================================================== --- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java (original) +++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java Sat Oct 24 16:27:30 2009 @@ -20,109 +20,165 @@ import java.util.Set; /** - * Provides an unchecked version of ContextedException + * <p> + * A runtime exception that provides an easy and safe way to add contextual information. + * </p><p> + * An exception trace itself is often insufficient to provide rapid diagnosis of the issue. + * Frequently what is needed is a select few pieces of local contextual data. + * Providing this data is tricky however, due to concerns over formatting and nulls. + * </p><p> + * The contexted exception approach allows the exception to be created together with a + * map of context values. This additional information is automatically included in the + * message and printed stack trace. + * </p><p> + * An checked version of this exception is provided by ContextedException. + * </p> + * <p> + * To use this class write code as follows: + * </p> + * <pre> + * try { + * ... + * } catch (Throwable e) { + * throw new ContextedException("Error posting account transaction", e) + * .addLabeledValue("accountNumber", accountNumber) + * .addLabeledValue("amountPosted", amountPosted) + * .addLabeledValue("previousBalance", previousBalance) + * } + * } + * </pre> + * </p><p> + * The output in a printStacktrace() (which often is written to a log) would look something like the following: + * <pre> + * org.apache.commons.lang.exception.ContextedRuntimeException: java.lang.Exception: Error posting account transaction + * Exception Context: + * [accountNumber=null] + * [amountPosted=100.00] + * [previousBalance=-2.17] + * + * --------------------------------- + * at org.apache.commons.lang.exception.ContextedRuntimeExceptionTest.testAddLabeledValue(ContextedExceptionTest.java:88) + * ..... (rest of trace) + * </pre> + * </p> + * * @see ContextedException * @author D. Ashmore * @author Jörg Schaible * @since 3.0 - * */ -public class ContextedRuntimeException extends RuntimeException implements ExceptionContext { +public class ContextedRuntimeException extends Exception implements ExceptionContext { + /** The serialization version. */ private static final long serialVersionUID = 1459691936045811817L; - private ExceptionContext exceptionContext = new DefaultExceptionContext(); - + /** The context where the data is stored. */ + private final ExceptionContext exceptionContext; + /** * Instantiates ContextedRuntimeException without message or cause. - * <p>DefaultExceptionContext used to store and format context information.</p> - * + * <p> + * The context information is stored using a default implementation. */ public ContextedRuntimeException() { + super(); + exceptionContext = new DefaultExceptionContext(); } /** * Instantiates ContextedRuntimeException with message, but without cause. - * <p>DefaultExceptionContext used to store and format context information.</p> - * @param message The exception message - * @since 3.0 + * <p> + * The context information is stored using a default implementation. + * + * @param message the exception message, may be null */ public ContextedRuntimeException(String message) { super(message); + exceptionContext = new DefaultExceptionContext(); } /** * Instantiates ContextedRuntimeException with cause, but without message. - * <p>DefaultExceptionContext used to store and format context information.</p> - * @param cause Exception creating need for ContextedRuntimeException - * @since 3.0 + * <p> + * The context information is stored using a default implementation. + * + * @param cause the underlying cause of the exception, may be null */ public ContextedRuntimeException(Throwable cause) { super(cause); + exceptionContext = new DefaultExceptionContext(); } /** * Instantiates ContextedRuntimeException with cause and message. - * <p>DefaultExceptionContext used to store and format context information.</p> - * @param message The exception message - * @param cause Exception creating need for ContextedException - * @since 3.0 + * <p> + * The context information is stored using a default implementation. + * + * @param message the exception message, may be null + * @param cause the underlying cause of the exception, may be null */ public ContextedRuntimeException(String message, Throwable cause) { - this(message, cause, cause instanceof ExceptionContext ? (ExceptionContext)cause : null); + super(message, cause); + exceptionContext = new DefaultExceptionContext(); } - + /** * Instantiates ContextedRuntimeException with cause, message, and ExceptionContext. - * @param message The exception message - * @param cause Exception creating need for ContextedRuntimeException - * @param context Context used to store additional information - * @since 3.0 + * + * @param message the exception message, may be null + * @param cause the underlying cause of the exception, may be null + * @param context the context used to store the additional information, null uses default implementation */ public ContextedRuntimeException(String message, Throwable cause, ExceptionContext context) { super(message, cause); - if (context != null) { - this.exceptionContext = context; + if (context == null) { + context = new DefaultExceptionContext(); } + exceptionContext = context; } - + + //----------------------------------------------------------------------- /** * Adds information helpful to a developer in diagnosing and correcting - * the problem. - * @see ContextedException#addLabeledValue(String, Serializable) - * @param label a textual label associated with information - * @param value information needed to understand exception. May be <code>null</code>. - * @return this - * @since 3.0 + * the problem. For the information to be meaningful, the value passed + * should have a reasonable toString() implementation. + * <p> + * Note: If the value provided isn't Serializable, one solution would be + * to provide its toString() if it has a meaningful implementation or + * individual properties of the value object instead. + * + * @param label a textual label associated with information, null not recommended + * @param value information needed to understand exception, may be null + * @return this, for method chaining */ public ContextedRuntimeException addLabeledValue(String label, Serializable value) { - this.exceptionContext.addLabeledValue(label, value); + exceptionContext.addLabeledValue(label, value); return this; } - + /** - * Convenience method to retrieve a value from the underlying ExceptionContext. - * @param label a textual label associated with information - * @return value information needed to understand exception. May be <code>null</code>. - * @since 3.0 + * Retrieves a contextual data value associated with the label. + * + * @param label the label to get the contextual value for, may be null + * @return the contextual value associated with the label, may be null */ public Serializable getLabeledValue(String label) { - return this.exceptionContext.getLabeledValue(label); + return exceptionContext.getLabeledValue(label); } - + /** - * Convenience method to retrieve currently defined labels from the underlying ExceptionContext. - * @return labelSet - * @since 3.0 + * Retrieves the labels defined in the contextual data. + * + * @return the set of labels, never null */ public Set<String> getLabelSet() { - return this.exceptionContext.getLabelSet(); + return exceptionContext.getLabelSet(); } - + /** - * Provides message pertaining to exception. + * Provides the message explaining the exception, including the contextual data. + * * @see java.lang.Throwable#getMessage() - * @return message - * @since 3.0 + * @return the message, never null */ @Override public String getMessage(){ @@ -133,6 +189,6 @@ * {...@inheritdoc} */ public String getFormattedExceptionMessage(String baseMessage) { - return this.exceptionContext.getFormattedExceptionMessage(baseMessage); + return exceptionContext.getFormattedExceptionMessage(baseMessage); } } Modified: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java?rev=829400&r1=829399&r2=829400&view=diff ============================================================================== --- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java (original) +++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java Sat Oct 24 16:27:30 2009 @@ -17,74 +17,63 @@ package org.apache.commons.lang.exception; import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import org.apache.commons.lang.SystemUtils; /** - * Provides context feature for exceptions. Used by both checked and unchecked version of the contexted exceptions. - * @see ContextedRuntimeException + * Default implementation of the context storing the label-value pairs for contexted exceptions. + * * @author D. Ashmore * @since 3.0 */ -public class DefaultExceptionContext implements ExceptionContext { - +class DefaultExceptionContext implements ExceptionContext { + + /** The serialization version. */ private static final long serialVersionUID = 293747957535772807L; - - /* - * This value list could really be obtained from the Map, however, some - * callers want to control the order of the list as it appears in the - * Message. The list allows that. name/value pairs will appear in - * the order that they're provided. D. Ashmore - */ - private List<String> contextKeyList = new ArrayList<String>(); - private Map<String, Serializable> contextValueMap = new HashMap<String, Serializable>(); - + /** The ordered map storing the label-data pairs. */ + private Map<String, Serializable> contextValueMap = new LinkedHashMap<String, Serializable>(); + /** - * Adds information helpful to a developer in diagnosing and correcting - * the problem. - * @see ContextedException#addLabeledValue(String, Serializable) - * @param label a textual label associated with information - * @param value information needed to understand exception. May be null. - * @return this - * @since 3.0 + * Adds a contextual label-value pair into this context. + * <p> + * This label-value pair provides information useful for debugging. + * + * @param label the label of the item to add, null not recommended + * @param value the value of item to add, may be null + * @return this, for method chaining */ public ExceptionContext addLabeledValue(String label, Serializable value) { - this.contextKeyList.add(label); - this.contextValueMap.put(label, value); - + contextValueMap.put(label, value); return this; } - + /** - * Retrieves the value for a given label. - * @param label a textual label associated with information - * @return value information needed to understand exception. May be null. - * @since 3.0 + * Retrieves a contextual data value associated with the label. + * + * @param label the label to get the contextual value for, may be null + * @return the contextual value associated with the label, may be null */ public Serializable getLabeledValue(String label) { - return this.contextValueMap.get(label); + return contextValueMap.get(label); } - + /** - * Retrieves currently defined labels. - * @return labelSet - * @since 3.0 + * Retrieves the labels defined in the contextual data. + * + * @return the set of labels, never null */ public Set<String> getLabelSet() { - return this.contextValueMap.keySet(); + return contextValueMap.keySet(); } - + /** - * Centralized message logic for both checked and unchecked version of - * context exceptions - * @param baseMessage message retained by super class - * @return message -- exception message - * @since 3.0 + * Builds the message containing the contextual information. + * + * @param baseMessage the base exception message <b>without</b> context information appended + * @return the exception message <b>with</b> context information appended, never null */ public String getFormattedExceptionMessage(String baseMessage){ StringBuilder buffer = new StringBuilder(256); @@ -92,7 +81,7 @@ buffer.append(baseMessage); } - if (contextKeyList.size() > 0) { + if (contextValueMap.size() > 0) { if (buffer.length() > 0l) { buffer.append(SystemUtils.LINE_SEPARATOR); } @@ -102,7 +91,7 @@ Object value; String valueStr; - for (String label: this.contextKeyList) { + for (String label : contextValueMap.keySet()) { buffer.append("["); buffer.append(label); buffer.append("="); @@ -126,5 +115,5 @@ } return buffer.toString(); } - + } Modified: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java?rev=829400&r1=829399&r2=829400&view=diff ============================================================================== --- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java (original) +++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java Sat Oct 24 16:27:30 2009 @@ -31,38 +31,40 @@ * @since 3.0 */ public interface ExceptionContext extends Serializable { - + /** - * Adds a context item along with a label. - * @param label label of item - * @param value value of item + * Adds a contextual label-value pair into this context. + * <p> + * This label-value pair provides information useful for debugging. + * + * @param label the label of the item to add, null not recommended + * @param value the value of item to add, may be null * @return context itself to allow method chaining - * @since 3.0 */ public ExceptionContext addLabeledValue(String label, Serializable value); - + /** - * Provides context information associated with the given label. - * @param label label of item - * @return value value associated with label - * @since 3.0 + * Retrieves a contextual data value associated with the label. + * + * @param label the label to get the contextual value for, may be null + * @return the contextual value associated with the label, may be null */ public Serializable getLabeledValue(String label); - + /** - * Provides a set of labels that are currently in the context. - * @return labelSet labels currently used by the context - * @since 3.0 + * Retrieves the labels defined in the contextual data. + * + * @return the set of labels, never null */ public Set<String> getLabelSet(); - + /** * Implementors provide the given base message with context label/value item * information appended. - * @param baseMessage exception message <b>without</b> context information appended - * @return formattedMessage exception message <b>with</b> context information appended - * @since 3.0 + * + * @param baseMessage the base exception message <b>without</b> context information appended + * @return the exception message <b>with</b> context information appended, never null */ public String getFormattedExceptionMessage(String baseMessage); -} \ No newline at end of file +}