From e307e733c2641ba1d2e55acee29a587b8a9c08eb Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Sat, 10 Oct 2020 19:03:29 +0530 Subject: [PATCH 1/3] Added patch to throw exception in afterExecute and beforeExecute parts --- .../engine/DataBuilderExecutionListener.java | 8 ++++++++ .../engine/DataBuilderFrameworkException.java | 4 +++- .../engine/MultiThreadedDataFlowExecutor.java | 14 ++++++++++++-- .../OptimizedMultiThreadedDataFlowExecutor.java | 14 ++++++++++++-- .../engine/SimpleDataFlowExecutor.java | 15 ++++++++++++--- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/flipkart/databuilderframework/engine/DataBuilderExecutionListener.java b/src/main/java/com/flipkart/databuilderframework/engine/DataBuilderExecutionListener.java index 66e683b..9061c2d 100644 --- a/src/main/java/com/flipkart/databuilderframework/engine/DataBuilderExecutionListener.java +++ b/src/main/java/com/flipkart/databuilderframework/engine/DataBuilderExecutionListener.java @@ -41,4 +41,12 @@ default void postProcessing(DataFlowInstance dataFlowInstance, default boolean shouldThrowException() { return false; } + + default boolean shouldThrowExceptionInBeforeExecute() { + return false; + } + + default boolean shouldThrowExceptionInAfterExecute() { + return false; + } } diff --git a/src/main/java/com/flipkart/databuilderframework/engine/DataBuilderFrameworkException.java b/src/main/java/com/flipkart/databuilderframework/engine/DataBuilderFrameworkException.java index 8374772..41cf02d 100644 --- a/src/main/java/com/flipkart/databuilderframework/engine/DataBuilderFrameworkException.java +++ b/src/main/java/com/flipkart/databuilderframework/engine/DataBuilderFrameworkException.java @@ -22,7 +22,9 @@ public static enum ErrorCode { NO_BUILDER_FOUND_FOR_NAME, INSTANTIATION_FAILURE, BUILDER_RESOLUTION_CONFLICT_FOR_DATA, - BUILDER_EXECUTION_ERROR + BUILDER_EXECUTION_ERROR, + BUILDER_PRE_EXECUTION_ERROR, + BUILDER_POST_EXECUTION_ERROR } private final ErrorCode errorCode; diff --git a/src/main/java/com/flipkart/databuilderframework/engine/MultiThreadedDataFlowExecutor.java b/src/main/java/com/flipkart/databuilderframework/engine/MultiThreadedDataFlowExecutor.java index 002bd4d..48c2e3e 100644 --- a/src/main/java/com/flipkart/databuilderframework/engine/MultiThreadedDataFlowExecutor.java +++ b/src/main/java/com/flipkart/databuilderframework/engine/MultiThreadedDataFlowExecutor.java @@ -224,7 +224,12 @@ public DataContainer call() throws Exception { try { listener.beforeExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData); } catch (Throwable t) { - logger.error("Error running pre-execution execution listener: ", t); + final String errorMessage = "Error running pre-execution execution listener: "; + logger.error(errorMessage, t); + if (listener.shouldThrowExceptionInBeforeExecute()) { + throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_PRE_EXECUTION_ERROR, + errorMessage + t.getMessage(), t); + } } } try { @@ -236,7 +241,12 @@ public DataContainer call() throws Exception { try { listener.afterExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData, response); } catch (Throwable t) { - logger.error("Error running post-execution listener: ", t); + final String errorMessage = "Error running post-execution execution listener: "; + logger.error(errorMessage, t); + if (listener.shouldThrowExceptionInAfterExecute()) { + throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_POST_EXECUTION_ERROR, + errorMessage + t.getMessage(), t); + } } } if(null != response) { diff --git a/src/main/java/com/flipkart/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java b/src/main/java/com/flipkart/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java index be07d25..5fa6746 100644 --- a/src/main/java/com/flipkart/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java +++ b/src/main/java/com/flipkart/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java @@ -243,7 +243,12 @@ public DataContainer call() throws Exception { try { listener.beforeExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData); } catch (Throwable t) { - logger.error("Error running pre-execution execution listener: ", t); + final String errorMessage = "Error running pre-execution execution listener: "; + logger.error(errorMessage, t); + if (listener.shouldThrowExceptionInBeforeExecute()) { + throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_PRE_EXECUTION_ERROR, + errorMessage + t.getMessage(), t); + } } } try { @@ -255,7 +260,12 @@ public DataContainer call() throws Exception { try { listener.afterExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData, response); } catch (Throwable t) { - logger.error("Error running post-execution listener: ", t); + final String errorMessage = "Error running post-execution execution listener: "; + logger.error(errorMessage, t); + if (listener.shouldThrowExceptionInAfterExecute()) { + throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_POST_EXECUTION_ERROR, + errorMessage + t.getMessage(), t); + } } } if(null != response) { diff --git a/src/main/java/com/flipkart/databuilderframework/engine/SimpleDataFlowExecutor.java b/src/main/java/com/flipkart/databuilderframework/engine/SimpleDataFlowExecutor.java index 37ee2fe..6ff5edf 100644 --- a/src/main/java/com/flipkart/databuilderframework/engine/SimpleDataFlowExecutor.java +++ b/src/main/java/com/flipkart/databuilderframework/engine/SimpleDataFlowExecutor.java @@ -67,7 +67,12 @@ protected DataExecutionResponse run(DataBuilderContext dataBuilderContext, try { listener.beforeExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData); } catch (Throwable t) { - logger.error("Error running pre-execution execution listener: ", t); + final String errorMessage = "Error running pre-execution execution listener: "; + logger.error(errorMessage, t); + if (listener.shouldThrowExceptionInBeforeExecute()) { + throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_PRE_EXECUTION_ERROR, + errorMessage + t.getMessage(), t); + } } } try { @@ -86,13 +91,17 @@ protected DataExecutionResponse run(DataBuilderContext dataBuilderContext, newlyGeneratedData.add(response.getData()); } } - //logger.debug("Ran " + builderMeta.getName()); processedBuilders.add(builderMeta); for (DataBuilderExecutionListener listener : dataBuilderExecutionListener) { try { listener.afterExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData, response); } catch (Throwable t) { - logger.error("Error running post-execution listener: ", t); + final String errorMessage = "Error running post-execution execution listener: "; + logger.error(errorMessage, t); + if (listener.shouldThrowExceptionInAfterExecute()) { + throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_POST_EXECUTION_ERROR, + errorMessage + t.getMessage(), t); + } } } From 48a79c638bd5f28b9a1d9bfc91f31b057c8d46ca Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Sun, 25 Oct 2020 15:48:41 +0530 Subject: [PATCH 2/3] moved common code to util class --- pom.xml | 2 +- .../engine/MultiThreadedDataFlowExecutor.java | 15 ++------- ...ptimizedMultiThreadedDataFlowExecutor.java | 15 ++------- .../engine/SimpleDataFlowExecutor.java | 15 ++------- .../engine/util/DataBuilderExceptionUtil.java | 32 +++++++++++++++++++ 5 files changed, 42 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/flipkart/databuilderframework/engine/util/DataBuilderExceptionUtil.java diff --git a/pom.xml b/pom.xml index 116150a..9316adc 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> com.flipkart.databuilderframework - 0.5.8 + 0.5.8-PATCH-SNAPSHOT 4.0.0 databuilderframework diff --git a/src/main/java/com/flipkart/databuilderframework/engine/MultiThreadedDataFlowExecutor.java b/src/main/java/com/flipkart/databuilderframework/engine/MultiThreadedDataFlowExecutor.java index 48c2e3e..ac4aeda 100644 --- a/src/main/java/com/flipkart/databuilderframework/engine/MultiThreadedDataFlowExecutor.java +++ b/src/main/java/com/flipkart/databuilderframework/engine/MultiThreadedDataFlowExecutor.java @@ -1,5 +1,6 @@ package com.flipkart.databuilderframework.engine; +import com.flipkart.databuilderframework.engine.util.DataBuilderExceptionUtil; import com.flipkart.databuilderframework.model.*; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; @@ -224,12 +225,7 @@ public DataContainer call() throws Exception { try { listener.beforeExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData); } catch (Throwable t) { - final String errorMessage = "Error running pre-execution execution listener: "; - logger.error(errorMessage, t); - if (listener.shouldThrowExceptionInBeforeExecute()) { - throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_PRE_EXECUTION_ERROR, - errorMessage + t.getMessage(), t); - } + DataBuilderExceptionUtil.handleExceptionInBeforeExecute(listener, logger, t); } } try { @@ -241,12 +237,7 @@ public DataContainer call() throws Exception { try { listener.afterExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData, response); } catch (Throwable t) { - final String errorMessage = "Error running post-execution execution listener: "; - logger.error(errorMessage, t); - if (listener.shouldThrowExceptionInAfterExecute()) { - throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_POST_EXECUTION_ERROR, - errorMessage + t.getMessage(), t); - } + DataBuilderExceptionUtil.handleExceptionInAfterExecute(listener, logger, t); } } if(null != response) { diff --git a/src/main/java/com/flipkart/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java b/src/main/java/com/flipkart/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java index 5fa6746..8c21852 100644 --- a/src/main/java/com/flipkart/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java +++ b/src/main/java/com/flipkart/databuilderframework/engine/OptimizedMultiThreadedDataFlowExecutor.java @@ -1,5 +1,6 @@ package com.flipkart.databuilderframework.engine; +import com.flipkart.databuilderframework.engine.util.DataBuilderExceptionUtil; import com.flipkart.databuilderframework.model.*; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; @@ -243,12 +244,7 @@ public DataContainer call() throws Exception { try { listener.beforeExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData); } catch (Throwable t) { - final String errorMessage = "Error running pre-execution execution listener: "; - logger.error(errorMessage, t); - if (listener.shouldThrowExceptionInBeforeExecute()) { - throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_PRE_EXECUTION_ERROR, - errorMessage + t.getMessage(), t); - } + DataBuilderExceptionUtil.handleExceptionInBeforeExecute(listener, logger, t); } } try { @@ -260,12 +256,7 @@ public DataContainer call() throws Exception { try { listener.afterExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData, response); } catch (Throwable t) { - final String errorMessage = "Error running post-execution execution listener: "; - logger.error(errorMessage, t); - if (listener.shouldThrowExceptionInAfterExecute()) { - throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_POST_EXECUTION_ERROR, - errorMessage + t.getMessage(), t); - } + DataBuilderExceptionUtil.handleExceptionInAfterExecute(listener, logger, t); } } if(null != response) { diff --git a/src/main/java/com/flipkart/databuilderframework/engine/SimpleDataFlowExecutor.java b/src/main/java/com/flipkart/databuilderframework/engine/SimpleDataFlowExecutor.java index 6ff5edf..410e879 100644 --- a/src/main/java/com/flipkart/databuilderframework/engine/SimpleDataFlowExecutor.java +++ b/src/main/java/com/flipkart/databuilderframework/engine/SimpleDataFlowExecutor.java @@ -1,5 +1,6 @@ package com.flipkart.databuilderframework.engine; +import com.flipkart.databuilderframework.engine.util.DataBuilderExceptionUtil; import com.flipkart.databuilderframework.model.*; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; @@ -67,12 +68,7 @@ protected DataExecutionResponse run(DataBuilderContext dataBuilderContext, try { listener.beforeExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData); } catch (Throwable t) { - final String errorMessage = "Error running pre-execution execution listener: "; - logger.error(errorMessage, t); - if (listener.shouldThrowExceptionInBeforeExecute()) { - throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_PRE_EXECUTION_ERROR, - errorMessage + t.getMessage(), t); - } + DataBuilderExceptionUtil.handleExceptionInBeforeExecute(listener, logger, t); } } try { @@ -96,12 +92,7 @@ protected DataExecutionResponse run(DataBuilderContext dataBuilderContext, try { listener.afterExecute(dataBuilderContext, dataFlowInstance, builderMeta, dataDelta, responseData, response); } catch (Throwable t) { - final String errorMessage = "Error running post-execution execution listener: "; - logger.error(errorMessage, t); - if (listener.shouldThrowExceptionInAfterExecute()) { - throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_POST_EXECUTION_ERROR, - errorMessage + t.getMessage(), t); - } + DataBuilderExceptionUtil.handleExceptionInAfterExecute(listener, logger, t); } } diff --git a/src/main/java/com/flipkart/databuilderframework/engine/util/DataBuilderExceptionUtil.java b/src/main/java/com/flipkart/databuilderframework/engine/util/DataBuilderExceptionUtil.java new file mode 100644 index 0000000..efcebab --- /dev/null +++ b/src/main/java/com/flipkart/databuilderframework/engine/util/DataBuilderExceptionUtil.java @@ -0,0 +1,32 @@ +package com.flipkart.databuilderframework.engine.util; + +import com.flipkart.databuilderframework.engine.DataBuilderExecutionListener; +import com.flipkart.databuilderframework.engine.DataBuilderFrameworkException; +import lombok.experimental.UtilityClass; +import org.slf4j.Logger; + +@UtilityClass +public class DataBuilderExceptionUtil { + + public static void handleExceptionInBeforeExecute(final DataBuilderExecutionListener listener, + final Logger logger, + final Throwable t) throws DataBuilderFrameworkException { + final String errorMessage = "Error running pre-execution execution listener: "; + logger.error(errorMessage, t); + if (listener.shouldThrowExceptionInBeforeExecute()) { + throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_PRE_EXECUTION_ERROR, + errorMessage + t.getMessage(), t); + } + } + + public static void handleExceptionInAfterExecute(final DataBuilderExecutionListener listener, + final Logger logger, + final Throwable t) throws DataBuilderFrameworkException { + final String errorMessage = "Error running post-execution execution listener: "; + logger.error(errorMessage, t); + if (listener.shouldThrowExceptionInAfterExecute()) { + throw new DataBuilderFrameworkException(DataBuilderFrameworkException.ErrorCode.BUILDER_POST_EXECUTION_ERROR, + errorMessage + t.getMessage(), t); + } + } +} From b20cfeceddd8548589744a644770bad7054ab787 Mon Sep 17 00:00:00 2001 From: Deepak Kumar Singh Date: Wed, 4 Nov 2020 00:14:25 +0530 Subject: [PATCH 3/3] added tests --- .../MultiThreadedDataFlowExecutorTest.java | 139 +++++++++++++- .../SimpleDataFlowExecutorTest.java | 170 ++++++++++++++++++ 2 files changed, 300 insertions(+), 9 deletions(-) create mode 100644 src/test/java/com/flipkart/databuilderframework/SimpleDataFlowExecutorTest.java diff --git a/src/test/java/com/flipkart/databuilderframework/MultiThreadedDataFlowExecutorTest.java b/src/test/java/com/flipkart/databuilderframework/MultiThreadedDataFlowExecutorTest.java index a029aec..92e414e 100644 --- a/src/test/java/com/flipkart/databuilderframework/MultiThreadedDataFlowExecutorTest.java +++ b/src/test/java/com/flipkart/databuilderframework/MultiThreadedDataFlowExecutorTest.java @@ -173,6 +173,99 @@ public void postProcessing(DataFlowInstance dataFlowInstance, } } + private static class TestListenerBeforeExecutionErrorWithExceptionThrown implements DataBuilderExecutionListener { + + @Override + public void preProcessing(DataFlowInstance dataFlowInstance, + DataDelta dataDelta) { + log.info("Being called for: " + dataFlowInstance.getId()); + } + + @Override + public void beforeExecute(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, Map prevResponses) throws Exception { + throw new Exception("Blah blah"); + } + + @Override + public void afterExecute(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, Map prevResponses, Data currentResponse) { + log.info("{} called for: {}", builderToBeApplied.getName(), dataFlowInstance.getId()); + } + + @Override + public void afterException(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, + Map prevResponses, Throwable frameworkException) { + log.info("{} called for: {}", builderToBeApplied.getName(), dataFlowInstance.getId()); + } + + @Override + public void postProcessing(DataFlowInstance dataFlowInstance, + DataDelta dataDelta, DataExecutionResponse response, + Throwable frameworkException) { + log.info("Being called for: {}", dataFlowInstance.getId()); + } + + @Override + public boolean shouldThrowExceptionInBeforeExecute() { + return true; + } + } + + private static class TestListenerAfterExecutionErrorWithExceptionThrown implements DataBuilderExecutionListener { + + @Override + public void preProcessing(DataFlowInstance dataFlowInstance, + DataDelta dataDelta) { + log.info("Being called for: {}", dataFlowInstance.getId()); + } + + + @Override + public void beforeExecute(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, Map prevResponses) { + log.info("{} called for: {}", builderToBeApplied.getName(), dataFlowInstance.getId()); + } + + @Override + public void afterExecute(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, Map prevResponses, Data currentResponse) throws Exception { + throw new Exception("Blah blah"); + } + + @Override + public void afterException(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, + Map prevResponses, Throwable frameworkException) { + log.info("{} called for: {}", builderToBeApplied.getName(), dataFlowInstance.getId()); + } + + @Override + public void postProcessing(DataFlowInstance dataFlowInstance, + DataDelta dataDelta, DataExecutionResponse response, + Throwable frameworkException) { + log.info("Being called for: {}", dataFlowInstance.getId()); + } + + @Override + public boolean shouldThrowExceptionInAfterExecute() { + return true; + } + } + private DataBuilderMetadataManager dataBuilderMetadataManager = new DataBuilderMetadataManager(); private DataFlowExecutor executor = new MultiThreadedDataFlowExecutor( new InstantiatingDataBuilderFactory(dataBuilderMetadataManager), @@ -196,30 +289,22 @@ public void setup() throws Exception { .withAnnotatedDataBuilder(TestBuilderError.class) .withTargetData("Y") .build(); - executor.registerExecutionListener(new TestListener()); - executor.registerExecutionListener(new TestListenerBeforeExecutionError()); - executor.registerExecutionListener(new TestListenerAfterExecutionError()); - executor.registerExecutionListener(new TestListenerAfterExceptionError()); dataFlowValidationError = new DataFlowBuilder() .withAnnotatedDataBuilder(TestBuilderDataValidationError.class) .withTargetData("Y") .build(); - executor.registerExecutionListener(new TestListener()); - executor.registerExecutionListener(new TestListenerBeforeExecutionError()); - executor.registerExecutionListener(new TestListenerAfterExecutionError()); - executor.registerExecutionListener(new TestListenerAfterExceptionError()); dataFlowValidationErrorWithPartialData = new DataFlowBuilder() .withAnnotatedDataBuilder(TestBuilderA.class) .withAnnotatedDataBuilder(TestBuilderDataValidationError.class) .withTargetData("Y") .build(); + executor.registerExecutionListener(new TestListener()); executor.registerExecutionListener(new TestListenerBeforeExecutionError()); executor.registerExecutionListener(new TestListenerAfterExecutionError()); executor.registerExecutionListener(new TestListenerAfterExceptionError()); - } @Test @@ -351,4 +436,40 @@ public void testRunValidationErrorWithPartialData() throws Exception { fail("Should have thrown exception"); } } + + @Test + public void testRunSingleStepWithExceptionThrownInBeforeExecuteInExecutionListener() throws Exception { + DataFlowInstance dataFlowInstance = new DataFlowInstance(); + dataFlowInstance.setId("testflow"); + dataFlowInstance.setDataFlow(dataFlow); + executor.registerExecutionListener(new TestListenerBeforeExecutionErrorWithExceptionThrown()); + + DataDelta dataDelta = new DataDelta(Lists.newArrayList( + new TestDataA("Hello"), new TestDataB("World"), + new TestDataD("this"), new TestDataG("Hmmm"))); + try { + executor.run(dataFlowInstance, dataDelta); + fail("It should not come here."); + } catch (DataBuilderFrameworkException exception) { + Assert.assertEquals(DataBuilderFrameworkException.ErrorCode.BUILDER_EXECUTION_ERROR, exception.getErrorCode()); + } + } + + @Test + public void testRunSingleStepWithExceptionThrownInAfterExecuteInExecutionListener() throws Exception { + DataFlowInstance dataFlowInstance = new DataFlowInstance(); + dataFlowInstance.setId("testflow"); + dataFlowInstance.setDataFlow(dataFlow); + executor.registerExecutionListener(new TestListenerAfterExecutionErrorWithExceptionThrown()); + + DataDelta dataDelta = new DataDelta(Lists.newArrayList( + new TestDataA("Hello"), new TestDataB("World"), + new TestDataD("this"), new TestDataG("Hmmm"))); + try { + executor.run(dataFlowInstance, dataDelta); + fail("It should not come here."); + } catch (DataBuilderFrameworkException exception) { + Assert.assertEquals(DataBuilderFrameworkException.ErrorCode.BUILDER_EXECUTION_ERROR, exception.getErrorCode()); + } + } } diff --git a/src/test/java/com/flipkart/databuilderframework/SimpleDataFlowExecutorTest.java b/src/test/java/com/flipkart/databuilderframework/SimpleDataFlowExecutorTest.java new file mode 100644 index 0000000..0528361 --- /dev/null +++ b/src/test/java/com/flipkart/databuilderframework/SimpleDataFlowExecutorTest.java @@ -0,0 +1,170 @@ +package com.flipkart.databuilderframework; + +import com.flipkart.databuilderframework.engine.DataBuilderContext; +import com.flipkart.databuilderframework.engine.DataBuilderExecutionListener; +import com.flipkart.databuilderframework.engine.DataBuilderFrameworkException; +import com.flipkart.databuilderframework.engine.DataFlowBuilder; +import com.flipkart.databuilderframework.engine.DataFlowExecutor; +import com.flipkart.databuilderframework.engine.SimpleDataFlowExecutor; +import com.flipkart.databuilderframework.engine.impl.MixedDataBuilderFactory; +import com.flipkart.databuilderframework.model.Data; +import com.flipkart.databuilderframework.model.DataBuilderMeta; +import com.flipkart.databuilderframework.model.DataDelta; +import com.flipkart.databuilderframework.model.DataExecutionResponse; +import com.flipkart.databuilderframework.model.DataFlow; +import com.flipkart.databuilderframework.model.DataFlowInstance; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Map; + +import static org.junit.Assert.fail; + +@Slf4j +public class SimpleDataFlowExecutorTest { + + private DataFlowExecutor executor = new SimpleDataFlowExecutor(new MixedDataBuilderFactory()); + private DataFlow dataFlow = new DataFlow(); + + @Before + public void setup() throws Exception { + dataFlow = new DataFlowBuilder() + .withAnnotatedDataBuilder(TestBuilderA.class) + .withAnnotatedDataBuilder(TestBuilderB.class) + .withAnnotatedDataBuilder(TestBuilderC.class) + .withTargetData("F") + .build(); + } + + private static class TestListenerBeforeExecutionErrorWithExceptionThrown implements DataBuilderExecutionListener { + + @Override + public void preProcessing(DataFlowInstance dataFlowInstance, + DataDelta dataDelta) { + log.info("Being called for: " + dataFlowInstance.getId()); + } + + @Override + public void beforeExecute(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, Map prevResponses) throws Exception { + throw new Exception("Blah blah"); + } + + @Override + public void afterExecute(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, Map prevResponses, Data currentResponse) { + log.info("{} called for: {}", builderToBeApplied.getName(), dataFlowInstance.getId()); + } + + @Override + public void afterException(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, + Map prevResponses, Throwable frameworkException) { + log.info("{} called for: {}", builderToBeApplied.getName(), dataFlowInstance.getId()); + } + + @Override + public void postProcessing(DataFlowInstance dataFlowInstance, + DataDelta dataDelta, DataExecutionResponse response, + Throwable frameworkException) { + log.info("Being called for: {}", dataFlowInstance.getId()); + } + + @Override + public boolean shouldThrowExceptionInBeforeExecute() { + return true; + } + } + + private static class TestListenerAfterExecutionErrorWithExceptionThrown implements DataBuilderExecutionListener { + + @Override + public void preProcessing(DataFlowInstance dataFlowInstance, + DataDelta dataDelta) { + log.info("Being called for: {}", dataFlowInstance.getId()); + } + + + @Override + public void beforeExecute(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, Map prevResponses) { + log.info("{} called for: {}", builderToBeApplied.getName(), dataFlowInstance.getId()); + } + + @Override + public void afterExecute(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, Map prevResponses, Data currentResponse) throws Exception { + throw new Exception("Blah blah"); + } + + @Override + public void afterException(DataBuilderContext builderContext, + DataFlowInstance dataFlowInstance, + DataBuilderMeta builderToBeApplied, + DataDelta dataDelta, + Map prevResponses, Throwable frameworkException) { + log.info("{} called for: {}", builderToBeApplied.getName(), dataFlowInstance.getId()); + } + + @Override + public void postProcessing(DataFlowInstance dataFlowInstance, + DataDelta dataDelta, DataExecutionResponse response, + Throwable frameworkException) { + log.info("Being called for: {}", dataFlowInstance.getId()); + } + + @Override + public boolean shouldThrowExceptionInAfterExecute() { + return true; + } + } + + @Test + public void testRunSingleStepWithExceptionThrownInBeforeExecuteInExecutionListener() throws Exception { + DataFlowInstance dataFlowInstance = new DataFlowInstance(); + dataFlowInstance.setId("testflow"); + dataFlowInstance.setDataFlow(dataFlow); + + executor.registerExecutionListener(new TestListenerBeforeExecutionErrorWithExceptionThrown()); + + DataDelta dataDelta = new DataDelta(Lists.newArrayList( + new TestDataA("Hello"), new TestDataB("World"), new TestDataD("this"))); + try { + executor.run(dataFlowInstance, dataDelta); + fail("It should not come here."); + } catch (DataBuilderFrameworkException exception) { + Assert.assertEquals(DataBuilderFrameworkException.ErrorCode.BUILDER_PRE_EXECUTION_ERROR, exception.getErrorCode()); + } + } + + @Test + public void testRunSingleStepWithExceptionThrownInAfterExecuteInExecutionListener() throws Exception { + DataFlowInstance dataFlowInstance = new DataFlowInstance(); + dataFlowInstance.setId("testflow"); + dataFlowInstance.setDataFlow(dataFlow); + + executor.registerExecutionListener(new TestListenerAfterExecutionErrorWithExceptionThrown()); + + DataDelta dataDelta = new DataDelta(Lists.newArrayList( + new TestDataA("Hello"), new TestDataB("World"), new TestDataD("this"))); + try { + executor.run(dataFlowInstance, dataDelta); + fail("It should not come here."); + } catch (DataBuilderFrameworkException exception) { + Assert.assertEquals(DataBuilderFrameworkException.ErrorCode.BUILDER_EXECUTION_ERROR, exception.getErrorCode()); + } + } +}