diff --git a/dao/src/main/java/com/iluwatar/dao/App.java b/dao/src/main/java/com/iluwatar/dao/App.java
index 3fa4b34d5..a63289ae9 100644
--- a/dao/src/main/java/com/iluwatar/dao/App.java
+++ b/dao/src/main/java/com/iluwatar/dao/App.java
@@ -20,49 +20,101 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
package com.iluwatar.dao;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Stream;
+
+import javax.sql.DataSource;
import org.apache.log4j.Logger;
+import org.h2.jdbcx.JdbcDataSource;
/**
- *
* Data Access Object (DAO) is an object that provides an abstract interface to some type of
* database or other persistence mechanism. By mapping application calls to the persistence layer,
* DAO provide some specific data operations without exposing details of the database. This
* isolation supports the Single responsibility principle. It separates what data accesses the
* application needs, in terms of domain-specific objects and data types (the public interface of
* the DAO), from how these needs can be satisfied with a specific DBMS.
- *
- * With the DAO pattern, we can use various method calls to retrieve/add/delete/update data without
- * directly interacting with the data. The below example demonstrates basic CRUD operations: select,
- * add, update, and delete.
+ *
+ *
With the DAO pattern, we can use various method calls to retrieve/add/delete/update data
+ * without directly interacting with the data source. The below example demonstrates basic CRUD
+ * operations: select, add, update, and delete.
+ *
*
*/
public class App {
-
+ private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
private static Logger log = Logger.getLogger(App.class);
-
+
/**
* Program entry point.
*
* @param args command line args.
+ * @throws Exception if any error occurs.
*/
- public static void main(final String[] args) {
- final CustomerDao customerDao = new CustomerDaoImpl(generateSampleCustomers());
- log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
- log.info("customerDao.getCusterById(2): " + customerDao.getCustomerById(2));
+ public static void main(final String[] args) throws Exception {
+ final CustomerDao inMemoryDao = new InMemoryCustomerDao();
+ performOperationsUsing(inMemoryDao);
+
+ final DataSource dataSource = createDataSource();
+ createSchema(dataSource);
+ final CustomerDao dbDao = new DbCustomerDao(dataSource);
+ performOperationsUsing(dbDao);
+ deleteSchema(dataSource);
+ }
+
+ private static void deleteSchema(DataSource dataSource) throws SQLException {
+ try (Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);
+ }
+ }
+
+ private static void createSchema(DataSource dataSource) throws SQLException {
+ try (Connection connection = dataSource.getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);
+ }
+ }
+
+ private static DataSource createDataSource() {
+ JdbcDataSource dataSource = new JdbcDataSource();
+ dataSource.setURL(DB_URL);
+ return dataSource;
+ }
+
+ private static void performOperationsUsing(final CustomerDao customerDao) throws Exception {
+ addCustomers(customerDao);
+ log.info("customerDao.getAllCustomers(): ");
+ try (Stream customerStream = customerDao.getAll()) {
+ customerStream.forEach((customer) -> log.info(customer));
+ }
+ log.info("customerDao.getCustomerById(2): " + customerDao.getById(2));
final Customer customer = new Customer(4, "Dan", "Danson");
- customerDao.addCustomer(customer);
- log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
+ customerDao.add(customer);
+ log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
customer.setFirstName("Daniel");
customer.setLastName("Danielson");
- customerDao.updateCustomer(customer);
- log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
- customerDao.deleteCustomer(customer);
- log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
+ customerDao.update(customer);
+ log.info("customerDao.getAllCustomers(): ");
+ try (Stream customerStream = customerDao.getAll()) {
+ customerStream.forEach((cust) -> log.info(cust));
+ }
+ customerDao.delete(customer);
+ log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
+ }
+
+ private static void addCustomers(CustomerDao customerDao) throws Exception {
+ for (Customer customer : generateSampleCustomers()) {
+ customerDao.add(customer);
+ }
}
/**
diff --git a/dao/src/main/java/com/iluwatar/dao/Customer.java b/dao/src/main/java/com/iluwatar/dao/Customer.java
index 6d10fb146..d6b512dd6 100644
--- a/dao/src/main/java/com/iluwatar/dao/Customer.java
+++ b/dao/src/main/java/com/iluwatar/dao/Customer.java
@@ -20,11 +20,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
package com.iluwatar.dao;
/**
- *
- * Customer
+ * A customer POJO that represents the data that will be read from the data source.
*
*/
public class Customer {
@@ -34,7 +34,7 @@ public class Customer {
private String lastName;
/**
- * Constructor
+ * Creates an instance of customer.
*/
public Customer(final int id, final String firstName, final String lastName) {
this.id = id;
@@ -73,12 +73,12 @@ public class Customer {
}
@Override
- public boolean equals(final Object o) {
+ public boolean equals(final Object that) {
boolean isEqual = false;
- if (this == o) {
+ if (this == that) {
isEqual = true;
- } else if (o != null && getClass() == o.getClass()) {
- final Customer customer = (Customer) o;
+ } else if (that != null && getClass() == that.getClass()) {
+ final Customer customer = (Customer) that;
if (getId() == customer.getId()) {
isEqual = true;
}
diff --git a/dao/src/main/java/com/iluwatar/dao/CustomerDao.java b/dao/src/main/java/com/iluwatar/dao/CustomerDao.java
index 26b4df47b..059a9e9f7 100644
--- a/dao/src/main/java/com/iluwatar/dao/CustomerDao.java
+++ b/dao/src/main/java/com/iluwatar/dao/CustomerDao.java
@@ -20,24 +20,62 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
package com.iluwatar.dao;
-import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
/**
+ * In an application the Data Access Object (DAO) is a part of Data access layer. It is an object
+ * that provides an interface to some type of persistence mechanism. By mapping application calls
+ * to the persistence layer, DAO provides some specific data operations without exposing details
+ * of the database. This isolation supports the Single responsibility principle. It separates what
+ * data accesses the application needs, in terms of domain-specific objects and data types
+ * (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS,
+ * database schema, etc.
*
- * CustomerDao
- *
+ * Any change in the way data is stored and retrieved will not change the client code as the
+ * client will be using interface and need not worry about exact source.
+ *
+ * @see InMemoryCustomerDao
+ * @see DbCustomerDao
*/
public interface CustomerDao {
- List getAllCustomers();
+ /**
+ * @return all the customers as a stream. The stream may be lazily or eagerly evaluated based
+ * on the implementation. The stream must be closed after use.
+ * @throws Exception if any error occurs.
+ */
+ Stream getAll() throws Exception;
+
+ /**
+ * @param id unique identifier of the customer.
+ * @return an optional with customer if a customer with unique identifier id
+ * exists, empty optional otherwise.
+ * @throws Exception if any error occurs.
+ */
+ Optional getById(int id) throws Exception;
- Customer getCustomerById(int id);
+ /**
+ * @param customer the customer to be added.
+ * @return true if customer is successfully added, false if customer already exists.
+ * @throws Exception if any error occurs.
+ */
+ boolean add(Customer customer) throws Exception;
- void addCustomer(Customer customer);
+ /**
+ * @param customer the customer to be updated.
+ * @return true if customer exists and is successfully updated, false otherwise.
+ * @throws Exception if any error occurs.
+ */
+ boolean update(Customer customer) throws Exception;
- void updateCustomer(Customer customer);
-
- void deleteCustomer(Customer customer);
+ /**
+ * @param customer the customer to be deleted.
+ * @return true if customer exists and is successfully deleted, false otherwise.
+ * @throws Exception if any error occurs.
+ */
+ boolean delete(Customer customer) throws Exception;
}
diff --git a/dao/src/main/java/com/iluwatar/dao/CustomerDaoImpl.java b/dao/src/main/java/com/iluwatar/dao/CustomerDaoImpl.java
deleted file mode 100644
index 25d4149fa..000000000
--- a/dao/src/main/java/com/iluwatar/dao/CustomerDaoImpl.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * The MIT License
- * Copyright (c) 2014 Ilkka Seppälä
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package com.iluwatar.dao;
-
-import java.util.List;
-
-/**
- *
- * The data access object (DAO) is an object that provides an abstract interface to some type of
- * database or other persistence mechanism. By mapping application calls to the persistence layer,
- * DAO provide some specific data operations without exposing details of the database. This
- * isolation supports the Single responsibility principle. It separates what data accesses the
- * application needs, in terms of domain-specific objects and data types (the public interface of
- * the DAO), from how these needs can be satisfied with a specific DBMS, database schema, etc.
- *
- */
-public class CustomerDaoImpl implements CustomerDao {
-
- // Represents the DB structure for our example so we don't have to managed it ourselves
- // Note: Normally this would be in the form of an actual database and not part of the Dao Impl.
- private List customers;
-
- public CustomerDaoImpl(final List customers) {
- this.customers = customers;
- }
-
- @Override
- public List getAllCustomers() {
- return customers;
- }
-
- @Override
- public Customer getCustomerById(final int id) {
- Customer customer = null;
- for (final Customer cus : getAllCustomers()) {
- if (cus.getId() == id) {
- customer = cus;
- break;
- }
- }
- return customer;
- }
-
- @Override
- public void addCustomer(final Customer customer) {
- if (getCustomerById(customer.getId()) == null) {
- customers.add(customer);
- }
- }
-
-
- @Override
- public void updateCustomer(final Customer customer) {
- if (getAllCustomers().contains(customer)) {
- final int index = getAllCustomers().indexOf(customer);
- getAllCustomers().set(index, customer);
- }
- }
-
- @Override
- public void deleteCustomer(final Customer customer) {
- getAllCustomers().remove(customer);
- }
-}
diff --git a/dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java b/dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java
new file mode 100644
index 000000000..05707fa0e
--- /dev/null
+++ b/dao/src/main/java/com/iluwatar/dao/CustomerSchemaSql.java
@@ -0,0 +1,9 @@
+package com.iluwatar.dao;
+
+public interface CustomerSchemaSql {
+
+ String CREATE_SCHEMA_SQL = "CREATE TABLE CUSTOMERS (ID NUMBER, FNAME VARCHAR(100), "
+ + "LNAME VARCHAR(100))";
+
+ String DELETE_SCHEMA_SQL = "DROP TABLE CUSTOMERS";
+}
diff --git a/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java b/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java
new file mode 100644
index 000000000..622b5b1f0
--- /dev/null
+++ b/dao/src/main/java/com/iluwatar/dao/DbCustomerDao.java
@@ -0,0 +1,183 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.dao;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Optional;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import javax.sql.DataSource;
+
+/**
+ * An implementation of {@link CustomerDao} that persists customers in RDBMS.
+ *
+ */
+public class DbCustomerDao implements CustomerDao {
+
+ private final DataSource dataSource;
+
+ /**
+ * Creates an instance of {@link DbCustomerDao} which uses provided dataSource
+ * to store and retrieve customer information.
+ *
+ * @param dataSource a non-null dataSource.
+ */
+ public DbCustomerDao(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ /**
+ * @return a lazily populated stream of customers. Note the stream returned must be closed to
+ * free all the acquired resources. The stream keeps an open connection to the database till
+ * it is complete or is closed manually.
+ */
+ @Override
+ public Stream getAll() throws Exception {
+
+ Connection connection;
+ try {
+ connection = getConnection();
+ PreparedStatement statement = connection.prepareStatement("SELECT * FROM CUSTOMERS");
+ ResultSet resultSet = statement.executeQuery();
+ return StreamSupport.stream(new Spliterators.AbstractSpliterator(Long.MAX_VALUE,
+ Spliterator.ORDERED) {
+
+ @Override
+ public boolean tryAdvance(Consumer super Customer> action) {
+ try {
+ if (!resultSet.next()) {
+ return false;
+ }
+ action.accept(createCustomer(resultSet));
+ return true;
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }, false).onClose(() -> mutedClose(connection));
+ } catch (SQLException e) {
+ throw new Exception(e.getMessage(), e);
+ }
+ }
+
+ private Connection getConnection() throws SQLException {
+ return dataSource.getConnection();
+ }
+
+ private void mutedClose(Connection connection) {
+ try {
+ connection.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private Customer createCustomer(ResultSet resultSet) throws SQLException {
+ return new Customer(resultSet.getInt("ID"),
+ resultSet.getString("FNAME"),
+ resultSet.getString("LNAME"));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Optional getById(int id) throws Exception {
+ try (Connection connection = getConnection();
+ PreparedStatement statement =
+ connection.prepareStatement("SELECT * FROM CUSTOMERS WHERE ID = ?")) {
+
+ statement.setInt(1, id);
+ ResultSet resultSet = statement.executeQuery();
+ if (resultSet.next()) {
+ return Optional.of(createCustomer(resultSet));
+ } else {
+ return Optional.empty();
+ }
+ } catch (SQLException ex) {
+ throw new Exception(ex.getMessage(), ex);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean add(Customer customer) throws Exception {
+ if (getById(customer.getId()).isPresent()) {
+ return false;
+ }
+
+ try (Connection connection = getConnection();
+ PreparedStatement statement =
+ connection.prepareStatement("INSERT INTO CUSTOMERS VALUES (?,?,?)")) {
+ statement.setInt(1, customer.getId());
+ statement.setString(2, customer.getFirstName());
+ statement.setString(3, customer.getLastName());
+ statement.execute();
+ return true;
+ } catch (SQLException ex) {
+ throw new Exception(ex.getMessage(), ex);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean update(Customer customer) throws Exception {
+ try (Connection connection = getConnection();
+ PreparedStatement statement =
+ connection.prepareStatement("UPDATE CUSTOMERS SET FNAME = ?, LNAME = ? WHERE ID = ?")) {
+ statement.setString(1, customer.getFirstName());
+ statement.setString(2, customer.getLastName());
+ statement.setInt(3, customer.getId());
+ return statement.executeUpdate() > 0;
+ } catch (SQLException ex) {
+ throw new Exception(ex.getMessage(), ex);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean delete(Customer customer) throws Exception {
+ try (Connection connection = getConnection();
+ PreparedStatement statement =
+ connection.prepareStatement("DELETE FROM CUSTOMERS WHERE ID = ?")) {
+ statement.setInt(1, customer.getId());
+ return statement.executeUpdate() > 0;
+ } catch (SQLException ex) {
+ throw new Exception(ex.getMessage(), ex);
+ }
+ }
+}
diff --git a/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java b/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java
new file mode 100644
index 000000000..15c63d1de
--- /dev/null
+++ b/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java
@@ -0,0 +1,73 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.dao;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+/**
+ * An in memory implementation of {@link CustomerDao}, which stores the customers in JVM memory
+ * and data is lost when the application exits.
+ *
+ * This implementation is useful as temporary database or for testing.
+ */
+public class InMemoryCustomerDao implements CustomerDao {
+
+ private Map idToCustomer = new HashMap<>();
+
+ /**
+ * An eagerly evaluated stream of customers stored in memory.
+ */
+ @Override
+ public Stream getAll() {
+ return idToCustomer.values().stream();
+ }
+
+ @Override
+ public Optional getById(final int id) {
+ return Optional.ofNullable(idToCustomer.get(id));
+ }
+
+ @Override
+ public boolean add(final Customer customer) {
+ if (getById(customer.getId()).isPresent()) {
+ return false;
+ }
+
+ idToCustomer.put(customer.getId(), customer);
+ return true;
+ }
+
+ @Override
+ public boolean update(final Customer customer) {
+ return idToCustomer.replace(customer.getId(), customer) != null;
+ }
+
+ @Override
+ public boolean delete(final Customer customer) {
+ return idToCustomer.remove(customer.getId()) != null;
+ }
+}
diff --git a/dao/src/test/java/com/iluwatar/dao/AppTest.java b/dao/src/test/java/com/iluwatar/dao/AppTest.java
index b4caa54b4..169fc046e 100644
--- a/dao/src/test/java/com/iluwatar/dao/AppTest.java
+++ b/dao/src/test/java/com/iluwatar/dao/AppTest.java
@@ -20,18 +20,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
package com.iluwatar.dao;
import org.junit.Test;
-import java.io.IOException;
-
/**
* Tests that DAO example runs without errors.
*/
public class AppTest {
@Test
- public void test() throws IOException {
+ public void test() throws Exception {
String[] args = {};
App.main(args);
}
diff --git a/dao/src/test/java/com/iluwatar/dao/CustomerDaoImplTest.java b/dao/src/test/java/com/iluwatar/dao/CustomerDaoImplTest.java
deleted file mode 100644
index f30740629..000000000
--- a/dao/src/test/java/com/iluwatar/dao/CustomerDaoImplTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * The MIT License
- * Copyright (c) 2014 Ilkka Seppälä
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package com.iluwatar.dao;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class CustomerDaoImplTest {
-
- private CustomerDaoImpl impl;
- private List customers;
- private static final Customer CUSTOMER = new Customer(1, "Freddy", "Krueger");
-
- @Before
- public void setUp() {
- customers = new ArrayList<>();
- customers.add(CUSTOMER);
- impl = new CustomerDaoImpl(customers);
- }
-
- @Test
- public void deleteExistingCustomer() {
- assertEquals(1, impl.getAllCustomers().size());
- impl.deleteCustomer(CUSTOMER);
- assertTrue(impl.getAllCustomers().isEmpty());
- }
-
- @Test
- public void deleteNonExistingCustomer() {
- final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
- impl.deleteCustomer(nonExistingCustomer);
- assertEquals(1, impl.getAllCustomers().size());
- }
-
- @Test
- public void updateExistingCustomer() {
- final String newFirstname = "Bernard";
- final String newLastname = "Montgomery";
- final Customer customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname);
- impl.updateCustomer(customer);
- final Customer cust = impl.getCustomerById(CUSTOMER.getId());
- assertEquals(newFirstname, cust.getFirstName());
- assertEquals(newLastname, cust.getLastName());
- }
-
- @Test
- public void updateNonExistingCustomer() {
- final int nonExistingId = getNonExistingCustomerId();
- final String newFirstname = "Douglas";
- final String newLastname = "MacArthur";
- final Customer customer = new Customer(nonExistingId, newFirstname, newLastname);
- impl.updateCustomer(customer);
- assertNull(impl.getCustomerById(nonExistingId));
- final Customer existingCustomer = impl.getCustomerById(CUSTOMER.getId());
- assertEquals(CUSTOMER.getFirstName(), existingCustomer.getFirstName());
- assertEquals(CUSTOMER.getLastName(), existingCustomer.getLastName());
- }
-
- @Test
- public void addCustomer() {
- final Customer newCustomer = new Customer(3, "George", "Patton");
- impl.addCustomer(newCustomer);
- assertEquals(2, impl.getAllCustomers().size());
- }
-
- @Test
- public void addAlreadyAddedCustomer() {
- final Customer newCustomer = new Customer(3, "George", "Patton");
- impl.addCustomer(newCustomer);
- assertEquals(2, impl.getAllCustomers().size());
- impl.addCustomer(newCustomer);
- assertEquals(2, impl.getAllCustomers().size());
- }
-
- @Test
- public void getExistinCustomerById() {
- assertEquals(CUSTOMER, impl.getCustomerById(CUSTOMER.getId()));
- }
-
- @Test
- public void getNonExistinCustomerById() {
- final int nonExistingId = getNonExistingCustomerId();
- assertNull(impl.getCustomerById(nonExistingId));
- }
-
- /**
- * An arbitrary number which does not correspond to an active Customer id.
- *
- * @return an int of a customer id which doesn't exist
- */
- private int getNonExistingCustomerId() {
- return 999;
- }
-}
diff --git a/dao/src/test/java/com/iluwatar/dao/CustomerTest.java b/dao/src/test/java/com/iluwatar/dao/CustomerTest.java
index 600b5ba3f..6a02fd6be 100644
--- a/dao/src/test/java/com/iluwatar/dao/CustomerTest.java
+++ b/dao/src/test/java/com/iluwatar/dao/CustomerTest.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.dao;
import static org.junit.Assert.assertEquals;
diff --git a/dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java b/dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java
new file mode 100644
index 000000000..08e61ebe6
--- /dev/null
+++ b/dao/src/test/java/com/iluwatar/dao/DbCustomerDaoTest.java
@@ -0,0 +1,247 @@
+package com.iluwatar.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.stream.Stream;
+
+import javax.sql.DataSource;
+
+import org.h2.jdbcx.JdbcDataSource;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+import de.bechte.junit.runners.context.HierarchicalContextRunner;
+
+/**
+ * Tests {@link DbCustomerDao}.
+ */
+@RunWith(HierarchicalContextRunner.class)
+public class DbCustomerDaoTest {
+
+ private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
+ private DbCustomerDao dao;
+ private Customer existingCustomer = new Customer(1, "Freddy", "Krueger");
+
+ /**
+ * Creates customers schema.
+ * @throws SQLException if there is any error while creating schema.
+ */
+ @Before
+ public void createSchema() throws SQLException {
+ try (Connection connection = DriverManager.getConnection(DB_URL);
+ Statement statement = connection.createStatement()) {
+ statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);
+ }
+ }
+
+ /**
+ * Represents the scenario where DB connectivity is present.
+ */
+ public class ConnectionSuccess {
+
+ /**
+ * Setup for connection success scenario.
+ * @throws Exception if any error occurs.
+ */
+ @Before
+ public void setUp() throws Exception {
+ JdbcDataSource dataSource = new JdbcDataSource();
+ dataSource.setURL(DB_URL);
+ dao = new DbCustomerDao(dataSource);
+ boolean result = dao.add(existingCustomer);
+ assertTrue(result);
+ }
+
+ /**
+ * Represents the scenario when DAO operations are being performed on a non existing customer.
+ */
+ public class NonExistingCustomer {
+
+ @Test
+ public void addingShouldResultInSuccess() throws Exception {
+ try (Stream allCustomers = dao.getAll()) {
+ assumeTrue(allCustomers.count() == 1);
+ }
+
+ final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
+ boolean result = dao.add(nonExistingCustomer);
+ assertTrue(result);
+
+ assertCustomerCountIs(2);
+ assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get());
+ }
+
+ @Test
+ public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
+ final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
+ boolean result = dao.delete(nonExistingCustomer);
+
+ assertFalse(result);
+ assertCustomerCountIs(1);
+ }
+
+ @Test
+ public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
+ final int nonExistingId = getNonExistingCustomerId();
+ final String newFirstname = "Douglas";
+ final String newLastname = "MacArthur";
+ final Customer customer = new Customer(nonExistingId, newFirstname, newLastname);
+ boolean result = dao.update(customer);
+
+ assertFalse(result);
+ assertFalse(dao.getById(nonExistingId).isPresent());
+ }
+
+ @Test
+ public void retrieveShouldReturnNoCustomer() throws Exception {
+ assertFalse(dao.getById(getNonExistingCustomerId()).isPresent());
+ }
+ }
+
+ /**
+ * Represents a scenario where DAO operations are being performed on an already existing
+ * customer.
+ *
+ */
+ public class ExistingCustomer {
+
+ @Test
+ public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception {
+ Customer existingCustomer = new Customer(1, "Freddy", "Krueger");
+
+ boolean result = dao.add(existingCustomer);
+
+ assertFalse(result);
+ assertCustomerCountIs(1);
+ assertEquals(existingCustomer, dao.getById(existingCustomer.getId()).get());
+ }
+
+ @Test
+ public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception {
+ boolean result = dao.delete(existingCustomer);
+
+ assertTrue(result);
+ assertCustomerCountIs(0);
+ assertFalse(dao.getById(existingCustomer.getId()).isPresent());
+ }
+
+ @Test
+ public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception {
+ final String newFirstname = "Bernard";
+ final String newLastname = "Montgomery";
+ final Customer customer = new Customer(existingCustomer.getId(), newFirstname, newLastname);
+ boolean result = dao.update(customer);
+
+ assertTrue(result);
+
+ final Customer cust = dao.getById(existingCustomer.getId()).get();
+ assertEquals(newFirstname, cust.getFirstName());
+ assertEquals(newLastname, cust.getLastName());
+ }
+ }
+ }
+
+ /**
+ * Represents a scenario where DB connectivity is not present due to network issue, or
+ * DB service unavailable.
+ *
+ */
+ public class ConnectivityIssue {
+
+ private static final String EXCEPTION_CAUSE = "Connection not available";
+ @Rule public ExpectedException exception = ExpectedException.none();
+
+ /**
+ * setup a connection failure scenario.
+ * @throws SQLException if any error occurs.
+ */
+ @Before
+ public void setUp() throws SQLException {
+ dao = new DbCustomerDao(mockedDatasource());
+ exception.expect(Exception.class);
+ exception.expectMessage(EXCEPTION_CAUSE);
+ }
+
+ private DataSource mockedDatasource() throws SQLException {
+ DataSource mockedDataSource = mock(DataSource.class);
+ Connection mockedConnection = mock(Connection.class);
+ SQLException exception = new SQLException(EXCEPTION_CAUSE);
+ doThrow(exception).when(mockedConnection).prepareStatement(Mockito.anyString());
+ doReturn(mockedConnection).when(mockedDataSource).getConnection();
+ return mockedDataSource;
+ }
+
+ @Test
+ public void addingACustomerFailsWithExceptionAsFeedbackToClient() throws Exception {
+ dao.add(new Customer(2, "Bernard", "Montgomery"));
+ }
+
+ @Test
+ public void deletingACustomerFailsWithExceptionAsFeedbackToTheClient() throws Exception {
+ dao.delete(existingCustomer);
+ }
+
+ @Test
+ public void updatingACustomerFailsWithFeedbackToTheClient() throws Exception {
+ final String newFirstname = "Bernard";
+ final String newLastname = "Montgomery";
+
+ dao.update(new Customer(existingCustomer.getId(), newFirstname, newLastname));
+ }
+
+ @Test
+ public void retrievingACustomerByIdFailsWithExceptionAsFeedbackToClient() throws Exception {
+ dao.getById(existingCustomer.getId());
+ }
+
+ @Test
+ public void retrievingAllCustomersFailsWithExceptionAsFeedbackToClient() throws Exception {
+ dao.getAll();
+ }
+
+ }
+
+ /**
+ * Delete customer schema for fresh setup per test.
+ * @throws SQLException if any error occurs.
+ */
+ @After
+ public void deleteSchema() throws SQLException {
+ try (Connection connection = DriverManager.getConnection(DB_URL);
+ Statement statement = connection.createStatement()) {
+ statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);
+ }
+ }
+
+ private void assertCustomerCountIs(int count) throws Exception {
+ try (Stream allCustomers = dao.getAll()) {
+ assertTrue(allCustomers.count() == count);
+ }
+ }
+
+
+ /**
+ * An arbitrary number which does not correspond to an active Customer id.
+ *
+ * @return an int of a customer id which doesn't exist
+ */
+ private int getNonExistingCustomerId() {
+ return 999;
+ }
+}
diff --git a/dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java b/dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java
new file mode 100644
index 000000000..65a087b9b
--- /dev/null
+++ b/dao/src/test/java/com/iluwatar/dao/InMemoryCustomerDaoTest.java
@@ -0,0 +1,164 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import de.bechte.junit.runners.context.HierarchicalContextRunner;
+
+/**
+ * Tests {@link InMemoryCustomerDao}.
+ */
+@RunWith(HierarchicalContextRunner.class)
+public class InMemoryCustomerDaoTest {
+
+ private InMemoryCustomerDao dao;
+ private static final Customer CUSTOMER = new Customer(1, "Freddy", "Krueger");
+
+ @Before
+ public void setUp() {
+ dao = new InMemoryCustomerDao();
+ assertTrue(dao.add(CUSTOMER));
+ }
+
+ /**
+ * Represents the scenario when the DAO operations are being performed on a non existent
+ * customer.
+ */
+ public class NonExistingCustomer {
+
+ @Test
+ public void addingShouldResultInSuccess() throws Exception {
+ try (Stream allCustomers = dao.getAll()) {
+ assumeTrue(allCustomers.count() == 1);
+ }
+
+ final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
+ boolean result = dao.add(nonExistingCustomer);
+ assertTrue(result);
+
+ assertCustomerCountIs(2);
+ assertEquals(nonExistingCustomer, dao.getById(nonExistingCustomer.getId()).get());
+ }
+
+ @Test
+ public void deletionShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
+ final Customer nonExistingCustomer = new Customer(2, "Robert", "Englund");
+ boolean result = dao.delete(nonExistingCustomer);
+
+ assertFalse(result);
+ assertCustomerCountIs(1);
+ }
+
+ @Test
+ public void updationShouldBeFailureAndNotAffectExistingCustomers() throws Exception {
+ final int nonExistingId = getNonExistingCustomerId();
+ final String newFirstname = "Douglas";
+ final String newLastname = "MacArthur";
+ final Customer customer = new Customer(nonExistingId, newFirstname, newLastname);
+ boolean result = dao.update(customer);
+
+ assertFalse(result);
+ assertFalse(dao.getById(nonExistingId).isPresent());
+ }
+
+ @Test
+ public void retrieveShouldReturnNoCustomer() throws Exception {
+ assertFalse(dao.getById(getNonExistingCustomerId()).isPresent());
+ }
+ }
+
+ /**
+ * Represents the scenario when the DAO operations are being performed on an already existing
+ * customer.
+ */
+ public class ExistingCustomer {
+
+ @Test
+ public void addingShouldResultInFailureAndNotAffectExistingCustomers() throws Exception {
+ boolean result = dao.add(CUSTOMER);
+
+ assertFalse(result);
+ assertCustomerCountIs(1);
+ assertEquals(CUSTOMER, dao.getById(CUSTOMER.getId()).get());
+ }
+
+ @Test
+ public void deletionShouldBeSuccessAndCustomerShouldBeNonAccessible() throws Exception {
+ boolean result = dao.delete(CUSTOMER);
+
+ assertTrue(result);
+ assertCustomerCountIs(0);
+ assertFalse(dao.getById(CUSTOMER.getId()).isPresent());
+ }
+
+ @Test
+ public void updationShouldBeSuccessAndAccessingTheSameCustomerShouldReturnUpdatedInformation() throws Exception {
+ final String newFirstname = "Bernard";
+ final String newLastname = "Montgomery";
+ final Customer customer = new Customer(CUSTOMER.getId(), newFirstname, newLastname);
+ boolean result = dao.update(customer);
+
+ assertTrue(result);
+
+ final Customer cust = dao.getById(CUSTOMER.getId()).get();
+ assertEquals(newFirstname, cust.getFirstName());
+ assertEquals(newLastname, cust.getLastName());
+ }
+
+ @Test
+ public void retriveShouldReturnTheCustomer() {
+ Optional optionalCustomer = dao.getById(CUSTOMER.getId());
+
+ assertTrue(optionalCustomer.isPresent());
+ assertEquals(CUSTOMER, optionalCustomer.get());
+ }
+ }
+
+ /**
+ * An arbitrary number which does not correspond to an active Customer id.
+ *
+ * @return an int of a customer id which doesn't exist
+ */
+ private int getNonExistingCustomerId() {
+ return 999;
+ }
+
+ private void assertCustomerCountIs(int count) throws Exception {
+ try (Stream allCustomers = dao.getAll()) {
+ assertTrue(allCustomers.count() == count);
+ }
+ }
+}
diff --git a/decorator/index.md b/decorator/README.md
similarity index 100%
rename from decorator/index.md
rename to decorator/README.md
diff --git a/decorator/pom.xml b/decorator/pom.xml
index d8f253bd2..58f2bb0ba 100644
--- a/decorator/pom.xml
+++ b/decorator/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
decorator
diff --git a/decorator/src/main/java/com/iluwatar/decorator/Troll.java b/decorator/src/main/java/com/iluwatar/decorator/Troll.java
index 7992d708d..628adda4b 100644
--- a/decorator/src/main/java/com/iluwatar/decorator/Troll.java
+++ b/decorator/src/main/java/com/iluwatar/decorator/Troll.java
@@ -29,6 +29,7 @@ package com.iluwatar.decorator;
*/
public class Troll implements Hostile {
+ @Override
public void attack() {
System.out.println("The troll swings at you with a club!");
}
@@ -38,6 +39,7 @@ public class Troll implements Hostile {
return 10;
}
+ @Override
public void fleeBattle() {
System.out.println("The troll shrieks in horror and runs away!");
}
diff --git a/delegation/index.md b/delegation/README.md
similarity index 100%
rename from delegation/index.md
rename to delegation/README.md
diff --git a/delegation/pom.xml b/delegation/pom.xml
index 1cfb3e4e3..33592dd82 100644
--- a/delegation/pom.xml
+++ b/delegation/pom.xml
@@ -30,7 +30,7 @@
java-design-patterns
com.iluwatar
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
4.0.0
diff --git a/dependency-injection/index.md b/dependency-injection/README.md
similarity index 100%
rename from dependency-injection/index.md
rename to dependency-injection/README.md
diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml
index cb210ca5a..d8be9fcff 100644
--- a/dependency-injection/pom.xml
+++ b/dependency-injection/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
dependency-injection
diff --git a/double-checked-locking/index.md b/double-checked-locking/README.md
similarity index 100%
rename from double-checked-locking/index.md
rename to double-checked-locking/README.md
diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml
index e3b4c5bff..f8ac5fa2e 100644
--- a/double-checked-locking/pom.xml
+++ b/double-checked-locking/pom.xml
@@ -27,7 +27,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
double-checked-locking
diff --git a/double-dispatch/index.md b/double-dispatch/README.md
similarity index 100%
rename from double-dispatch/index.md
rename to double-dispatch/README.md
diff --git a/double-dispatch/pom.xml b/double-dispatch/pom.xml
index 8414a6aa1..8896abd9f 100644
--- a/double-dispatch/pom.xml
+++ b/double-dispatch/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
double-dispatch
diff --git a/event-aggregator/index.md b/event-aggregator/README.md
similarity index 100%
rename from event-aggregator/index.md
rename to event-aggregator/README.md
diff --git a/event-aggregator/pom.xml b/event-aggregator/pom.xml
index 6627bdb1a..1b1f289b2 100644
--- a/event-aggregator/pom.xml
+++ b/event-aggregator/pom.xml
@@ -28,7 +28,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
event-aggregator
diff --git a/event-driven-architecture/index.md b/event-driven-architecture/README.md
similarity index 100%
rename from event-driven-architecture/index.md
rename to event-driven-architecture/README.md
diff --git a/event-driven-architecture/pom.xml b/event-driven-architecture/pom.xml
index b0b588c6b..cccf39088 100644
--- a/event-driven-architecture/pom.xml
+++ b/event-driven-architecture/pom.xml
@@ -31,7 +31,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
event-driven-architecture
diff --git a/execute-around/index.md b/execute-around/README.md
similarity index 100%
rename from execute-around/index.md
rename to execute-around/README.md
diff --git a/execute-around/pom.xml b/execute-around/pom.xml
index a8654ac77..23a0a4a15 100644
--- a/execute-around/pom.xml
+++ b/execute-around/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
execute-around
diff --git a/facade/index.md b/facade/README.md
similarity index 100%
rename from facade/index.md
rename to facade/README.md
diff --git a/facade/pom.xml b/facade/pom.xml
index daa3853cd..a526243a1 100644
--- a/facade/pom.xml
+++ b/facade/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
facade
diff --git a/factory-kit/index.md b/factory-kit/README.md
similarity index 100%
rename from factory-kit/index.md
rename to factory-kit/README.md
diff --git a/factory-kit/pom.xml b/factory-kit/pom.xml
index c336c5f49..ea2aa5976 100644
--- a/factory-kit/pom.xml
+++ b/factory-kit/pom.xml
@@ -30,7 +30,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
factory-kit
diff --git a/factory-method/index.md b/factory-method/README.md
similarity index 100%
rename from factory-method/index.md
rename to factory-method/README.md
diff --git a/factory-method/pom.xml b/factory-method/pom.xml
index 25ca9f726..7e1cfd28f 100644
--- a/factory-method/pom.xml
+++ b/factory-method/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
factory-method
diff --git a/feature-toggle/index.md b/feature-toggle/README.md
similarity index 100%
rename from feature-toggle/index.md
rename to feature-toggle/README.md
diff --git a/feature-toggle/pom.xml b/feature-toggle/pom.xml
index 5f732f5a3..cf479dd0a 100644
--- a/feature-toggle/pom.xml
+++ b/feature-toggle/pom.xml
@@ -30,7 +30,7 @@
java-design-patterns
com.iluwatar
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
4.0.0
diff --git a/fluentinterface/index.md b/fluentinterface/README.md
similarity index 100%
rename from fluentinterface/index.md
rename to fluentinterface/README.md
diff --git a/fluentinterface/pom.xml b/fluentinterface/pom.xml
index 5faf359d1..2e4129b2d 100644
--- a/fluentinterface/pom.xml
+++ b/fluentinterface/pom.xml
@@ -29,7 +29,7 @@
java-design-patterns
com.iluwatar
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
4.0.0
diff --git a/flux/index.md b/flux/README.md
similarity index 100%
rename from flux/index.md
rename to flux/README.md
diff --git a/flux/pom.xml b/flux/pom.xml
index 25182d784..bd454ca23 100644
--- a/flux/pom.xml
+++ b/flux/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
flux
diff --git a/flyweight/index.md b/flyweight/README.md
similarity index 100%
rename from flyweight/index.md
rename to flyweight/README.md
diff --git a/flyweight/pom.xml b/flyweight/pom.xml
index a066c8924..a4221d762 100644
--- a/flyweight/pom.xml
+++ b/flyweight/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
flyweight
diff --git a/front-controller/index.md b/front-controller/README.md
similarity index 100%
rename from front-controller/index.md
rename to front-controller/README.md
diff --git a/front-controller/pom.xml b/front-controller/pom.xml
index 8cb7ddc6d..c8f136ca8 100644
--- a/front-controller/pom.xml
+++ b/front-controller/pom.xml
@@ -30,7 +30,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
front-controller
diff --git a/half-sync-half-async/index.md b/half-sync-half-async/README.md
similarity index 100%
rename from half-sync-half-async/index.md
rename to half-sync-half-async/README.md
diff --git a/half-sync-half-async/pom.xml b/half-sync-half-async/pom.xml
index 357cabf4b..5b6ce56b1 100644
--- a/half-sync-half-async/pom.xml
+++ b/half-sync-half-async/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
half-sync-half-async
diff --git a/intercepting-filter/index.md b/intercepting-filter/README.md
similarity index 100%
rename from intercepting-filter/index.md
rename to intercepting-filter/README.md
diff --git a/intercepting-filter/pom.xml b/intercepting-filter/pom.xml
index 0ff3be16b..6ef1e25bc 100644
--- a/intercepting-filter/pom.xml
+++ b/intercepting-filter/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
intercepting-filter
diff --git a/interpreter/index.md b/interpreter/README.md
similarity index 100%
rename from interpreter/index.md
rename to interpreter/README.md
diff --git a/interpreter/pom.xml b/interpreter/pom.xml
index 3a09ae310..a0003672a 100644
--- a/interpreter/pom.xml
+++ b/interpreter/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
interpreter
diff --git a/iterator/index.md b/iterator/README.md
similarity index 100%
rename from iterator/index.md
rename to iterator/README.md
diff --git a/iterator/pom.xml b/iterator/pom.xml
index 2aeea6100..dcd70f809 100644
--- a/iterator/pom.xml
+++ b/iterator/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
iterator
diff --git a/layers/index.md b/layers/README.md
similarity index 100%
rename from layers/index.md
rename to layers/README.md
diff --git a/layers/pom.xml b/layers/pom.xml
index c6e68150b..abd888afa 100644
--- a/layers/pom.xml
+++ b/layers/pom.xml
@@ -30,7 +30,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
com.iluwatar.layers
layers
diff --git a/lazy-loading/index.md b/lazy-loading/README.md
similarity index 100%
rename from lazy-loading/index.md
rename to lazy-loading/README.md
diff --git a/lazy-loading/pom.xml b/lazy-loading/pom.xml
index 0ca7272a0..37b321aec 100644
--- a/lazy-loading/pom.xml
+++ b/lazy-loading/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
lazy-loading
diff --git a/mediator/index.md b/mediator/README.md
similarity index 100%
rename from mediator/index.md
rename to mediator/README.md
diff --git a/mediator/pom.xml b/mediator/pom.xml
index 8e24da4b9..7f3209479 100644
--- a/mediator/pom.xml
+++ b/mediator/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
mediator
diff --git a/memento/index.md b/memento/README.md
similarity index 100%
rename from memento/index.md
rename to memento/README.md
diff --git a/memento/pom.xml b/memento/pom.xml
index fc78cb65b..b7355784c 100644
--- a/memento/pom.xml
+++ b/memento/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
memento
diff --git a/message-channel/index.md b/message-channel/README.md
similarity index 100%
rename from message-channel/index.md
rename to message-channel/README.md
diff --git a/message-channel/pom.xml b/message-channel/pom.xml
index a6f626a11..3afc5b32e 100644
--- a/message-channel/pom.xml
+++ b/message-channel/pom.xml
@@ -30,7 +30,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
message-channel
diff --git a/model-view-controller/index.md b/model-view-controller/README.md
similarity index 100%
rename from model-view-controller/index.md
rename to model-view-controller/README.md
diff --git a/model-view-controller/pom.xml b/model-view-controller/pom.xml
index 4e8697171..0ae6a6fc6 100644
--- a/model-view-controller/pom.xml
+++ b/model-view-controller/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
model-view-controller
diff --git a/model-view-presenter/index.md b/model-view-presenter/README.md
similarity index 100%
rename from model-view-presenter/index.md
rename to model-view-presenter/README.md
diff --git a/model-view-presenter/pom.xml b/model-view-presenter/pom.xml
index c4f1c82dd..e0a3c57fb 100644
--- a/model-view-presenter/pom.xml
+++ b/model-view-presenter/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
model-view-presenter
model-view-presenter
diff --git a/monad/index.md b/monad/README.md
similarity index 97%
rename from monad/index.md
rename to monad/README.md
index 82deba922..ffc67a354 100644
--- a/monad/index.md
+++ b/monad/README.md
@@ -1,35 +1,35 @@
----
-layout: pattern
-title: Monad
-folder: monad
-permalink: /patterns/monad/
-categories: Other
-tags:
- - Java
- - Difficulty-Advanced
- - Functional
----
-
-## Intent
-
-Monad pattern based on monad from linear algebra represents the way of chaining operations
-together step by step. Binding functions can be described as passing one's output to another's input
-basing on the 'same type' contract. Formally, monad consists of a type constructor M and two
-operations:
-bind - that takes monadic object and a function from plain object to monadic value and returns monadic value
-return - that takes plain type object and returns this object wrapped in a monadic value.
-
-
-
-## Applicability
-
-Use the Monad in any of the following situations
-
-* when you want to chain operations easily
-* when you want to apply each function regardless of the result of any of them
-
-## Credits
-
-* [Design Pattern Reloaded by Remi Forax](https://youtu.be/-k2X7guaArU)
-* [Brian Beckman: Don't fear the Monad](https://channel9.msdn.com/Shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monads)
+---
+layout: pattern
+title: Monad
+folder: monad
+permalink: /patterns/monad/
+categories: Other
+tags:
+ - Java
+ - Difficulty-Advanced
+ - Functional
+---
+
+## Intent
+
+Monad pattern based on monad from linear algebra represents the way of chaining operations
+together step by step. Binding functions can be described as passing one's output to another's input
+basing on the 'same type' contract. Formally, monad consists of a type constructor M and two
+operations:
+bind - that takes monadic object and a function from plain object to monadic value and returns monadic value
+return - that takes plain type object and returns this object wrapped in a monadic value.
+
+
+
+## Applicability
+
+Use the Monad in any of the following situations
+
+* when you want to chain operations easily
+* when you want to apply each function regardless of the result of any of them
+
+## Credits
+
+* [Design Pattern Reloaded by Remi Forax](https://youtu.be/-k2X7guaArU)
+* [Brian Beckman: Don't fear the Monad](https://channel9.msdn.com/Shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monads)
* [Monad on Wikipedia](https://en.wikipedia.org/wiki/Monad_(functional_programming))
\ No newline at end of file
diff --git a/monad/pom.xml b/monad/pom.xml
index ec5a14a8c..b737e2174 100644
--- a/monad/pom.xml
+++ b/monad/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
monad
diff --git a/monostate/index.md b/monostate/README.md
similarity index 100%
rename from monostate/index.md
rename to monostate/README.md
diff --git a/monostate/pom.xml b/monostate/pom.xml
index bb6119253..bb246d38c 100644
--- a/monostate/pom.xml
+++ b/monostate/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
monostate
diff --git a/multiton/index.md b/multiton/README.md
similarity index 94%
rename from multiton/index.md
rename to multiton/README.md
index 68fb6bbc6..0462ff0ec 100644
--- a/multiton/index.md
+++ b/multiton/README.md
@@ -9,6 +9,9 @@ tags:
- Difficulty-Beginner
---
+## Also known as
+Registry
+
## Intent
Ensure a class only has limited number of instances, and provide a
global point of access to them.
diff --git a/multiton/pom.xml b/multiton/pom.xml
index 6b07c638d..2482c056b 100644
--- a/multiton/pom.xml
+++ b/multiton/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
multiton
diff --git a/mute-idiom/README.md b/mute-idiom/README.md
new file mode 100644
index 000000000..efc09f306
--- /dev/null
+++ b/mute-idiom/README.md
@@ -0,0 +1,28 @@
+---
+layout: pattern
+title: Mute Idiom
+folder: mute-idiom
+permalink: /patterns/mute-idiom/
+categories: Other
+tags:
+ - Java
+ - Difficulty-Beginner
+ - Idiom
+---
+
+## Intent
+Provide a template to supress any exceptions that either are declared but cannot occur or should only be logged;
+while executing some business logic. The template removes the need to write repeated `try-catch` blocks.
+
+
+
+
+## Applicability
+Use this idiom when
+
+* an API declares some exception but can never throw that exception. Eg. ByteArrayOutputStream bulk write method.
+* you need to suppress some exception just by logging it, such as closing a resource.
+
+## Credits
+
+* [JOOQ: Mute Design Pattern](http://blog.jooq.org/2016/02/18/the-mute-design-pattern/)
diff --git a/mute-idiom/etc/mute-idiom.png b/mute-idiom/etc/mute-idiom.png
new file mode 100644
index 000000000..203bdafc4
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..7b4d2f916
--- /dev/null
+++ b/mute-idiom/etc/mute-idiom.ucls
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mute-idiom/pom.xml b/mute-idiom/pom.xml
new file mode 100644
index 000000000..3bfc3bf8a
--- /dev/null
+++ b/mute-idiom/pom.xml
@@ -0,0 +1,34 @@
+
+
+
+ 4.0.0
+
+ com.iluwatar
+ java-design-patterns
+ 1.12.0-SNAPSHOT
+
+ mute-idiom
+
+
+ junit
+ junit
+ test
+
+
+
diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/App.java b/mute-idiom/src/main/java/com/iluwatar/mute/App.java
new file mode 100644
index 000000000..8a2aca41e
--- /dev/null
+++ b/mute-idiom/src/main/java/com/iluwatar/mute/App.java
@@ -0,0 +1,103 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.mute;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.sql.SQLException;
+
+/**
+ * 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 {
+
+ /**
+ * 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.
+ */
+ private static void useOfMute() {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Mute.mute(() -> out.write("Hello".getBytes()));
+ }
+
+ private static void useOfLoggedMute() throws SQLException {
+ Resource resource = null;
+ try {
+ resource = acquireResource();
+ utilizeResource(resource);
+ } finally {
+ closeResource(resource);
+ }
+ }
+
+ /*
+ * All we can do while failed close of a resource is to log it.
+ */
+ private static void closeResource(Resource resource) {
+ Mute.loggedMute(() -> resource.close());
+ }
+
+ private static void utilizeResource(Resource resource) throws SQLException {
+ System.out.println("Utilizing acquired resource: " + resource);
+ }
+
+ private static Resource acquireResource() throws SQLException {
+ return new Resource() {
+
+ @Override
+ public void close() throws IOException {
+ throw new IOException("Error in closing resource: " + this);
+ }
+ };
+ }
+}
diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java b/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java
new file mode 100644
index 000000000..d1440636f
--- /dev/null
+++ b/mute-idiom/src/main/java/com/iluwatar/mute/CheckedRunnable.java
@@ -0,0 +1,37 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.mute;
+
+/**
+ * A runnable which may throw exception on execution.
+ *
+ */
+@FunctionalInterface
+public interface CheckedRunnable {
+ /**
+ * Same as {@link Runnable#run()} with a possibility of exception in execution.
+ * @throws Exception if any exception occurs.
+ */
+ 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
new file mode 100644
index 000000000..64169a8f5
--- /dev/null
+++ b/mute-idiom/src/main/java/com/iluwatar/mute/Mute.java
@@ -0,0 +1,68 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.iluwatar.mute;
+
+import java.io.ByteArrayOutputStream;
+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}.
+ * This method should be utilized to mute the operations that are guaranteed not to throw an exception.
+ * For instance {@link ByteArrayOutputStream#write(byte[])} declares in it's signature that it can throw
+ * an {@link IOException}, but in reality it cannot. This is because the bulk write method is not overridden
+ * in {@link ByteArrayOutputStream}.
+ *
+ * @param runnable a runnable that should never throw an exception on execution.
+ */
+ public static void mute(CheckedRunnable runnable) {
+ try {
+ runnable.run();
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /**
+ * Executes the runnable and logs the exception occurred on {@link System#err}.
+ * This method should be utilized to mute the operations about which most you can do is log.
+ * For instance while closing a connection to database, or cleaning up a resource,
+ * all you can do is log the exception occurred.
+ *
+ * @param runnable a runnable that may throw an exception on execution.
+ */
+ public static void loggedMute(CheckedRunnable runnable) {
+ try {
+ runnable.run();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java b/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java
new file mode 100644
index 000000000..6970d06bc
--- /dev/null
+++ b/mute-idiom/src/main/java/com/iluwatar/mute/Resource.java
@@ -0,0 +1,35 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.mute;
+
+import java.io.Closeable;
+
+/**
+ * Represents any resource that the application might acquire and that must be closed
+ * after it is utilized. Example of such resources can be a database connection, open
+ * files, sockets.
+ */
+public interface Resource extends Closeable {
+
+}
diff --git a/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java b/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java
new file mode 100644
index 000000000..8075d9c85
--- /dev/null
+++ b/mute-idiom/src/test/java/com/iluwatar/mute/AppTest.java
@@ -0,0 +1,38 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package com.iluwatar.mute;
+
+import org.junit.Test;
+
+/**
+ * Tests that Mute idiom example runs without errors.
+ *
+ */
+public class AppTest {
+
+ @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
new file mode 100644
index 000000000..58cbfe893
--- /dev/null
+++ b/mute-idiom/src/test/java/com/iluwatar/mute/MuteTest.java
@@ -0,0 +1,78 @@
+/**
+ * The MIT License
+ * Copyright (c) 2014 Ilkka Seppälä
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * 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;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class MuteTest {
+
+ private static final String MESSAGE = "should not occur";
+
+ @Rule public ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void muteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() {
+ Mute.mute(() -> methodNotThrowingAnyException());
+ }
+
+ @Test
+ public void muteShouldRethrowUnexpectedExceptionAsAssertionError() throws Exception {
+ exception.expect(AssertionError.class);
+ exception.expectMessage(MESSAGE);
+
+ Mute.mute(() -> methodThrowingException());
+ }
+
+ @Test
+ public void loggedMuteShouldRunTheCheckedRunnableAndNotThrowAnyExceptionIfCheckedRunnableDoesNotThrowAnyException() {
+ Mute.loggedMute(() -> methodNotThrowingAnyException());
+ }
+
+ @Test
+ public void loggedMuteShouldLogExceptionTraceBeforeSwallowingIt() throws IOException {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ System.setErr(new PrintStream(stream));
+
+ Mute.loggedMute(() -> methodThrowingException());
+
+ 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/naked-objects/index.md b/naked-objects/README.md
similarity index 100%
rename from naked-objects/index.md
rename to naked-objects/README.md
diff --git a/naked-objects/dom/pom.xml b/naked-objects/dom/pom.xml
index 102c7178e..be96b2456 100644
--- a/naked-objects/dom/pom.xml
+++ b/naked-objects/dom/pom.xml
@@ -16,7 +16,7 @@
com.iluwatar
naked-objects
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
naked-objects-dom
diff --git a/naked-objects/fixture/pom.xml b/naked-objects/fixture/pom.xml
index 6f476bc9b..6bbaaaeb1 100644
--- a/naked-objects/fixture/pom.xml
+++ b/naked-objects/fixture/pom.xml
@@ -16,7 +16,7 @@
com.iluwatar
naked-objects
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
naked-objects-fixture
diff --git a/naked-objects/integtests/pom.xml b/naked-objects/integtests/pom.xml
index 6dbfc9946..68cac3790 100644
--- a/naked-objects/integtests/pom.xml
+++ b/naked-objects/integtests/pom.xml
@@ -16,7 +16,7 @@
com.iluwatar
naked-objects
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
naked-objects-integtests
diff --git a/naked-objects/pom.xml b/naked-objects/pom.xml
index 451944aa5..d34dba9a3 100644
--- a/naked-objects/pom.xml
+++ b/naked-objects/pom.xml
@@ -15,7 +15,7 @@
java-design-patterns
com.iluwatar
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
naked-objects
@@ -350,17 +350,17 @@
${project.groupId}
naked-objects-dom
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
${project.groupId}
naked-objects-fixture
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
${project.groupId}
naked-objects-webapp
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
diff --git a/naked-objects/webapp/pom.xml b/naked-objects/webapp/pom.xml
index c8b483513..aa7d60438 100644
--- a/naked-objects/webapp/pom.xml
+++ b/naked-objects/webapp/pom.xml
@@ -16,7 +16,7 @@
com.iluwatar
naked-objects
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
naked-objects-webapp
diff --git a/null-object/index.md b/null-object/README.md
similarity index 100%
rename from null-object/index.md
rename to null-object/README.md
diff --git a/null-object/pom.xml b/null-object/pom.xml
index e8b1d2465..b765c6537 100644
--- a/null-object/pom.xml
+++ b/null-object/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
null-object
diff --git a/object-pool/index.md b/object-pool/README.md
similarity index 100%
rename from object-pool/index.md
rename to object-pool/README.md
diff --git a/object-pool/pom.xml b/object-pool/pom.xml
index 5a2e4b8b6..6022ef8a7 100644
--- a/object-pool/pom.xml
+++ b/object-pool/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
object-pool
diff --git a/observer/index.md b/observer/README.md
similarity index 100%
rename from observer/index.md
rename to observer/README.md
diff --git a/observer/pom.xml b/observer/pom.xml
index c8cca3edc..fcc3e88aa 100644
--- a/observer/pom.xml
+++ b/observer/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
observer
diff --git a/poison-pill/index.md b/poison-pill/README.md
similarity index 100%
rename from poison-pill/index.md
rename to poison-pill/README.md
diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml
index 0cc3bd6e8..b76578122 100644
--- a/poison-pill/pom.xml
+++ b/poison-pill/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
poison-pill
diff --git a/pom.xml b/pom.xml
index 6339fb72b..ef443a2d5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,7 +27,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
pom
2014
@@ -48,6 +48,7 @@
19.0
1.15.1
1.10.19
+ 4.12.1
abstract-factory
@@ -121,7 +122,7 @@
feature-toggle
value-object
monad
- hexagonal
+ mute-idiom
@@ -194,6 +195,12 @@
${systemrules.version}
test
+
+ de.bechte.junit
+ junit-hierarchicalcontextrunner
+ ${hierarchical-junit-runner-version}
+ test
+
diff --git a/private-class-data/index.md b/private-class-data/README.md
similarity index 100%
rename from private-class-data/index.md
rename to private-class-data/README.md
diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml
index 97d623b46..877197664 100644
--- a/private-class-data/pom.xml
+++ b/private-class-data/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
private-class-data
diff --git a/producer-consumer/index.md b/producer-consumer/README.md
similarity index 100%
rename from producer-consumer/index.md
rename to producer-consumer/README.md
diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml
index 5c00b85f9..c4ea8f1df 100644
--- a/producer-consumer/pom.xml
+++ b/producer-consumer/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
producer-consumer
diff --git a/property/index.md b/property/README.md
similarity index 100%
rename from property/index.md
rename to property/README.md
diff --git a/property/pom.xml b/property/pom.xml
index a5cd459df..c753261d1 100644
--- a/property/pom.xml
+++ b/property/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
property
diff --git a/prototype/index.md b/prototype/README.md
similarity index 100%
rename from prototype/index.md
rename to prototype/README.md
diff --git a/prototype/pom.xml b/prototype/pom.xml
index da1aa0fd2..7fb43402f 100644
--- a/prototype/pom.xml
+++ b/prototype/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
prototype
diff --git a/proxy/index.md b/proxy/README.md
similarity index 100%
rename from proxy/index.md
rename to proxy/README.md
diff --git a/proxy/pom.xml b/proxy/pom.xml
index 4640a1bba..9936be34b 100644
--- a/proxy/pom.xml
+++ b/proxy/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
proxy
diff --git a/publish-subscribe/index.md b/publish-subscribe/README.md
similarity index 100%
rename from publish-subscribe/index.md
rename to publish-subscribe/README.md
diff --git a/publish-subscribe/pom.xml b/publish-subscribe/pom.xml
index bfa4838e7..1ff97ca47 100644
--- a/publish-subscribe/pom.xml
+++ b/publish-subscribe/pom.xml
@@ -28,7 +28,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
publish-subscribe
diff --git a/reactor/index.md b/reactor/README.md
similarity index 100%
rename from reactor/index.md
rename to reactor/README.md
diff --git a/reactor/pom.xml b/reactor/pom.xml
index 9e228ce6e..80a15f9d3 100644
--- a/reactor/pom.xml
+++ b/reactor/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
reactor
diff --git a/reader-writer-lock/index.md b/reader-writer-lock/README.md
similarity index 100%
rename from reader-writer-lock/index.md
rename to reader-writer-lock/README.md
diff --git a/reader-writer-lock/pom.xml b/reader-writer-lock/pom.xml
index dbfafff66..0391ea291 100644
--- a/reader-writer-lock/pom.xml
+++ b/reader-writer-lock/pom.xml
@@ -30,7 +30,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
reader-writer-lock
diff --git a/repository/index.md b/repository/README.md
similarity index 100%
rename from repository/index.md
rename to repository/README.md
diff --git a/repository/pom.xml b/repository/pom.xml
index 82e4b4d67..b8b81ee05 100644
--- a/repository/pom.xml
+++ b/repository/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
repository
diff --git a/repository/src/main/java/com/iluwatar/repository/App.java b/repository/src/main/java/com/iluwatar/repository/App.java
index df24e1424..2807ae7ca 100644
--- a/repository/src/main/java/com/iluwatar/repository/App.java
+++ b/repository/src/main/java/com/iluwatar/repository/App.java
@@ -100,6 +100,8 @@ public class App {
System.out.println(person);
}
+ repository.deleteAll();
+
context.close();
}
diff --git a/repository/src/main/resources/applicationContext.xml b/repository/src/main/resources/applicationContext.xml
index a3b5162da..8b4b81bb7 100644
--- a/repository/src/main/resources/applicationContext.xml
+++ b/repository/src/main/resources/applicationContext.xml
@@ -54,7 +54,8 @@
diff --git a/resource-acquisition-is-initialization/index.md b/resource-acquisition-is-initialization/README.md
similarity index 100%
rename from resource-acquisition-is-initialization/index.md
rename to resource-acquisition-is-initialization/README.md
diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml
index e79ec99ee..63971d97c 100644
--- a/resource-acquisition-is-initialization/pom.xml
+++ b/resource-acquisition-is-initialization/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
resource-acquisition-is-initialization
diff --git a/servant/index.md b/servant/README.md
similarity index 100%
rename from servant/index.md
rename to servant/README.md
diff --git a/servant/pom.xml b/servant/pom.xml
index 0161e71f6..a102ad348 100644
--- a/servant/pom.xml
+++ b/servant/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
servant
diff --git a/service-layer/index.md b/service-layer/README.md
similarity index 100%
rename from service-layer/index.md
rename to service-layer/README.md
diff --git a/service-layer/pom.xml b/service-layer/pom.xml
index ff88256a9..c5e4eb8d9 100644
--- a/service-layer/pom.xml
+++ b/service-layer/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
service-layer
diff --git a/service-locator/index.md b/service-locator/README.md
similarity index 100%
rename from service-locator/index.md
rename to service-locator/README.md
diff --git a/service-locator/pom.xml b/service-locator/pom.xml
index 4a64e8615..f07dc93f8 100644
--- a/service-locator/pom.xml
+++ b/service-locator/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
service-locator
diff --git a/singleton/index.md b/singleton/README.md
similarity index 100%
rename from singleton/index.md
rename to singleton/README.md
diff --git a/singleton/pom.xml b/singleton/pom.xml
index 66c02e664..8ab7e0686 100644
--- a/singleton/pom.xml
+++ b/singleton/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
singleton
diff --git a/specification/index.md b/specification/README.md
similarity index 100%
rename from specification/index.md
rename to specification/README.md
diff --git a/specification/pom.xml b/specification/pom.xml
index 125c34e0b..c54688919 100644
--- a/specification/pom.xml
+++ b/specification/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
specification
diff --git a/state/index.md b/state/README.md
similarity index 100%
rename from state/index.md
rename to state/README.md
diff --git a/state/pom.xml b/state/pom.xml
index 08b4846e6..2411eb2a7 100644
--- a/state/pom.xml
+++ b/state/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
state
diff --git a/step-builder/index.md b/step-builder/README.md
similarity index 100%
rename from step-builder/index.md
rename to step-builder/README.md
diff --git a/step-builder/pom.xml b/step-builder/pom.xml
index dde7443f9..8d926d118 100644
--- a/step-builder/pom.xml
+++ b/step-builder/pom.xml
@@ -30,7 +30,7 @@
java-design-patterns
com.iluwatar
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
step-builder
diff --git a/strategy/index.md b/strategy/README.md
similarity index 100%
rename from strategy/index.md
rename to strategy/README.md
diff --git a/strategy/pom.xml b/strategy/pom.xml
index 0b6b2dc4e..934ff8775 100644
--- a/strategy/pom.xml
+++ b/strategy/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
strategy
diff --git a/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java b/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java
index d5b752c52..d17ff9041 100644
--- a/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java
+++ b/strategy/src/main/java/com/iluwatar/strategy/MeleeStrategy.java
@@ -31,6 +31,6 @@ public class MeleeStrategy implements DragonSlayingStrategy {
@Override
public void execute() {
- System.out.println("With your Excalibur you severe the dragon's head!");
+ System.out.println("With your Excalibur you sever the dragon's head!");
}
}
diff --git a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java
index 341db8caf..35f4c1a82 100644
--- a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java
+++ b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java
@@ -52,7 +52,7 @@ public class DragonSlayingStrategyTest {
return Arrays.asList(
new Object[]{
new MeleeStrategy(),
- "With your Excalibur you severe the dragon's head!"
+ "With your Excalibur you sever the dragon's head!"
},
new Object[]{
new ProjectileStrategy(),
diff --git a/template-method/index.md b/template-method/README.md
similarity index 100%
rename from template-method/index.md
rename to template-method/README.md
diff --git a/template-method/pom.xml b/template-method/pom.xml
index 0feb89c02..af0b19cb4 100644
--- a/template-method/pom.xml
+++ b/template-method/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
template-method
diff --git a/thread-pool/index.md b/thread-pool/README.md
similarity index 100%
rename from thread-pool/index.md
rename to thread-pool/README.md
diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml
index a2e683359..824dcd7af 100644
--- a/thread-pool/pom.xml
+++ b/thread-pool/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
thread-pool
diff --git a/tolerant-reader/index.md b/tolerant-reader/README.md
similarity index 100%
rename from tolerant-reader/index.md
rename to tolerant-reader/README.md
diff --git a/tolerant-reader/pom.xml b/tolerant-reader/pom.xml
index 6c8c96b3c..249788da0 100644
--- a/tolerant-reader/pom.xml
+++ b/tolerant-reader/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
tolerant-reader
diff --git a/twin/index.md b/twin/README.md
similarity index 100%
rename from twin/index.md
rename to twin/README.md
diff --git a/twin/pom.xml b/twin/pom.xml
index dc23b26ef..010bf37b2 100644
--- a/twin/pom.xml
+++ b/twin/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
twin
diff --git a/value-object/index.md b/value-object/README.md
similarity index 100%
rename from value-object/index.md
rename to value-object/README.md
diff --git a/value-object/pom.xml b/value-object/pom.xml
index 3cbb7bb86..66b2342eb 100644
--- a/value-object/pom.xml
+++ b/value-object/pom.xml
@@ -30,7 +30,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
value-object
diff --git a/visitor/index.md b/visitor/README.md
similarity index 100%
rename from visitor/index.md
rename to visitor/README.md
diff --git a/visitor/pom.xml b/visitor/pom.xml
index cdffb0151..1b594b179 100644
--- a/visitor/pom.xml
+++ b/visitor/pom.xml
@@ -29,7 +29,7 @@
com.iluwatar
java-design-patterns
- 1.11.0-SNAPSHOT
+ 1.12.0-SNAPSHOT
visitor