diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/ExceptionUtils.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/ExceptionUtils.java index 1448846992..1232391506 100644 --- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/ExceptionUtils.java +++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/ExceptionUtils.java @@ -1,17 +1,18 @@ + package org.alfresco.module.org_alfresco_module_rm.test.util; -/* - * #%L - * Alfresco Records Management Module - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% * This file is part of the Alfresco software. * * If the software was purchased under a paid Alfresco license, the terms of * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: - * + * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -23,7 +24,7 @@ package org.alfresco.module.org_alfresco_module_rm.test.util; * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . + * along with Alfresco. If not, see . * #L% */ @@ -173,5 +174,73 @@ public class ExceptionUtils { throw new UnexpectedThrowableException(expected, thrownByCode); } + } + + /** + * Helper method to work around the difficulties of working with lambdas and checked exceptions. + * Use as follows: + *
+     *     expectedException(WebScriptException.class, () ->
+     *         // "Wash away" any checked exceptions in the inner code block.
+     *         smuggleCheckedExceptions( () -> methodThrowsException())
+     *     );
+     * 
+ * @param code a block of code which is declared to throw a checked exception. + * @param the return type of the block of code. + * @param the type of the checked exception. + * @return the value returned by the block of code. + * @throws SmuggledException if the code block threw an exception of type T. + */ + public static R smuggleCheckedExceptions(final ThrowingSupplier code) + { + try + { + return code.get(); + } + catch (RuntimeException e) + { + throw e; + } + catch (Exception e) + { + throw new SmuggledException(e); + } } -} + + /** + * Equivalent to `java.util.function.Supplier` but its method declares that it + * throws checked exceptions. + * + * @param The result type of this supplier. + * @param The exception type declared to be thrown by this supplier. + */ + @FunctionalInterface + public interface ThrowingSupplier + { + /** Gets the value */ + R get() throws T; + } + + /** + * A wrapper for checked exceptions so that they can be handled as unchecked exceptions, namely by not requiring + * try/catch blocks etc. + *

+ * This type is expected to be most useful when handling Java 8 lambdas containing code which throws checked + * exceptions. + */ + public static class SmuggledException extends RuntimeException + { + private static final long serialVersionUID = -606404592461576013L; + private final Exception e; + + public SmuggledException(Exception e) + { + this.e = e; + } + + public Exception getCheckedException() + { + return this.e; + } + } +} diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/ExceptionUtilsUsageExamplesUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/ExceptionUtilsUsageExamplesUnitTest.java index 0001ccfadb..570ea8e33f 100644 --- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/ExceptionUtilsUsageExamplesUnitTest.java +++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/ExceptionUtilsUsageExamplesUnitTest.java @@ -2,11 +2,11 @@ package org.alfresco.module.org_alfresco_module_rm.test.util; /* - * #%L - * Alfresco Records Management Module - * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited - * %% + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% * This file is part of the Alfresco software. * * If the software was purchased under a paid Alfresco license, the terms of @@ -24,18 +24,20 @@ package org.alfresco.module.org_alfresco_module_rm.test.util; * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . + * along with Alfresco. If not, see . * #L% */ import org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.MissingThrowableException; +import org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.SmuggledException; import org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.UnexpectedThrowableException; import org.junit.Test; import java.io.IOException; import static org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.expectedException; +import static org.alfresco.module.org_alfresco_module_rm.test.util.ExceptionUtils.smuggleCheckedExceptions; import static org.junit.Assert.*; /** @@ -110,5 +112,20 @@ public class ExceptionUtilsUsageExamplesUnitTest onlySideEffectsHere("hello"); return null; }); + } + + // If you use lambdas that throw checked exceptions, the standard Java 8 types are insufficient. + @Test public void smuggleCheckedExceptionsShouldHideCheckedExceptionsInAnUncheckedException() + { + SmuggledException e = expectedException(SmuggledException.class, () -> smuggleCheckedExceptions(() -> methodThrowsException())); + + assertEquals(Exception.class, e.getCheckedException().getClass()); + assertEquals("Checked", e.getCheckedException().getMessage()); } -} + + /** This method declares that it throws `java.lang.Exception`. */ + private Object methodThrowsException() throws Exception + { + throw new Exception("Checked"); + } +}