diff --git a/src/main/java/org/apache/commons/lang3/exception/ContextedException.java b/src/main/java/org/apache/commons/lang3/exception/ContextedException.java index 3b1f8e6a9..25a6896e2 100644 --- a/src/main/java/org/apache/commons/lang3/exception/ContextedException.java +++ b/src/main/java/org/apache/commons/lang3/exception/ContextedException.java @@ -43,9 +43,22 @@ import org.apache.commons.lang3.tuple.Pair; * ... * } catch (Exception e) { * throw new ContextedException("Error posting account transaction", e) - * .addContextValue("accountNumber", accountNumber) - * .addContextValue("amountPosted", amountPosted) - * .addContextValue("previousBalance", previousBalance) + * .addContextValue("Account Number", accountNumber) + * .addContextValue("Amount Posted", amountPosted) + * .addContextValue("Previous Balance", previousBalance) + * } + * } + * or improve diagnose data at a higher level: + *
+ *   try {
+ *     ...
+ *   } catch (ContextedException e) {
+ *     throw e.setContextValue("Transaction Id", transactionId);
+ *   } catch (Exception e) {
+ *     if (e instanceof ExceptionContext) {
+ *       e.setContextValue("Transaction Id", transactionId);
+ *     }
+ *     throw e;
  *   }
  * }
  * 
@@ -54,9 +67,10 @@ import org.apache.commons.lang3.tuple.Pair; *
  * org.apache.commons.lang3.exception.ContextedException: java.lang.Exception: Error posting account transaction
  *  Exception Context:
- *  [accountNumber=null]
- *  [amountPosted=100.00]
- *  [previousBalance=-2.17]
+ *  [1:Account Number=null]
+ *  [2:Amount Posted=100.00]
+ *  [3:Previous Balance=-2.17]
+ *  [4:Transaction Id=94ef1d15-d443-46c4-822b-637f26244899]
  *
  *  ---------------------------------
  *  at org.apache.commons.lang3.exception.ContextedExceptionTest.testAddValue(ContextedExceptionTest.java:88)
@@ -155,24 +169,6 @@ public class ContextedException extends Exception implements ExceptionContext {
         return this;
     }
 
-    /**
-     * 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.
-     * Different values can be added with the same label multiple times.
-     * 

- * Note: This exception is only serializable if the object added as value is serializable. - *

- * - * @param pair a pair of textual label and information, not {@code null} - * @return {@code this}, for method chaining, not {@code null} - * @throws NullPointerException if {@code pair} is {@code null} - */ - public ContextedException addContextValue(Pair pair) { - this.exceptionContext.addContextValue(pair); - return this; - } - /** * Sets information helpful to a developer in diagnosing and correcting the problem. * For the information to be meaningful, the value passed should have a reasonable @@ -191,24 +187,6 @@ public class ContextedException extends Exception implements ExceptionContext { return this; } - /** - * Sets 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. - * Any existing values with the same labels are removed before the new one is added. - *

- * Note: This exception is only serializable if the object added as value is serializable. - *

- * - * @param pair a pair of textual label and information, not {@code null} - * @return {@code this}, for method chaining, not {@code null} - * @throws NullPointerException if {@code pair} is {@code null} - */ - public ContextedException setContextValue(Pair pair) { - this.exceptionContext.setContextValue(pair); - return this; - } - /** * {@inheritDoc} */ diff --git a/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java b/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java index 4d318dd56..980b69c3e 100644 --- a/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java +++ b/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java @@ -42,10 +42,23 @@ import org.apache.commons.lang3.tuple.Pair; * try { * ... * } catch (Exception e) { - * throw new ContextedException("Error posting account transaction", e) - * .addContextValue("accountNumber", accountNumber) - * .addContextValue("amountPosted", amountPosted) - * .addContextValue("previousBalance", previousBalance) + * throw new ContextedRuntimeException("Error posting account transaction", e) + * .addContextValue("Account Number", accountNumber) + * .addContextValue("Amount Posted", amountPosted) + * .addContextValue("Previous Balance", previousBalance) + * } + * } + *
or improve diagnose data at a higher level: + *
+ *   try {
+ *     ...
+ *   } catch (ContextedRuntimeException e) {
+ *     throw e.setContextValue("Transaction Id", transactionId);
+ *   } catch (Exception e) {
+ *     if (e instanceof ExceptionContext) {
+ *       e.setContextValue("Transaction Id", transactionId);
+ *     }
+ *     throw e;
  *   }
  * }
  * 
