From 9b1d47ff4ec5cf2f17e801c967e3321c258e90f7 Mon Sep 17 00:00:00 2001 From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com> Date: Thu, 24 Aug 2023 12:04:54 -0700 Subject: [PATCH 1/7] BAEL-6865, Aggregate Runtime Exceptions in Java Streams Changed method names --- core-java-modules/core-java-streams-5/pom.xml | 6 + .../baeldung/aggregateEx/CustomMapper.java | 19 ++ .../aggregateEx/ExceptionCollector.java | 41 ++++ .../entity/ExceptionAggregator.java | 27 +++ .../baeldung/aggregateEx/entity/Result.java | 27 +++ .../AggregateExceptionHandlerUnitTest.java | 180 ++++++++++++++++++ 6 files changed, 300 insertions(+) create mode 100644 core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java create mode 100644 core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/ExceptionCollector.java create mode 100644 core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java create mode 100644 core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java create mode 100644 core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java diff --git a/core-java-modules/core-java-streams-5/pom.xml b/core-java-modules/core-java-streams-5/pom.xml index d1f8af6461..abbdb504c1 100644 --- a/core-java-modules/core-java-streams-5/pom.xml +++ b/core-java-modules/core-java-streams-5/pom.xml @@ -38,6 +38,11 @@ 3.12.0 test + + io.vavr + vavr + ${vavr.version} + @@ -67,6 +72,7 @@ 3.1 12 12 + 0.10.2 \ No newline at end of file diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java new file mode 100644 index 0000000000..114a812fdc --- /dev/null +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java @@ -0,0 +1,19 @@ +package com.baeldung.aggregateEx; + +import com.baeldung.aggregateEx.entity.Result; + +import java.util.function.Function; + +public class CustomMapper { + public static Function> mapper(Function func) { + return arg -> { + Result result; + try { + result = new Result(func.apply(arg)); + } catch (Exception e) { + result = new Result(e); + } + return result; + }; + } +} diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/ExceptionCollector.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/ExceptionCollector.java new file mode 100644 index 0000000000..5472724b7c --- /dev/null +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/ExceptionCollector.java @@ -0,0 +1,41 @@ +package com.baeldung.aggregateEx; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collector; + +public class ExceptionCollector { + private final List results = new ArrayList<>(); + private final List exceptions = new ArrayList<>(); + + private ExceptionCollector() { + } + + public static Collector> of(Function mapper) { + return Collector.of( + ExceptionCollector::new, + (collector, item) -> { + try { + R result = mapper.apply(item); + collector.results.add(result); + } catch (Exception e) { + collector.exceptions.add(e); + } + }, + (left, right) -> { + left.results.addAll(right.results); + left.exceptions.addAll(right.exceptions); + return left; + } + ); + } + + public List getResults() { + return results; + } + + public List getExceptions() { + return exceptions; + } +} diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java new file mode 100644 index 0000000000..b4c38db2cf --- /dev/null +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java @@ -0,0 +1,27 @@ +package com.baeldung.aggregateEx.entity; + +import java.util.ArrayList; +import java.util.List; + +public class ExceptionAggregator extends RuntimeException { + private List exceptions; + + public ExceptionAggregator(String message) { + super(message); + exceptions = new ArrayList<>(); + } + + public List getExceptions() { + return exceptions; + } + + public Exception addException(Exception e) { + this.addSuppressed(e); + exceptions.add(e); + return e; + } + + public void addExceptions(List exceptions) { + exceptions.forEach(this::addException); + } +} diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java new file mode 100644 index 0000000000..287cccd060 --- /dev/null +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java @@ -0,0 +1,27 @@ +package com.baeldung.aggregateEx.entity; + +import java.util.Optional; + +public class Result { + private Optional result; + private Optional exception; + + public Result(R result) { + this.result = Optional.of(result); + this.exception = Optional.empty(); + } + + public Result(Exception exception) { + this.exception = Optional.of(exception); + this.result = Optional.empty(); + } + + public Optional getResult() { + return result; + } + + public Optional getException() { + return exception; + } + +} diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java new file mode 100644 index 0000000000..952ec376ac --- /dev/null +++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java @@ -0,0 +1,180 @@ +package com.baeldung.aggregateEx; + +import com.baeldung.aggregateEx.entity.ExceptionAggregator; +import com.baeldung.aggregateEx.entity.Result; + +import static org.junit.Assert.*; + +import io.vavr.control.Either; +import io.vavr.control.Try; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class AggregateExceptionHandlerUnitTest { + + private static RuntimeException process(String str) { + try { + Integer.parseInt(str); + return null; + } catch (NumberFormatException e) { + return new RuntimeException(e); + } + } + + private static Object transform(String str) { + try { + return (Integer.parseInt(str)); + } catch (NumberFormatException e) { + return new RuntimeException(e); + } + } + + @Test + public void givenExtractedMethod_whenFoundNonInt_thenAggregateException() { + String[] strings = {"1", "2", "3", "a", "b", "c"}; + RuntimeException runEx = Arrays.stream(strings) + .map(AggregateExceptionHandlerUnitTest::process) + .filter(Objects::nonNull) + .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { + o1.addSuppressed(o2); + return o1; + }); + assertEquals("Errors Occurred", runEx.getMessage()); + assertEquals(3, runEx.getSuppressed().length); + } + + @Test + public void givenTryCatchInPipeline_whenFoundNonInts_thenAggregateException() { + String[] strings = {"1", "2", "3", "a", "b", "c"}; + RuntimeException runEx = Arrays.stream(strings) + .map(str -> { + try { + Integer.parseInt(str); + return null; + } catch (NumberFormatException e) { + return new RuntimeException(e); + } + }) + .filter(Objects::nonNull) + .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { + o1.addSuppressed(o2); + return o1; + }); + assertEquals("Errors Occurred", runEx.getMessage()); + assertEquals(3, runEx.getSuppressed().length); + } + + @Test + public void whenFoundNonInts_thenAggregateExceptionAndReturnOutput() { + String[] strings = {"1", "2", "3", "a", "b", "c"}; + Map resultMap = Arrays.stream(strings) + .map(AggregateExceptionHandlerUnitTest::transform) + .collect(Collectors.partitioningBy(o -> o instanceof RuntimeException, Collectors.toList())); + RuntimeException ex = null; + if (resultMap.containsKey(Boolean.TRUE)) { + List exs = (List) resultMap.get(Boolean.TRUE); + ex = exs.stream() + .reduce( + new RuntimeException("Errors Occurred"), (o1, o2) -> { + o1.addSuppressed(o2); + return o1; + }); + } + assertEquals("Errors Occurred", ex.getMessage()); + assertEquals(3, ex.getSuppressed().length); + } + + @Test + public void givenWrapFunction_whenFoundNonInts_thenAggregateException() throws ExceptionAggregator { + String[] strings = {"1", "2", "3", "a", "b", "c"}; + Map>> resultmap = Arrays.stream(strings) + .map(CustomMapper.mapper(Integer::parseInt)) + .collect(Collectors.partitioningBy(r -> r.getException().isEmpty(), Collectors.toList())); + + if (resultmap.containsKey(Boolean.FALSE)) { + List> resultList = resultmap.get(Boolean.FALSE); + List exceptionList = resultList.stream() + .map(opex -> opex.getException().get()) + .collect(Collectors.toList()); + + assertThrows(ExceptionAggregator.class, () -> handleExceptions(exceptionList)); + } + } + + private void handleExceptions(List exceptions) throws ExceptionAggregator { + ExceptionAggregator exceptionAggregator = new ExceptionAggregator("Errors occurred"); + exceptionAggregator.addExceptions(exceptions); + throw exceptionAggregator; + } + + @Test + public void givenExCollector_whenFoundNonInts_thenAggregateException() throws ExceptionAggregator { + String[] strings = {"1", "2", "3", "a", "b", "c"}; + ExceptionCollector exCollector = Arrays.stream(strings) + .collect(ExceptionCollector.of(Integer::parseInt)); + List output = exCollector.getResults(); + List runEx = exCollector.getExceptions(); + assertEquals(3, runEx.size()); + } + + private static Either processAndReturnEither(String str) { + Either either = null; + try { + either = Either.right(Integer.parseInt(str)); + } catch (NumberFormatException e) { + either = Either.left(new RuntimeException(e)); + } + return either; + } + + @Test + public void givenVavrEither_whenFoundNonInts_thenAggregateException() { + List strings = List.of("1", "2", "3", "a", "b", "c"); + Map>> map = strings.stream() + .map(str -> processAndReturnEither(str)) + .collect(Collectors.partitioningBy((t) -> t.isLeft(), Collectors.toList())); + + RuntimeException runEx = map.get(Boolean.TRUE) + .stream().map(either -> either.getLeft()) + .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { + o1.addSuppressed(o2); + return o1; + }); + assertEquals(3, runEx.getSuppressed().length); + } + + @Test + public void givenVavrTry_whenFoundNonInts_thenAggregateException() { + List strings = List.of("1", "2", "3", "a", "b", "c"); + Map>> map = strings.stream() + .map(str -> Try.of(() -> Integer.parseInt(str))) + .collect(Collectors.partitioningBy((t) -> t.isFailure(), Collectors.toList())); + Throwable runEx = map.get(Boolean.TRUE).stream() + .map(t -> t.getCause()) + .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { + o1.addSuppressed(o2); + return o1; + }); + assertEquals(3, runEx.getSuppressed().length); + } + + @Test + public void givenVavrEitherAndTry_whenFoundNonInts_thenAggregateException() { + List strings = List.of("1", "2", "3", "a", "b", "c"); + Map>> map = strings.stream() + .map(str -> Try.of(() -> Integer.parseInt(str)).toEither()) + .collect(Collectors.partitioningBy(Either::isLeft, Collectors.toList())); + Throwable runEx = map.get(Boolean.TRUE).stream() + .map(either -> either.getLeft()) + .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { + o1.addSuppressed(o2); + return o1; + }); + assertEquals(3, runEx.getSuppressed().length); + } +} From 63f511b9c607ac599d49773b4d613c6752246c07 Mon Sep 17 00:00:00 2001 From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com> Date: Fri, 25 Aug 2023 09:50:53 -0700 Subject: [PATCH 2/7] Update core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java removing extra parentheses Co-authored-by: Liam Williams --- .../baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java index 952ec376ac..20cce4440b 100644 --- a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java +++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java @@ -28,7 +28,7 @@ public class AggregateExceptionHandlerUnitTest { private static Object transform(String str) { try { - return (Integer.parseInt(str)); + return Integer.parseInt(str); } catch (NumberFormatException e) { return new RuntimeException(e); } From 5bf002e0fdf017c2e1b4384eadde496982fd1760 Mon Sep 17 00:00:00 2001 From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com> Date: Fri, 25 Aug 2023 10:35:47 -0700 Subject: [PATCH 3/7] BAEL-6865, taking care of review comments as part of PR-14653 --- .../baeldung/aggregateEx/CustomMapper.java | 6 +- .../AggregateExceptionHandlerUnitTest.java | 71 ++++++++++--------- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java index 114a812fdc..47b433a132 100644 --- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java @@ -7,13 +7,11 @@ import java.util.function.Function; public class CustomMapper { public static Function> mapper(Function func) { return arg -> { - Result result; try { - result = new Result(func.apply(arg)); + return new Result(func.apply(arg)); } catch (Exception e) { - result = new Result(e); + return new Result(e); } - return result; }; } } diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java index 952ec376ac..dff9dafbb7 100644 --- a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java +++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java @@ -2,9 +2,6 @@ package com.baeldung.aggregateEx; import com.baeldung.aggregateEx.entity.ExceptionAggregator; import com.baeldung.aggregateEx.entity.Result; - -import static org.junit.Assert.*; - import io.vavr.control.Either; import io.vavr.control.Try; import org.junit.Test; @@ -15,6 +12,8 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import static org.junit.Assert.*; + public class AggregateExceptionHandlerUnitTest { private static RuntimeException process(String str) { @@ -28,14 +27,14 @@ public class AggregateExceptionHandlerUnitTest { private static Object transform(String str) { try { - return (Integer.parseInt(str)); + return Integer.parseInt(str); } catch (NumberFormatException e) { return new RuntimeException(e); } } @Test - public void givenExtractedMethod_whenFoundNonInt_thenAggregateException() { + public void givenExtractedMethod_whenFoundNonInt_thenSuppressExIntoRuntimeEx() { String[] strings = {"1", "2", "3", "a", "b", "c"}; RuntimeException runEx = Arrays.stream(strings) .map(AggregateExceptionHandlerUnitTest::process) @@ -49,7 +48,7 @@ public class AggregateExceptionHandlerUnitTest { } @Test - public void givenTryCatchInPipeline_whenFoundNonInts_thenAggregateException() { + public void givenTryCatchInPipeline_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { String[] strings = {"1", "2", "3", "a", "b", "c"}; RuntimeException runEx = Arrays.stream(strings) .map(str -> { @@ -70,40 +69,44 @@ public class AggregateExceptionHandlerUnitTest { } @Test - public void whenFoundNonInts_thenAggregateExceptionAndReturnOutput() { + public void givenExtractedMethodReturnOutputAndEx_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { String[] strings = {"1", "2", "3", "a", "b", "c"}; Map resultMap = Arrays.stream(strings) .map(AggregateExceptionHandlerUnitTest::transform) .collect(Collectors.partitioningBy(o -> o instanceof RuntimeException, Collectors.toList())); + RuntimeException ex = null; - if (resultMap.containsKey(Boolean.TRUE)) { - List exs = (List) resultMap.get(Boolean.TRUE); - ex = exs.stream() - .reduce( - new RuntimeException("Errors Occurred"), (o1, o2) -> { - o1.addSuppressed(o2); - return o1; - }); - } + + assertTrue(resultMap.containsKey(Boolean.TRUE)); + + List exs = (List) resultMap.get(Boolean.TRUE); + ex = exs.stream() + .reduce( + new RuntimeException("Errors Occurred"), (o1, o2) -> { + o1.addSuppressed(o2); + return o1; + }); + assertEquals("Errors Occurred", ex.getMessage()); assertEquals(3, ex.getSuppressed().length); } @Test - public void givenWrapFunction_whenFoundNonInts_thenAggregateException() throws ExceptionAggregator { + public void givenWrapFunction_whenFoundNonInts_thenUseExAggregator() throws ExceptionAggregator { String[] strings = {"1", "2", "3", "a", "b", "c"}; Map>> resultmap = Arrays.stream(strings) .map(CustomMapper.mapper(Integer::parseInt)) .collect(Collectors.partitioningBy(r -> r.getException().isEmpty(), Collectors.toList())); - if (resultmap.containsKey(Boolean.FALSE)) { - List> resultList = resultmap.get(Boolean.FALSE); - List exceptionList = resultList.stream() - .map(opex -> opex.getException().get()) - .collect(Collectors.toList()); + assertTrue(resultmap.containsKey(Boolean.TRUE)); + + List> resultList = resultmap.get(Boolean.FALSE); + List exceptionList = resultList.stream() + .map(opex -> opex.getException().get()) + .collect(Collectors.toList()); + + assertThrows(ExceptionAggregator.class, () -> handleExceptions(exceptionList)); - assertThrows(ExceptionAggregator.class, () -> handleExceptions(exceptionList)); - } } private void handleExceptions(List exceptions) throws ExceptionAggregator { @@ -113,7 +116,7 @@ public class AggregateExceptionHandlerUnitTest { } @Test - public void givenExCollector_whenFoundNonInts_thenAggregateException() throws ExceptionAggregator { + public void givenExCollector_whenFoundNonInts_thenAggregateExInCustomCollector() throws ExceptionAggregator { String[] strings = {"1", "2", "3", "a", "b", "c"}; ExceptionCollector exCollector = Arrays.stream(strings) .collect(ExceptionCollector.of(Integer::parseInt)); @@ -123,21 +126,21 @@ public class AggregateExceptionHandlerUnitTest { } private static Either processAndReturnEither(String str) { - Either either = null; try { - either = Either.right(Integer.parseInt(str)); + return Either.right(Integer.parseInt(str)); } catch (NumberFormatException e) { - either = Either.left(new RuntimeException(e)); + return Either.left(new RuntimeException(e)); } - return either; } @Test - public void givenVavrEither_whenFoundNonInts_thenAggregateException() { + public void givenVavrEither_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { List strings = List.of("1", "2", "3", "a", "b", "c"); Map>> map = strings.stream() .map(str -> processAndReturnEither(str)) - .collect(Collectors.partitioningBy((t) -> t.isLeft(), Collectors.toList())); + .collect(Collectors.partitioningBy(t -> t.isLeft(), Collectors.toList())); + + assertTrue(map.containsKey(Boolean.TRUE)); RuntimeException runEx = map.get(Boolean.TRUE) .stream().map(either -> either.getLeft()) @@ -149,11 +152,11 @@ public class AggregateExceptionHandlerUnitTest { } @Test - public void givenVavrTry_whenFoundNonInts_thenAggregateException() { + public void givenVavrTry_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { List strings = List.of("1", "2", "3", "a", "b", "c"); Map>> map = strings.stream() .map(str -> Try.of(() -> Integer.parseInt(str))) - .collect(Collectors.partitioningBy((t) -> t.isFailure(), Collectors.toList())); + .collect(Collectors.partitioningBy(t -> t.isFailure(), Collectors.toList())); Throwable runEx = map.get(Boolean.TRUE).stream() .map(t -> t.getCause()) .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { @@ -164,7 +167,7 @@ public class AggregateExceptionHandlerUnitTest { } @Test - public void givenVavrEitherAndTry_whenFoundNonInts_thenAggregateException() { + public void givenVavrEitherAndTry_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { List strings = List.of("1", "2", "3", "a", "b", "c"); Map>> map = strings.stream() .map(str -> Try.of(() -> Integer.parseInt(str)).toEither()) From 2b88d3e646a7d8be3bcf091417713367d821ed5b Mon Sep 17 00:00:00 2001 From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com> Date: Mon, 28 Aug 2023 10:40:06 -0700 Subject: [PATCH 4/7] BAEL-6865, implemented review comments --- ...ionCollector.java => CustomCollector.java} | 21 +- .../baeldung/aggregateEx/CustomMapper.java | 2 +- .../entity/ExceptionAggregator.java | 8 +- .../baeldung/aggregateEx/entity/Result.java | 9 +- .../AggregateExceptionHandlerUnitTest.java | 220 ++++++++---------- 5 files changed, 117 insertions(+), 143 deletions(-) rename core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/{ExceptionCollector.java => CustomCollector.java} (56%) diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/ExceptionCollector.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomCollector.java similarity index 56% rename from core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/ExceptionCollector.java rename to core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomCollector.java index 5472724b7c..4e3c2679a1 100644 --- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/ExceptionCollector.java +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomCollector.java @@ -1,31 +1,34 @@ package com.baeldung.aggregateEx; +import com.baeldung.aggregateEx.entity.ExceptionAggregator; + import java.util.ArrayList; import java.util.List; import java.util.function.Function; import java.util.stream.Collector; -public class ExceptionCollector { +public class CustomCollector { private final List results = new ArrayList<>(); - private final List exceptions = new ArrayList<>(); + private final List exceptions = new ArrayList<>(); - private ExceptionCollector() { - } + private final ExceptionAggregator exceptionAggregator = new ExceptionAggregator("Exceptions occurred"); - public static Collector> of(Function mapper) { + public static Collector> of(Function mapper) { return Collector.of( - ExceptionCollector::new, + CustomCollector::new, (collector, item) -> { try { R result = mapper.apply(item); collector.results.add(result); } catch (Exception e) { collector.exceptions.add(e); + collector.exceptionAggregator.addException(e); } }, (left, right) -> { left.results.addAll(right.results); left.exceptions.addAll(right.exceptions); + left.exceptionAggregator.addExceptions(right.exceptions); return left; } ); @@ -35,7 +38,11 @@ public class ExceptionCollector { return results; } - public List getExceptions() { + public List getExceptions() { return exceptions; } + + public ExceptionAggregator getExceptionAggregator() { + return exceptionAggregator; + } } diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java index 47b433a132..2e4de3ac66 100644 --- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java @@ -5,7 +5,7 @@ import com.baeldung.aggregateEx.entity.Result; import java.util.function.Function; public class CustomMapper { - public static Function> mapper(Function func) { + public static Function> mapper(Function func) { return arg -> { try { return new Result(func.apply(arg)); diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java index b4c38db2cf..50e11ca33e 100644 --- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java @@ -4,24 +4,24 @@ import java.util.ArrayList; import java.util.List; public class ExceptionAggregator extends RuntimeException { - private List exceptions; + private List exceptions; public ExceptionAggregator(String message) { super(message); exceptions = new ArrayList<>(); } - public List getExceptions() { + public List getExceptions() { return exceptions; } - public Exception addException(Exception e) { + public Throwable addException(Throwable e) { this.addSuppressed(e); exceptions.add(e); return e; } - public void addExceptions(List exceptions) { + public void addExceptions(List exceptions) { exceptions.forEach(this::addException); } } diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java index 287cccd060..95823d0bc9 100644 --- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java @@ -2,16 +2,16 @@ package com.baeldung.aggregateEx.entity; import java.util.Optional; -public class Result { +public class Result { private Optional result; - private Optional exception; + private Optional exception; public Result(R result) { this.result = Optional.of(result); this.exception = Optional.empty(); } - public Result(Exception exception) { + public Result(E exception) { this.exception = Optional.of(exception); this.result = Optional.empty(); } @@ -20,8 +20,7 @@ public class Result { return result; } - public Optional getException() { + public Optional getException() { return exception; } - } diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java index dff9dafbb7..17a53f41f5 100644 --- a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java +++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java @@ -5,6 +5,8 @@ import com.baeldung.aggregateEx.entity.Result; import io.vavr.control.Either; import io.vavr.control.Try; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Arrays; import java.util.List; @@ -12,172 +14,138 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + public class AggregateExceptionHandlerUnitTest { - - private static RuntimeException process(String str) { - try { - Integer.parseInt(str); - return null; - } catch (NumberFormatException e) { - return new RuntimeException(e); - } - } - - private static Object transform(String str) { - try { - return Integer.parseInt(str); - } catch (NumberFormatException e) { - return new RuntimeException(e); - } - } + static Logger logger = LoggerFactory.getLogger(AggregateExceptionHandlerUnitTest.class); @Test - public void givenExtractedMethod_whenFoundNonInt_thenSuppressExIntoRuntimeEx() { + public void givenExtractedMethod_whenFoundEx_thenSuppressExIntoRuntimeEx() { String[] strings = {"1", "2", "3", "a", "b", "c"}; - RuntimeException runEx = Arrays.stream(strings) - .map(AggregateExceptionHandlerUnitTest::process) + Throwable runEx = Arrays.stream(strings) + .map(str -> callProcessThrowsExAndNoOutput(str)) .filter(Objects::nonNull) .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { o1.addSuppressed(o2); return o1; }); + processExceptions(runEx); assertEquals("Errors Occurred", runEx.getMessage()); assertEquals(3, runEx.getSuppressed().length); } - @Test - public void givenTryCatchInPipeline_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { + public void givenTryCatchInPipeline_whenFoundEx_thenSuppressExIntoRuntimeEx() { String[] strings = {"1", "2", "3", "a", "b", "c"}; - RuntimeException runEx = Arrays.stream(strings) - .map(str -> { + RuntimeException runEx = Arrays.stream(strings).map(str -> { try { - Integer.parseInt(str); + processThrowsExAndNoOutput(str); return null; - } catch (NumberFormatException e) { - return new RuntimeException(e); + } catch (RuntimeException e) { + return e; } - }) - .filter(Objects::nonNull) - .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { - o1.addSuppressed(o2); - return o1; - }); + }).filter(Objects::nonNull) + .collect(Collectors.collectingAndThen(Collectors.toList(), list -> { + RuntimeException runtimeException = new RuntimeException("Errors Occurred"); + list.forEach(runtimeException::addSuppressed); + return runtimeException; + })); + processExceptions(runEx); assertEquals("Errors Occurred", runEx.getMessage()); assertEquals(3, runEx.getSuppressed().length); } @Test - public void givenExtractedMethodReturnOutputAndEx_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { - String[] strings = {"1", "2", "3", "a", "b", "c"}; - Map resultMap = Arrays.stream(strings) - .map(AggregateExceptionHandlerUnitTest::transform) + public void givenProcessMethod_whenStreamResultHasExAndOutput_thenHandleExceptionListAndOutputList() { + List strings = List.of("1", "2", "3", "a", "b", "c"); + Map map = strings.stream() + .map(s -> processReturnsExAndOutput(s)) .collect(Collectors.partitioningBy(o -> o instanceof RuntimeException, Collectors.toList())); - - RuntimeException ex = null; - - assertTrue(resultMap.containsKey(Boolean.TRUE)); - - List exs = (List) resultMap.get(Boolean.TRUE); - ex = exs.stream() - .reduce( - new RuntimeException("Errors Occurred"), (o1, o2) -> { - o1.addSuppressed(o2); - return o1; - }); - - assertEquals("Errors Occurred", ex.getMessage()); - assertEquals(3, ex.getSuppressed().length); + assert(map.containsKey(Boolean.TRUE) && map.containsKey(Boolean.FALSE)); + handleExceptionsAndOutputs((List) map.get(Boolean.TRUE), (List)map.get(Boolean.FALSE)); } @Test - public void givenWrapFunction_whenFoundNonInts_thenUseExAggregator() throws ExceptionAggregator { - String[] strings = {"1", "2", "3", "a", "b", "c"}; - Map>> resultmap = Arrays.stream(strings) + public void givenCustomMapper_whenStreamResultHasExAndSuccess_thenHandleExceptionListAndOutputList() { + List strings = List.of("1", "2", "3", "a", "b", "c"); + strings.stream() .map(CustomMapper.mapper(Integer::parseInt)) - .collect(Collectors.partitioningBy(r -> r.getException().isEmpty(), Collectors.toList())); - - assertTrue(resultmap.containsKey(Boolean.TRUE)); - - List> resultList = resultmap.get(Boolean.FALSE); - List exceptionList = resultList.stream() - .map(opex -> opex.getException().get()) - .collect(Collectors.toList()); - - assertThrows(ExceptionAggregator.class, () -> handleExceptions(exceptionList)); - - } - - private void handleExceptions(List exceptions) throws ExceptionAggregator { - ExceptionAggregator exceptionAggregator = new ExceptionAggregator("Errors occurred"); - exceptionAggregator.addExceptions(exceptions); - throw exceptionAggregator; + .collect(Collectors.collectingAndThen(Collectors.toList(), list -> handleErrorsAndOutPutForResult(list))); } @Test - public void givenExCollector_whenFoundNonInts_thenAggregateExInCustomCollector() throws ExceptionAggregator { + public void givenCustomCollector_whenStreamResultHasExAndSuccess_thenHandleAggrExceptionAndResults() { String[] strings = {"1", "2", "3", "a", "b", "c"}; - ExceptionCollector exCollector = Arrays.stream(strings) - .collect(ExceptionCollector.of(Integer::parseInt)); - List output = exCollector.getResults(); - List runEx = exCollector.getExceptions(); - assertEquals(3, runEx.size()); + Arrays.stream(strings) + .collect(Collectors.collectingAndThen(CustomCollector.of(Integer::parseInt), col -> { + handleExAndResults(col.getExceptionAggregator(), col.getResults()); + return col; + })); } - private static Either processAndReturnEither(String str) { + @Test + public void givenVavrEitherAndTry_whenStreamResultHasExAndSuccess_thenHandleExceptionListAndOutputList() { + List strings = List.of("1", "2", "3", "a", "b", "c"); + strings.stream() + .map(str -> Try.of(() -> Integer.parseInt(str)).toEither()) + .collect(Collectors.collectingAndThen(Collectors.partitioningBy(Either::isLeft, Collectors.toList()), map -> { + handleErrorsAndOutPutForEither(map); + return map; + })); + } + + private static void processThrowsExAndNoOutput(String input) { + //return exception when input is "a", "b", "c" + if (input.matches("[a-c]")) { + throw new RuntimeException("Downstream method throws exception for " + input); + } + } + private static Throwable callProcessThrowsExAndNoOutput(String input) { try { - return Either.right(Integer.parseInt(str)); - } catch (NumberFormatException e) { - return Either.left(new RuntimeException(e)); + processThrowsExAndNoOutput(input); + return null; + } catch (RuntimeException e) { + return e; } } - @Test - public void givenVavrEither_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { - List strings = List.of("1", "2", "3", "a", "b", "c"); - Map>> map = strings.stream() - .map(str -> processAndReturnEither(str)) - .collect(Collectors.partitioningBy(t -> t.isLeft(), Collectors.toList())); - - assertTrue(map.containsKey(Boolean.TRUE)); - - RuntimeException runEx = map.get(Boolean.TRUE) - .stream().map(either -> either.getLeft()) - .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { - o1.addSuppressed(o2); - return o1; - }); - assertEquals(3, runEx.getSuppressed().length); + private static Object processReturnsExAndOutput(String input) { + logger.info("call a downstream method that returns an Integer"); + try { + return Integer.parseInt(input); + } catch (Exception e) { + return new RuntimeException("Exception in processWithReturnOutput for " + input, e); + } } - @Test - public void givenVavrTry_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { - List strings = List.of("1", "2", "3", "a", "b", "c"); - Map>> map = strings.stream() - .map(str -> Try.of(() -> Integer.parseInt(str))) - .collect(Collectors.partitioningBy(t -> t.isFailure(), Collectors.toList())); - Throwable runEx = map.get(Boolean.TRUE).stream() - .map(t -> t.getCause()) - .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { - o1.addSuppressed(o2); - return o1; - }); - assertEquals(3, runEx.getSuppressed().length); + private static void processExceptions(Throwable throwable) { + logger.error("Process Exception" + throwable.getMessage()); } - @Test - public void givenVavrEitherAndTry_whenFoundNonInts_thenSuppressExIntoRuntimeEx() { - List strings = List.of("1", "2", "3", "a", "b", "c"); - Map>> map = strings.stream() - .map(str -> Try.of(() -> Integer.parseInt(str)).toEither()) - .collect(Collectors.partitioningBy(Either::isLeft, Collectors.toList())); - Throwable runEx = map.get(Boolean.TRUE).stream() - .map(either -> either.getLeft()) - .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { - o1.addSuppressed(o2); - return o1; - }); - assertEquals(3, runEx.getSuppressed().length); + private static void handleExceptionsAndOutputs(List exs, List output) { + logger.info("handle exceptions and output"); } -} + + private static void handleExAndResults(ExceptionAggregator exAgg, List results ) { + logger.info("handle aggregated exceptions and results" + exAgg.getExceptions().size() + " " + results.size()); + } + + private static void handleErrorsAndOutPutForEither(Map>> map) { + logger.info("handle errors and output"); + map.get(Boolean.TRUE).forEach(either -> logger.error("Process Exception " + either.getLeft())); + + map.get(Boolean.FALSE).forEach(either -> logger.info("Process Result " + either.get())); + } + + private static String handleErrorsAndOutPutForResult(List> successAndErrors) { + logger.info("handle errors and output"); + successAndErrors.forEach(result -> { + if (result.getException().isPresent()) { + logger.error("Process Exception " + result.getException().get()); + } else { + logger.info("Process Result" + result.getResult()); + } + }); + return "Errors and Output Handled"; + } +} \ No newline at end of file From 2f309cff8636b40df58ef6c62a0aec1595f2883e Mon Sep 17 00:00:00 2001 From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com> Date: Tue, 29 Aug 2023 08:34:38 -0700 Subject: [PATCH 5/7] BAEL-6865, implemented review comments --- .../entity/ExceptionAggregator.java | 27 ---------- .../CustomCollector.java | 12 +---- .../CustomMapper.java | 4 +- .../entity/Result.java | 2 +- .../AggregateExceptionHandlerUnitTest.java | 53 +++++++++---------- 5 files changed, 30 insertions(+), 68 deletions(-) delete mode 100644 core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java rename core-java-modules/core-java-streams-5/src/main/java/com/baeldung/{aggregateEx => aggregateexception}/CustomCollector.java (71%) rename core-java-modules/core-java-streams-5/src/main/java/com/baeldung/{aggregateEx => aggregateexception}/CustomMapper.java (78%) rename core-java-modules/core-java-streams-5/src/main/java/com/baeldung/{aggregateEx => aggregateexception}/entity/Result.java (91%) rename core-java-modules/core-java-streams-5/src/test/java/com/baeldung/{aggregateEx => aggregateexception}/AggregateExceptionHandlerUnitTest.java (72%) diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java deleted file mode 100644 index 50e11ca33e..0000000000 --- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/ExceptionAggregator.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.aggregateEx.entity; - -import java.util.ArrayList; -import java.util.List; - -public class ExceptionAggregator extends RuntimeException { - private List exceptions; - - public ExceptionAggregator(String message) { - super(message); - exceptions = new ArrayList<>(); - } - - public List getExceptions() { - return exceptions; - } - - public Throwable addException(Throwable e) { - this.addSuppressed(e); - exceptions.add(e); - return e; - } - - public void addExceptions(List exceptions) { - exceptions.forEach(this::addException); - } -} diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomCollector.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateexception/CustomCollector.java similarity index 71% rename from core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomCollector.java rename to core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateexception/CustomCollector.java index 4e3c2679a1..dea3d3f44c 100644 --- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomCollector.java +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateexception/CustomCollector.java @@ -1,6 +1,4 @@ -package com.baeldung.aggregateEx; - -import com.baeldung.aggregateEx.entity.ExceptionAggregator; +package com.baeldung.aggregateexception; import java.util.ArrayList; import java.util.List; @@ -11,8 +9,6 @@ public class CustomCollector { private final List results = new ArrayList<>(); private final List exceptions = new ArrayList<>(); - private final ExceptionAggregator exceptionAggregator = new ExceptionAggregator("Exceptions occurred"); - public static Collector> of(Function mapper) { return Collector.of( CustomCollector::new, @@ -22,13 +18,11 @@ public class CustomCollector { collector.results.add(result); } catch (Exception e) { collector.exceptions.add(e); - collector.exceptionAggregator.addException(e); } }, (left, right) -> { left.results.addAll(right.results); left.exceptions.addAll(right.exceptions); - left.exceptionAggregator.addExceptions(right.exceptions); return left; } ); @@ -41,8 +35,4 @@ public class CustomCollector { public List getExceptions() { return exceptions; } - - public ExceptionAggregator getExceptionAggregator() { - return exceptionAggregator; - } } diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateexception/CustomMapper.java similarity index 78% rename from core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java rename to core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateexception/CustomMapper.java index 2e4de3ac66..920c963337 100644 --- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/CustomMapper.java +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateexception/CustomMapper.java @@ -1,6 +1,6 @@ -package com.baeldung.aggregateEx; +package com.baeldung.aggregateexception; -import com.baeldung.aggregateEx.entity.Result; +import com.baeldung.aggregateexception.entity.Result; import java.util.function.Function; diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateexception/entity/Result.java similarity index 91% rename from core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java rename to core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateexception/entity/Result.java index 95823d0bc9..b723c3e510 100644 --- a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateEx/entity/Result.java +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/aggregateexception/entity/Result.java @@ -1,4 +1,4 @@ -package com.baeldung.aggregateEx.entity; +package com.baeldung.aggregateexception.entity; import java.util.Optional; diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java similarity index 72% rename from core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java rename to core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java index 17a53f41f5..0a6a294f3a 100644 --- a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateEx/AggregateExceptionHandlerUnitTest.java +++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java @@ -1,7 +1,6 @@ -package com.baeldung.aggregateEx; +package com.baeldung.aggregateexception; -import com.baeldung.aggregateEx.entity.ExceptionAggregator; -import com.baeldung.aggregateEx.entity.Result; +import com.baeldung.aggregateexception.entity.Result; import io.vavr.control.Either; import io.vavr.control.Try; import org.junit.Test; @@ -18,12 +17,12 @@ import static org.junit.Assert.assertEquals; public class AggregateExceptionHandlerUnitTest { - static Logger logger = LoggerFactory.getLogger(AggregateExceptionHandlerUnitTest.class); + private static final Logger logger = LoggerFactory.getLogger(AggregateExceptionHandlerUnitTest.class); @Test public void givenExtractedMethod_whenFoundEx_thenSuppressExIntoRuntimeEx() { String[] strings = {"1", "2", "3", "a", "b", "c"}; - Throwable runEx = Arrays.stream(strings) + RuntimeException runEx = Arrays.stream(strings) .map(str -> callProcessThrowsExAndNoOutput(str)) .filter(Objects::nonNull) .reduce(new RuntimeException("Errors Occurred"), (o1, o2) -> { @@ -58,11 +57,13 @@ public class AggregateExceptionHandlerUnitTest { @Test public void givenProcessMethod_whenStreamResultHasExAndOutput_thenHandleExceptionListAndOutputList() { List strings = List.of("1", "2", "3", "a", "b", "c"); - Map map = strings.stream() + Map> map = strings.stream() .map(s -> processReturnsExAndOutput(s)) .collect(Collectors.partitioningBy(o -> o instanceof RuntimeException, Collectors.toList())); - assert(map.containsKey(Boolean.TRUE) && map.containsKey(Boolean.FALSE)); - handleExceptionsAndOutputs((List) map.get(Boolean.TRUE), (List)map.get(Boolean.FALSE)); + + List exceptions = map.getOrDefault(Boolean.TRUE, List.of()); + List results = map.getOrDefault(Boolean.FALSE, List.of()); + handleExceptionsAndOutputs(exceptions, results); } @Test @@ -70,17 +71,15 @@ public class AggregateExceptionHandlerUnitTest { List strings = List.of("1", "2", "3", "a", "b", "c"); strings.stream() .map(CustomMapper.mapper(Integer::parseInt)) - .collect(Collectors.collectingAndThen(Collectors.toList(), list -> handleErrorsAndOutPutForResult(list))); + .collect(Collectors.collectingAndThen(Collectors.toList(), list -> handleErrorsAndOutputForResult(list))); } @Test public void givenCustomCollector_whenStreamResultHasExAndSuccess_thenHandleAggrExceptionAndResults() { String[] strings = {"1", "2", "3", "a", "b", "c"}; Arrays.stream(strings) - .collect(Collectors.collectingAndThen(CustomCollector.of(Integer::parseInt), col -> { - handleExAndResults(col.getExceptionAggregator(), col.getResults()); - return col; - })); + .collect(Collectors.collectingAndThen(CustomCollector.of(Integer::parseInt), + col -> handleExAndResults(col.getExceptions(), col.getResults()))); } @Test @@ -88,19 +87,17 @@ public class AggregateExceptionHandlerUnitTest { List strings = List.of("1", "2", "3", "a", "b", "c"); strings.stream() .map(str -> Try.of(() -> Integer.parseInt(str)).toEither()) - .collect(Collectors.collectingAndThen(Collectors.partitioningBy(Either::isLeft, Collectors.toList()), map -> { - handleErrorsAndOutPutForEither(map); - return map; - })); + .collect(Collectors.collectingAndThen(Collectors.partitioningBy(Either::isLeft, Collectors.toList()) + , map -> handleErrorsAndOutputForEither(map))); } private static void processThrowsExAndNoOutput(String input) { - //return exception when input is "a", "b", "c" + //throw exception when input is "a", "b", "c" if (input.matches("[a-c]")) { throw new RuntimeException("Downstream method throws exception for " + input); } } - private static Throwable callProcessThrowsExAndNoOutput(String input) { + private static RuntimeException callProcessThrowsExAndNoOutput(String input) { try { processThrowsExAndNoOutput(input); return null; @@ -122,22 +119,24 @@ public class AggregateExceptionHandlerUnitTest { logger.error("Process Exception" + throwable.getMessage()); } - private static void handleExceptionsAndOutputs(List exs, List output) { - logger.info("handle exceptions and output"); + private static void handleExceptionsAndOutputs(List exs, List output) { + logger.info("number of exceptions " + exs.size() + " number of outputs " + output.size()); } - private static void handleExAndResults(ExceptionAggregator exAgg, List results ) { - logger.info("handle aggregated exceptions and results" + exAgg.getExceptions().size() + " " + results.size()); + private static String handleExAndResults(List ex, List results ) { + logger.info("handle aggregated exceptions and results" + ex.size() + " " + results.size()); + return "Exceptions and Results Handled"; } - private static void handleErrorsAndOutPutForEither(Map>> map) { + private static String handleErrorsAndOutputForEither(Map>> map) { logger.info("handle errors and output"); - map.get(Boolean.TRUE).forEach(either -> logger.error("Process Exception " + either.getLeft())); + map.getOrDefault(Boolean.TRUE, List.of()).forEach(either -> logger.error("Process Exception " + either.getLeft())); - map.get(Boolean.FALSE).forEach(either -> logger.info("Process Result " + either.get())); + map.getOrDefault(Boolean.FALSE, List.of()).forEach(either -> logger.info("Process Result " + either.get())); + return "Errors and Output Handled"; } - private static String handleErrorsAndOutPutForResult(List> successAndErrors) { + private static String handleErrorsAndOutputForResult(List> successAndErrors) { logger.info("handle errors and output"); successAndErrors.forEach(result -> { if (result.getException().isPresent()) { From bd869f214e21131b999e09e3c0813ff9ada0f03b Mon Sep 17 00:00:00 2001 From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com> Date: Tue, 29 Aug 2023 09:00:39 -0700 Subject: [PATCH 6/7] BAEL-6865, implemented review comments --- .../AggregateExceptionHandlerUnitTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java index 0a6a294f3a..8c19724b87 100644 --- a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java +++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java @@ -57,12 +57,12 @@ public class AggregateExceptionHandlerUnitTest { @Test public void givenProcessMethod_whenStreamResultHasExAndOutput_thenHandleExceptionListAndOutputList() { List strings = List.of("1", "2", "3", "a", "b", "c"); - Map> map = strings.stream() + Map map = strings.stream() .map(s -> processReturnsExAndOutput(s)) .collect(Collectors.partitioningBy(o -> o instanceof RuntimeException, Collectors.toList())); - List exceptions = map.getOrDefault(Boolean.TRUE, List.of()); - List results = map.getOrDefault(Boolean.FALSE, List.of()); + List exceptions = (List)map.getOrDefault(Boolean.TRUE, List.of()); + List results = (List)map.getOrDefault(Boolean.FALSE, List.of()); handleExceptionsAndOutputs(exceptions, results); } @@ -119,7 +119,7 @@ public class AggregateExceptionHandlerUnitTest { logger.error("Process Exception" + throwable.getMessage()); } - private static void handleExceptionsAndOutputs(List exs, List output) { + private static void handleExceptionsAndOutputs(List exs, List output) { logger.info("number of exceptions " + exs.size() + " number of outputs " + output.size()); } From 9e0223b28f73d50814e78b20cca12d35d1dea678 Mon Sep 17 00:00:00 2001 From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com> Date: Tue, 29 Aug 2023 20:16:37 -0700 Subject: [PATCH 7/7] BAEL-6865, implemented review comments --- .../AggregateExceptionHandlerUnitTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java index 8c19724b87..6410645d2a 100644 --- a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java +++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/aggregateexception/AggregateExceptionHandlerUnitTest.java @@ -87,8 +87,8 @@ public class AggregateExceptionHandlerUnitTest { List strings = List.of("1", "2", "3", "a", "b", "c"); strings.stream() .map(str -> Try.of(() -> Integer.parseInt(str)).toEither()) - .collect(Collectors.collectingAndThen(Collectors.partitioningBy(Either::isLeft, Collectors.toList()) - , map -> handleErrorsAndOutputForEither(map))); + .collect(Collectors.collectingAndThen(Collectors.partitioningBy(Either::isLeft, Collectors.toList()), + map -> handleErrorsAndOutputForEither(map))); } private static void processThrowsExAndNoOutput(String input) { @@ -142,7 +142,7 @@ public class AggregateExceptionHandlerUnitTest { if (result.getException().isPresent()) { logger.error("Process Exception " + result.getException().get()); } else { - logger.info("Process Result" + result.getResult()); + logger.info("Process Result" + result.getResult().get()); } }); return "Errors and Output Handled";