diff --git a/mute-idiom/etc/mute-idiom.png b/mute-idiom/etc/mute-idiom.png new file mode 100644 index 000000000..626cec827 Binary files /dev/null and b/mute-idiom/etc/mute-idiom.png differ diff --git a/mute-idiom/etc/mute-idiom.ucls b/mute-idiom/etc/mute-idiom.ucls new file mode 100644 index 000000000..25a7bfefb --- /dev/null +++ b/mute-idiom/etc/mute-idiom.ucls @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/App.java b/mute-idiom/src/main/java/com/iluwatar/mute/App.java index 36da1c4f9..a0eb815fd 100644 --- a/mute-idiom/src/main/java/com/iluwatar/mute/App.java +++ b/mute-idiom/src/main/java/com/iluwatar/mute/App.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.mute; import static org.mockito.Mockito.doThrow; @@ -28,33 +29,56 @@ import static org.mockito.Mockito.mock; import java.io.ByteArrayOutputStream; import java.sql.Connection; import java.sql.SQLException; +import java.sql.Statement; +/** + * Mute pattern is utilized when we need to suppress an exception due to an API flaw or in + * situation when all we can do to handle the exception is to log it. + * This pattern should not be used everywhere. It is very important to logically handle the + * exceptions in a system, but some situations like the ones described above require this pattern, + * so that we don't need to repeat + *
+ * 
+ *   try {
+ *     // code that may throwing exception we need to ignore or may never be thrown
+ *   } catch (Exception ex) {
+ *     // ignore by logging or throw error if unexpected exception occurs
+ *   }
+ * 
+ * 
every time we need to ignore an exception. + * + */ public class App { - public static void main(String[] args) { - + /** + * Program entry point. + * + * @param args command line args. + * @throws Exception if any exception occurs + */ + public static void main(String[] args) throws Exception { + useOfLoggedMute(); - + useOfMute(); } /* - * Typically used when the API declares some exception but cannot do so. Usually a signature mistake. - * In this example out is not supposed to throw exception as it is a ByteArrayOutputStream. So we - * utilize mute, which will throw AssertionError if unexpected exception occurs. + * Typically used when the API declares some exception but cannot do so. Usually a + * signature mistake.In this example out is not supposed to throw exception as it is a + * ByteArrayOutputStream. So we utilize mute, which will throw AssertionError if unexpected + * exception occurs. */ private static void useOfMute() { ByteArrayOutputStream out = new ByteArrayOutputStream(); Mute.mute(() -> out.write("Hello".getBytes())); } - private static void useOfLoggedMute() { + private static void useOfLoggedMute() throws SQLException { Connection connection = null; try { connection = openConnection(); readStuff(connection); - } catch (SQLException ex) { - ex.printStackTrace(); } finally { closeConnection(connection); } @@ -64,14 +88,12 @@ public class App { * All we can do while failed close of connection is to log it. */ private static void closeConnection(Connection connection) { - if (connection != null) { - Mute.loggedMute(() -> connection.close()); - } + Mute.loggedMute(() -> connection.close()); } private static void readStuff(Connection connection) throws SQLException { - if (connection != null) { - connection.createStatement(); + try (Statement statement = connection.createStatement()) { + System.out.println("Read data from statement"); } } diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java b/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java index 7f99386f0..d1440636f 100644 --- a/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java +++ b/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.mute; /** @@ -32,5 +33,5 @@ public interface CheckedRunnable { * Same as {@link Runnable#run()} with a possibility of exception in execution. * @throws Exception if any exception occurs. */ - public void run() throws Exception; + void run() throws Exception; } diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java b/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java index 3e1ad2e2e..64169a8f5 100644 --- a/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java +++ b/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java @@ -29,6 +29,9 @@ import java.io.IOException; * A utility class that allows you to utilize mute idiom. */ public final class Mute { + + // The constructor is never meant to be called. + private Mute() {} /** * Executes the runnable and throws the exception occurred within a {@link AssertionError}. diff --git a/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java b/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java index 8079c6acb..2d4e344a9 100644 --- a/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java +++ b/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java @@ -9,7 +9,7 @@ import org.junit.Test; public class AppTest { @Test - public void test() { + public void test() throws Exception { App.main(null); } } diff --git a/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java b/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java index b0016a331..58cbfe893 100644 --- a/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java +++ b/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java @@ -20,6 +20,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package com.iluwatar.mute; import static org.junit.Assert.assertTrue; @@ -38,6 +39,11 @@ public class MuteTest { @Rule public ExpectedException exception = ExpectedException.none(); + @Test + public void muteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() { + Mute.mute(() -> methodNotThrowingAnyException()); + } + @Test public void muteShouldRethrowUnexpectedExceptionAsAssertionError() throws Exception { exception.expect(AssertionError.class); @@ -46,8 +52,9 @@ public class MuteTest { Mute.mute(() -> methodThrowingException()); } - private void methodThrowingException() throws Exception { - throw new Exception(MESSAGE); + @Test + public void loggedMuteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() { + Mute.loggedMute(() -> methodNotThrowingAnyException()); } @Test @@ -59,4 +66,13 @@ public class MuteTest { assertTrue(new String(stream.toByteArray()).contains(MESSAGE)); } + + + private void methodNotThrowingAnyException() { + System.out.println("Executed successfully"); + } + + private void methodThrowingException() throws Exception { + throw new Exception(MESSAGE); + } } diff --git a/pom.xml b/pom.xml index 555844660..57d030756 100644 --- a/pom.xml +++ b/pom.xml @@ -123,6 +123,7 @@ feature-toggle value-object monad + mute-idiom