From 2a9d96f493542156cc6281b114d5757cfe7da280 Mon Sep 17 00:00:00 2001 From: Maros Date: Wed, 2 Oct 2013 13:35:00 +0200 Subject: [PATCH] Exception handler able to catch getter and setter exceptions Exception handler able to catch getter and setter exceptions (2nd try). --- .../de/danielbechler/diff/BeanDiffer.java | 5 ++-- .../diff/BeanPropertyComparisonDelegator.java | 16 +++++++++++-- .../de/danielbechler/diff/DifferFactory.java | 2 +- .../diff/accessor/PropertyAccessor.java | 4 +--- .../exception/DefaultExceptionListener.java | 19 ++++++++++++--- .../accessor/exception/ExceptionListener.java | 24 ++++++++++++++++++- .../exception/PropertyWriteException.java | 9 ++++++- .../danielbechler/diff/BeanDifferShould.java | 11 +++++---- ...BeanPropertyComparisonDelegatorShould.java | 10 ++++---- .../diff/DifferFactoryShould.java | 4 ++++ 10 files changed, 83 insertions(+), 21 deletions(-) diff --git a/src/main/java/de/danielbechler/diff/BeanDiffer.java b/src/main/java/de/danielbechler/diff/BeanDiffer.java index 8977b390..8c9783ed 100644 --- a/src/main/java/de/danielbechler/diff/BeanDiffer.java +++ b/src/main/java/de/danielbechler/diff/BeanDiffer.java @@ -17,6 +17,7 @@ package de.danielbechler.diff; import de.danielbechler.diff.accessor.*; +import de.danielbechler.diff.accessor.exception.ExceptionListener; import de.danielbechler.diff.introspect.*; import de.danielbechler.diff.node.*; import de.danielbechler.util.*; @@ -34,11 +35,11 @@ final class BeanDiffer implements Differ private BeanPropertyComparisonDelegator beanPropertyComparisonDelegator; private DefaultNodeFactory defaultNodeFactory = new DefaultNodeFactory(); - public BeanDiffer(final DifferDelegator delegator, final NodeInspector nodeInspector) + public BeanDiffer(final DifferDelegator delegator, final NodeInspector nodeInspector, final ExceptionListener exceptionListener) { Assert.notNull(delegator, "delegator"); Assert.notNull(nodeInspector, "configuration"); - this.beanPropertyComparisonDelegator = new BeanPropertyComparisonDelegator(delegator, nodeInspector); + this.beanPropertyComparisonDelegator = new BeanPropertyComparisonDelegator(delegator, nodeInspector, exceptionListener); this.nodeInspector = nodeInspector; } diff --git a/src/main/java/de/danielbechler/diff/BeanPropertyComparisonDelegator.java b/src/main/java/de/danielbechler/diff/BeanPropertyComparisonDelegator.java index 02238fea..33ce7fd7 100644 --- a/src/main/java/de/danielbechler/diff/BeanPropertyComparisonDelegator.java +++ b/src/main/java/de/danielbechler/diff/BeanPropertyComparisonDelegator.java @@ -17,6 +17,9 @@ package de.danielbechler.diff; import de.danielbechler.diff.accessor.*; +import de.danielbechler.diff.accessor.exception.ExceptionListener; +import de.danielbechler.diff.accessor.exception.PropertyReadException; +import de.danielbechler.diff.accessor.exception.PropertyWriteException; import de.danielbechler.diff.node.*; import de.danielbechler.util.*; @@ -26,14 +29,17 @@ class BeanPropertyComparisonDelegator private final DifferDelegator delegator; private final NodeInspector nodeInspector; private PropertyNodeFactory propertyNodeFactory = new PropertyNodeFactory(); + private final ExceptionListener exceptionListener; - public BeanPropertyComparisonDelegator(final DifferDelegator delegator, final NodeInspector nodeInspector) + public BeanPropertyComparisonDelegator(final DifferDelegator delegator, final NodeInspector nodeInspector, final ExceptionListener exceptionListener) { Assert.notNull(delegator, "delegator"); Assert.notNull(nodeInspector, "nodeInspector"); + Assert.notNull(exceptionListener, "exceptionListener"); this.delegator = delegator; this.nodeInspector = nodeInspector; + this.exceptionListener = exceptionListener; } public Node compare(final Node beanNode, final Instances beanInstances, final Accessor propertyAccessor) @@ -51,7 +57,13 @@ public Node compare(final Node beanNode, final Instances beanInstances, final Ac } else { - return delegator.delegate(beanNode, beanInstances.access(propertyAccessor)); + try { + return delegator.delegate(beanNode, beanInstances.access(propertyAccessor)); + } catch(PropertyReadException e) { + return exceptionListener.onPropertyReadException(e, propertyNode); + } catch(PropertyWriteException e) { + return exceptionListener.onPropertyWriteException(e, propertyNode); + } } } diff --git a/src/main/java/de/danielbechler/diff/DifferFactory.java b/src/main/java/de/danielbechler/diff/DifferFactory.java index 0e7fea90..c3484ea7 100644 --- a/src/main/java/de/danielbechler/diff/DifferFactory.java +++ b/src/main/java/de/danielbechler/diff/DifferFactory.java @@ -50,7 +50,7 @@ else if (Map.class.isAssignableFrom(type)) } else { - return new BeanDiffer(delegator, configuration); + return new BeanDiffer(delegator, configuration, configuration.getExceptionListener()); } } diff --git a/src/main/java/de/danielbechler/diff/accessor/PropertyAccessor.java b/src/main/java/de/danielbechler/diff/accessor/PropertyAccessor.java index 42a16588..6126f6e2 100644 --- a/src/main/java/de/danielbechler/diff/accessor/PropertyAccessor.java +++ b/src/main/java/de/danielbechler/diff/accessor/PropertyAccessor.java @@ -86,9 +86,7 @@ private void invokeWriteMethod(final Object target, final Object value) } catch (Exception e) { - logFailedSet(value); - - final PropertyWriteException ex = new PropertyWriteException(e); + final PropertyWriteException ex = new PropertyWriteException(e, value); ex.setPropertyName(propertyName); ex.setTargetType(getType()); throw ex; diff --git a/src/main/java/de/danielbechler/diff/accessor/exception/DefaultExceptionListener.java b/src/main/java/de/danielbechler/diff/accessor/exception/DefaultExceptionListener.java index a7131fd0..775375f5 100644 --- a/src/main/java/de/danielbechler/diff/accessor/exception/DefaultExceptionListener.java +++ b/src/main/java/de/danielbechler/diff/accessor/exception/DefaultExceptionListener.java @@ -1,7 +1,9 @@ package de.danielbechler.diff.accessor.exception; -import de.danielbechler.diff.node.*; -import org.slf4j.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.danielbechler.diff.node.Node; /** * Handler for recoverable exceptional states which logs the warning or info messages into log. The exception @@ -19,4 +21,15 @@ public void onCircularReferenceException(final Node node) + "this instance along the current path."; logger.warn(message, node.getPropertyPath()); } -} + + public Node onPropertyWriteException(final PropertyWriteException ex, final Node propertyNode) + { + logger.info("Couldn't set new value '{}' for property '{}'", ex.getNewValue(), ex.getPropertyName()); + throw ex; + } + + public Node onPropertyReadException(final PropertyReadException ex, final Node propertyNode) + { + throw ex; + } +} \ No newline at end of file diff --git a/src/main/java/de/danielbechler/diff/accessor/exception/ExceptionListener.java b/src/main/java/de/danielbechler/diff/accessor/exception/ExceptionListener.java index 6dae5f25..49d63bed 100644 --- a/src/main/java/de/danielbechler/diff/accessor/exception/ExceptionListener.java +++ b/src/main/java/de/danielbechler/diff/accessor/exception/ExceptionListener.java @@ -14,4 +14,26 @@ public interface ExceptionListener * @param node The node which has been detected to cause a circular reference. */ void onCircularReferenceException(Node node); -} + + /** + * Called when PropertyWriteException happens. + * + * @param e + * PropertyWriteException itself. + * @param propertyNode + * Node of the property that we were unable to write to. + * @return Resulting node. + */ + Node onPropertyWriteException(PropertyWriteException e, Node propertyNode); + + /** + * Called when PropertyReadException happens. + * + * @param ex + * The PropertyReadException itself. + * @param propertyNode + * Node of the property that we were unable to read. + * @return Node as a result of wrong read. + */ + Node onPropertyReadException(PropertyReadException ex, Node propertyNode); +} \ No newline at end of file diff --git a/src/main/java/de/danielbechler/diff/accessor/exception/PropertyWriteException.java b/src/main/java/de/danielbechler/diff/accessor/exception/PropertyWriteException.java index 15ff4361..a52991bc 100644 --- a/src/main/java/de/danielbechler/diff/accessor/exception/PropertyWriteException.java +++ b/src/main/java/de/danielbechler/diff/accessor/exception/PropertyWriteException.java @@ -20,10 +20,12 @@ public class PropertyWriteException extends PropertyException { private static final long serialVersionUID = 1L; + private final Object newValue; - public PropertyWriteException(final Throwable cause) + public PropertyWriteException(final Throwable cause, final Object newValue) { super(cause); + this.newValue = newValue; } @Override @@ -31,4 +33,9 @@ public String getMessage() { return "Error while invoking write method. "; } + + public Object getNewValue() + { + return newValue; + } } diff --git a/src/test/java/de/danielbechler/diff/BeanDifferShould.java b/src/test/java/de/danielbechler/diff/BeanDifferShould.java index 5719e987..b8dcc3cf 100644 --- a/src/test/java/de/danielbechler/diff/BeanDifferShould.java +++ b/src/test/java/de/danielbechler/diff/BeanDifferShould.java @@ -17,10 +17,12 @@ package de.danielbechler.diff; import de.danielbechler.diff.accessor.*; +import de.danielbechler.diff.accessor.exception.DefaultExceptionListener; import de.danielbechler.diff.introspect.*; import de.danielbechler.diff.mock.*; import de.danielbechler.diff.node.*; import de.danielbechler.diff.path.*; + import org.mockito.Mock; import org.testng.annotations.*; @@ -51,7 +53,7 @@ public void setUp() { initMocks(this); configuration = new Configuration(); - differ = new BeanDiffer(delegator, configuration); + differ = new BeanDiffer(delegator, configuration, configuration.getExceptionListener()); differ.setIntrospector(introspector); } @@ -165,12 +167,13 @@ public void compare_bean_via_introspection_and_delegate_comparison_of_properties when(defaultNodeFactory.createNode(Node.ROOT, beanInstances)).thenReturn(beanNode); when(configuration.isIntrospectible(beanNode)).thenReturn(true); + when(configuration.getExceptionListener()).thenReturn(new DefaultExceptionListener()); doReturn(beanType).when(beanInstances).getType(); when(introspector.introspect(beanType)).thenReturn(asList(propertyAccessor)); when(beanPropertyComparer.compare(beanNode, beanInstances, propertyAccessor)).thenReturn(propertyNode); when(configuration.isReturnable(propertyNode)).thenReturn(true); - differ = new BeanDiffer(delegator, configuration); + differ = new BeanDiffer(delegator, configuration, configuration.getExceptionListener()); differ.setIntrospector(introspector); differ.setBeanPropertyComparisonDelegator(beanPropertyComparer); differ.setDefaultNodeFactory(defaultNodeFactory); @@ -183,12 +186,12 @@ public void compare_bean_via_introspection_and_delegate_comparison_of_properties @Test(expectedExceptions = IllegalArgumentException.class) public void fail_construction_without_delegator() { - new BeanDiffer(null, configuration); + new BeanDiffer(null, configuration, configuration.getExceptionListener()); } @Test(expectedExceptions = IllegalArgumentException.class) public void fail_construction_without_configuration() { - new BeanDiffer(delegator, null); + new BeanDiffer(delegator, null, new DefaultExceptionListener()); } } diff --git a/src/test/java/de/danielbechler/diff/BeanPropertyComparisonDelegatorShould.java b/src/test/java/de/danielbechler/diff/BeanPropertyComparisonDelegatorShould.java index 0723116d..26d95b76 100644 --- a/src/test/java/de/danielbechler/diff/BeanPropertyComparisonDelegatorShould.java +++ b/src/test/java/de/danielbechler/diff/BeanPropertyComparisonDelegatorShould.java @@ -17,7 +17,9 @@ package de.danielbechler.diff; import de.danielbechler.diff.accessor.*; +import de.danielbechler.diff.accessor.exception.DefaultExceptionListener; import de.danielbechler.diff.node.*; + import org.mockito.Mock; import org.testng.annotations.*; @@ -42,8 +44,8 @@ public class BeanPropertyComparisonDelegatorShould protected void setUp() throws Exception { initMocks(this); - - beanPropertyComparisonDelegator = new BeanPropertyComparisonDelegator(delegator, configuration); + when(configuration.getExceptionListener()).thenReturn(new DefaultExceptionListener()); + beanPropertyComparisonDelegator = new BeanPropertyComparisonDelegator(delegator, configuration, configuration.getExceptionListener()); beanPropertyComparisonDelegator.setPropertyNodeFactory(propertyNodeFactory); } @@ -94,13 +96,13 @@ public void delegate_property_comparison() @Test(expectedExceptions = IllegalArgumentException.class) public void fail_if_constructed_without_delegator() { - new BeanPropertyComparisonDelegator(null, configuration); + new BeanPropertyComparisonDelegator(null, configuration, configuration.getExceptionListener()); } @Test(expectedExceptions = IllegalArgumentException.class) public void fail_if_constructed_without_configuration() { - new BeanPropertyComparisonDelegator(delegator, null); + new BeanPropertyComparisonDelegator(delegator, null, new DefaultExceptionListener()); } @Test(expectedExceptions = IllegalArgumentException.class) diff --git a/src/test/java/de/danielbechler/diff/DifferFactoryShould.java b/src/test/java/de/danielbechler/diff/DifferFactoryShould.java index 9fb3b4b2..f3a7ba38 100644 --- a/src/test/java/de/danielbechler/diff/DifferFactoryShould.java +++ b/src/test/java/de/danielbechler/diff/DifferFactoryShould.java @@ -16,13 +16,16 @@ package de.danielbechler.diff; +import de.danielbechler.diff.accessor.exception.DefaultExceptionListener; import de.danielbechler.diff.mock.*; + import org.mockito.Mock; import org.testng.annotations.*; import java.util.*; import static org.fest.assertions.api.Assertions.*; +import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.*; /** @author Daniel Bechler */ @@ -38,6 +41,7 @@ public class DifferFactoryShould public void initDifferFactory() { initMocks(this); + when(configuration.getExceptionListener()).thenReturn(new DefaultExceptionListener()); differFactory = new DifferFactory(configuration); }