@@ -54,9 +67,10 @@ import org.apache.commons.lang3.tuple.Pair; *
  * org.apache.commons.lang3.exception.ContextedRuntimeException: java.lang.Exception: Error posting account transaction
  *  Exception Context:
- *  [accountNumber=null]
- *  [amountPosted=100.00]
- *  [previousBalance=-2.17]
+ *  [1:Account Number=null]
+ *  [2:Amount Posted=100.00]
+ *  [3:Previous Balance=-2.17]
+ *  [4:Transaction Id=94ef1d15-d443-46c4-822b-637f26244899]
  *
  *  ---------------------------------
  *  at org.apache.commons.lang3.exception.ContextedRuntimeExceptionTest.testAddValue(ContextedExceptionTest.java:88)
@@ -155,24 +169,6 @@ public class ContextedRuntimeException extends RuntimeException implements Excep
         return this;
     }
 
-    /**
-     * 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.
-     * Different values can be added with the same label multiple times.
-     * 

- * Note: This exception is only serializable if the object added as value is serializable. - *

- * - * @param pair a pair of textual label and information, not {@code null} - * @return {@code this}, for method chaining, not {@code null} - * @throws NullPointerException if {@code pair} is {@code null} - */ - public ContextedRuntimeException addContextValue(Pair pair) { - this.exceptionContext.addContextValue(pair); - return this; - } - /** * Sets information helpful to a developer in diagnosing and correcting the problem. * For the information to be meaningful, the value passed should have a reasonable @@ -191,24 +187,6 @@ public class ContextedRuntimeException extends RuntimeException implements Excep return this; } - /** - * Sets 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. - * Any existing values with the same labels are removed before the new one is added. - *

- * Note: This exception is only serializable if the object added as value is serializable. - *

- * - * @param pair a pair of textual label and information, not {@code null} - * @return {@code this}, for method chaining, not {@code null} - * @throws NullPointerException if {@code pair} is {@code null} - */ - public ContextedRuntimeException setContextValue(Pair pair) { - this.exceptionContext.setContextValue(pair); - return this; - } - /** * {@inheritDoc} */ diff --git a/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java b/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java index 9c8eaa717..8a54b7e96 100644 --- a/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java +++ b/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java @@ -32,7 +32,10 @@ import org.apache.commons.lang3.tuple.Pair; *

* This implementation is serializable, however this is dependent on the values that * are added also being serializable. + *

