You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by sc...@apache.org on 2009/10/24 18:27:32 UTC

svn commit: r829400 - in /commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception: ContextedException.java ContextedRuntimeException.java DefaultExceptionContext.java ExceptionContext.java

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&ouml;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
+}