* + * @see ContextedException + * @see ContextedRuntimeException * @since 3.0 */ public class DefaultExceptionContext implements ExceptionContext, Serializable { @@ -47,17 +50,7 @@ public class DefaultExceptionContext implements ExceptionContext, Serializable { * {@inheritDoc} */ public DefaultExceptionContext addContextValue(String label, Object value) { - return addContextValue(new ImmutablePair(label, value)); - } - - /** - * {@inheritDoc} - */ - public DefaultExceptionContext addContextValue(Pair pair) { - if (pair == null) { - throw new NullPointerException(); - } - contextValues.add(pair); + contextValues.add(new ImmutablePair(label, value)); return this; } @@ -65,21 +58,14 @@ public class DefaultExceptionContext implements ExceptionContext, Serializable { * {@inheritDoc} */ public DefaultExceptionContext setContextValue(String label, Object value) { - return setContextValue(new ImmutablePair(label, value)); - } - - /** - * {@inheritDoc} - */ - public DefaultExceptionContext setContextValue(Pair pair) { - final String label = pair.getKey(); // implicit NPE for (final Iterator> iter = contextValues.iterator(); iter.hasNext();) { final Pair p = iter.next(); if (StringUtils.equals(label, p.getKey())) { iter.remove(); } } - return addContextValue(pair); + addContextValue(label, value); + return this; } /** @@ -143,16 +129,18 @@ public class DefaultExceptionContext implements ExceptionContext, Serializable { } buffer.append("Exception Context:\n"); - Object value; - String valueStr; + int i = 0; for (final Pair pair : contextValues) { buffer.append("\t["); + buffer.append(++i); + buffer.append(':'); buffer.append(pair.getKey()); buffer.append("="); - value = pair.getValue(); + final Object value = pair.getValue(); if (value == null) { buffer.append("null"); } else { + String valueStr; try { valueStr = value.toString(); } catch (Exception e) { diff --git a/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java b/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java index beeacc477..719dad570 100644 --- a/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java +++ b/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java @@ -48,19 +48,6 @@ public interface ExceptionContext { */ public ExceptionContext addContextValue(String label, Object value); - /** - * Adds a contextual label-value pair into this context. - *

- * The pair will be added to the context, independently of an already - * existing pair with the same label. - *

- * - * @param pair the label-value pair to add, not {@code null} - * @return {@code this}, for method chaining, not {@code null} - * @throws NullPointerException if pair is {@code null} - */ - public ExceptionContext addContextValue(Pair pair); - /** * Sets a contextual label-value pair into this context. *

@@ -74,19 +61,6 @@ public interface ExceptionContext { */ public ExceptionContext setContextValue(String label, Object value); - /** - * Sets a contextual label-value pair into this context. - *

- * The pair will be added normally, but any existing label-value pair with - * the same label is removed from the context. - *

- * - * @param pair the label-value pair to add, not {@code null} - * @return {@code this}, for method chaining, not {@code null} - * @throws NullPointerException if pair is {@code null} - */ - public ExceptionContext setContextValue(Pair pair); - /** * Retrieves all the contextual data values associated with the label. * diff --git a/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionContextTest.java b/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionContextTest.java index 794410a68..0970cf0b4 100644 --- a/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionContextTest.java +++ b/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionContextTest.java @@ -23,6 +23,7 @@ import java.util.Date; import java.util.List; import java.util.Set; +import org.apache.commons.lang3.SerializationUtils; import org.apache.commons.lang3.tuple.Pair; import junit.framework.TestCase; @@ -31,16 +32,13 @@ import junit.framework.TestCase; /** * Abstract test of an ExceptionContext implementation. */ -public abstract class AbstractExceptionContextTest extends TestCase { +public abstract class AbstractExceptionContextTest extends TestCase { protected static final String TEST_MESSAGE_2 = "This is monotonous"; protected static final String TEST_MESSAGE = "Test Message"; protected T exceptionContext; - protected static class ObjectWithFaultyToString implements Serializable { - - private static final long serialVersionUID = 3495843995332310458L; - + protected static class ObjectWithFaultyToString { @Override public String toString() { throw new RuntimeException("Crap"); @@ -167,4 +165,12 @@ public abstract class AbstractExceptionContextTest e assertEquals("test Poorly written obj", entries.get(4).getKey()); assertEquals("test2", entries.get(5).getKey()); } + + public void testJavaSerialization() { + exceptionContext.setContextValue("test Poorly written obj", "serializable replacement"); + + @SuppressWarnings("unchecked") + T clone = (T)SerializationUtils.deserialize(SerializationUtils.serialize(exceptionContext)); + assertEquals(exceptionContext.getFormattedExceptionMessage(null), clone.getFormattedExceptionMessage(null)); + } }