From 9891c2e17b131ba16c168059c4881f9bfb3b2efc Mon Sep 17 00:00:00 2001 From: waisuan Date: Wed, 28 Oct 2015 23:55:47 +0800 Subject: [PATCH 1/4] Issue #273:Caching Patterns [new pattern] --- caching/.gitignore | 1 + caching/etc/caching.png | Bin 0 -> 51452 bytes caching/etc/caching.ucls | 106 +++++++++++++ caching/index.md | 24 +++ caching/pom.xml | 51 ++++++ .../src/main/java/com/wssia/caching/App.java | 100 ++++++++++++ .../java/com/wssia/caching/AppManager.java | 65 ++++++++ .../java/com/wssia/caching/CacheStore.java | 104 +++++++++++++ .../java/com/wssia/caching/CachingPolicy.java | 20 +++ .../java/com/wssia/caching/DBManager.java | 92 +++++++++++ .../main/java/com/wssia/caching/LRUCache.java | 146 ++++++++++++++++++ .../java/com/wssia/caching/UserAccount.java | 47 ++++++ .../test/java/com/wssia/caching/AppTest.java | 41 +++++ pom.xml | 1 + 14 files changed, 798 insertions(+) create mode 100644 caching/.gitignore create mode 100644 caching/etc/caching.png create mode 100644 caching/etc/caching.ucls create mode 100644 caching/index.md create mode 100644 caching/pom.xml create mode 100644 caching/src/main/java/com/wssia/caching/App.java create mode 100644 caching/src/main/java/com/wssia/caching/AppManager.java create mode 100644 caching/src/main/java/com/wssia/caching/CacheStore.java create mode 100644 caching/src/main/java/com/wssia/caching/CachingPolicy.java create mode 100644 caching/src/main/java/com/wssia/caching/DBManager.java create mode 100644 caching/src/main/java/com/wssia/caching/LRUCache.java create mode 100644 caching/src/main/java/com/wssia/caching/UserAccount.java create mode 100644 caching/src/test/java/com/wssia/caching/AppTest.java diff --git a/caching/.gitignore b/caching/.gitignore new file mode 100644 index 00000000..b83d2226 --- /dev/null +++ b/caching/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/caching/etc/caching.png b/caching/etc/caching.png new file mode 100644 index 0000000000000000000000000000000000000000..e69df17ea47351789cce03c927b20c2c0ab88be1 GIT binary patch literal 51452 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/caching/index.md b/caching/index.md new file mode 100644 index 00000000..f79f13e4 --- /dev/null +++ b/caching/index.md @@ -0,0 +1,24 @@ +--- +layout: pattern +title: Caching +folder: caching +permalink: /patterns/caching/ +categories: Other +tags: + - Java +--- + +**Intent:** To avoid expensive re-acquisition of resources by not releasing +the resources immediately after their use. The resources retain their identity, are kept in some +fast-access storage, and are re-used to avoid having to acquire them again. + +![alt text](./etc/caching.png "Caching") + +**Applicability:** Use the Caching pattern(s) when + +* Repetitious acquisition, initialization, and release of the same resource causes unnecessary performance overhead. + +**Credits** + +* [Write-through, write-around, write-back: Cache explained](http://www.computerweekly.com/feature/Write-through-write-around-write-back-Cache-explained) +* [Read-Through, Write-Through, Write-Behind, and Refresh-Ahead Caching](https://docs.oracle.com/cd/E15357_01/coh.360/e15723/cache_rtwtwbra.htm#COHDG5177) diff --git a/caching/pom.xml b/caching/pom.xml new file mode 100644 index 00000000..180320ee --- /dev/null +++ b/caching/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.7.0 + + caching + + + junit + junit + test + + + org.mongodb + mongodb-driver + 3.0.4 + + + org.mongodb + mongodb-driver-core + 3.0.4 + + + org.mongodb + bson + 3.0.4 + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19 + + true + + + + + diff --git a/caching/src/main/java/com/wssia/caching/App.java b/caching/src/main/java/com/wssia/caching/App.java new file mode 100644 index 00000000..afdbd7d5 --- /dev/null +++ b/caching/src/main/java/com/wssia/caching/App.java @@ -0,0 +1,100 @@ +package main.java.com.wssia.caching; + +/** + * + * The Caching pattern describes how to avoid expensive re-acquisition of resources by not releasing + * the resources immediately after their use. The resources retain their identity, are kept in some + * fast-access storage, and are re-used to avoid having to acquire them again. There are three main + * caching strategies/techniques in this pattern; each with their own pros and cons. They are: + * write-through which writes data to the cache and DB in a single transaction, + * write-around which writes data immediately into the DB instead of the cache, and + * write-behind which writes data into the cache initially whilst the data is only + * written into the DB when the cache is full. The read-through strategy is also + * included in the mentioned three strategies -- returns data from the cache to the caller if + * it exists else queries from DB and stores it into the cache for future use. These + * strategies determine when the data in the cache should be written back to the backing store (i.e. + * Database) and help keep both data sources synchronized/up-to-date. This pattern can improve + * performance and also helps to maintain consistency between data held in the cache and the data in + * the underlying data store. + *

+ * In this example, the user account ({@link UserAccount}) entity is used as the underlying + * application data. The cache itself is implemented as an internal (Java) data structure. It adopts + * a Least-Recently-Used (LRU) strategy for evicting data from itself when its full. The three + * strategies are individually tested. The testing of the cache is restricted towards saving and + * querying of user accounts from the underlying data store ( {@link DBManager}). The main class ( + * {@link App} is not aware of the underlying mechanics of the application (i.e. save and query) and + * whether the data is coming from the cache or the DB (i.e. separation of concern). The AppManager + * ({@link AppManager}) handles the transaction of data to-and-from the underlying data store + * (depending on the preferred caching policy/strategy). + * + * App --> AppManager --> CacheStore/LRUCache/CachingPolicy --> DBManager + *

+ * + * @see CacheStore + * @See LRUCache + * @see CachingPolicy + * + */ +public class App { + + /** + * Read-through and write-through + */ + public void useReadAndWriteThroughStrategy() { + System.out.println("# CachingPolicy.THROUGH"); + AppManager.initCachingPolicy(CachingPolicy.THROUGH); + + UserAccount userAccount1 = new UserAccount("001", "John", "He is a boy."); + + AppManager.save(userAccount1); + System.out.println(AppManager.printCacheContent()); + userAccount1 = AppManager.find("001"); + userAccount1 = AppManager.find("001"); + } + + /** + * Read-through and write-around + */ + public void useReadThroughAndWriteAroundStrategy() { + System.out.println("# CachingPolicy.AROUND"); + AppManager.initCachingPolicy(CachingPolicy.AROUND); + + UserAccount userAccount2 = new UserAccount("002", "Jane", "She is a girl."); + + AppManager.save(userAccount2); + System.out.println(AppManager.printCacheContent()); + userAccount2 = AppManager.find("002"); + System.out.println(AppManager.printCacheContent()); + userAccount2 = AppManager.find("002"); + userAccount2.setUserName("Jane G."); + AppManager.save(userAccount2); + System.out.println(AppManager.printCacheContent()); + userAccount2 = AppManager.find("002"); + System.out.println(AppManager.printCacheContent()); + userAccount2 = AppManager.find("002"); + } + + /** + * Read-through and write-behind + */ + public void useReadThroughAndWriteBehindStrategy() { + System.out.println("# CachingPolicy.BEHIND"); + AppManager.initCachingPolicy(CachingPolicy.BEHIND); + + UserAccount userAccount3 = new UserAccount("003", "Adam", "He likes food."); + UserAccount userAccount4 = new UserAccount("004", "Rita", "She hates cats."); + UserAccount userAccount5 = new UserAccount("005", "Isaac", "He is allergic to mustard."); + + AppManager.save(userAccount3); + AppManager.save(userAccount4); + AppManager.save(userAccount5); + System.out.println(AppManager.printCacheContent()); + userAccount3 = AppManager.find("003"); + System.out.println(AppManager.printCacheContent()); + UserAccount userAccount6 = new UserAccount("006", "Yasha", "She is an only child."); + AppManager.save(userAccount6); + System.out.println(AppManager.printCacheContent()); + userAccount4 = AppManager.find("004"); + System.out.println(AppManager.printCacheContent()); + } +} diff --git a/caching/src/main/java/com/wssia/caching/AppManager.java b/caching/src/main/java/com/wssia/caching/AppManager.java new file mode 100644 index 00000000..96b5fbdc --- /dev/null +++ b/caching/src/main/java/com/wssia/caching/AppManager.java @@ -0,0 +1,65 @@ +package main.java.com.wssia.caching; + +import java.text.ParseException; + +/** + * + * AppManager helps to bridge the gap in communication between the main class and the application's + * back-end. DB connection is initialized through this class. The chosen caching strategy/policy is + * also initialized here. Before the cache can be used, the size of the cache has to be set. + * Depending on the chosen caching policy, AppManager will call the appropriate function in the + * CacheStore class. + * + */ +public class AppManager { + + private static CachingPolicy cachingPolicy; + + public static void init() { + try { + DBManager.connect(); + } catch (ParseException e) { + e.printStackTrace(); + } + } + + public static void initCachingPolicy(CachingPolicy policy) { + cachingPolicy = policy; + if (cachingPolicy == CachingPolicy.BEHIND) { + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + CacheStore.flushCache(); + } + })); + } + CacheStore.clearCache(); + } + + public static void initCacheCapacity(int capacity) { + CacheStore.initCapacity(capacity); + } + + public static UserAccount find(String userID) { + if (cachingPolicy == CachingPolicy.THROUGH || cachingPolicy == CachingPolicy.AROUND) { + return CacheStore.readThrough(userID); + } else if (cachingPolicy == CachingPolicy.BEHIND) { + return CacheStore.readThroughWithWriteBackPolicy(userID); + } + return null; + } + + public static void save(UserAccount userAccount) { + if (cachingPolicy == CachingPolicy.THROUGH) { + CacheStore.writeThrough(userAccount); + } else if (cachingPolicy == CachingPolicy.AROUND) { + CacheStore.writeAround(userAccount); + } else if (cachingPolicy == CachingPolicy.BEHIND) { + CacheStore.writeBehind(userAccount); + } + } + + public static String printCacheContent() { + return CacheStore.print(); + } +} diff --git a/caching/src/main/java/com/wssia/caching/CacheStore.java b/caching/src/main/java/com/wssia/caching/CacheStore.java new file mode 100644 index 00000000..edb644bd --- /dev/null +++ b/caching/src/main/java/com/wssia/caching/CacheStore.java @@ -0,0 +1,104 @@ +package main.java.com.wssia.caching; + +import java.util.ArrayList; + +/** + * + * The caching strategies are implemented in this class. + * + */ +public class CacheStore { + + static LRUCache cache = null; + + public static void initCapacity(int capacity) { + if (null == cache) + cache = new LRUCache(capacity); + else + cache.setCapacity(capacity); + } + + public static UserAccount readThrough(String userID) { + if (cache.contains(userID)) { + System.out.println("# Cache Hit!"); + return cache.get(userID); + } + System.out.println("# Cache Miss!"); + UserAccount userAccount = DBManager.readFromDB(userID); + cache.set(userID, userAccount); + return userAccount; + } + + public static void writeThrough(UserAccount userAccount) { + if (cache.contains(userAccount.getUserID())) { + DBManager.updateDB(userAccount); + } else { + DBManager.writeToDB(userAccount); + } + cache.set(userAccount.getUserID(), userAccount); + } + + public static void writeAround(UserAccount userAccount) { + if (cache.contains(userAccount.getUserID())) { + DBManager.updateDB(userAccount); + cache.invalidate(userAccount.getUserID()); // Cache data has been updated -- remove older + // version from cache. + } else { + DBManager.writeToDB(userAccount); + } + } + + public static UserAccount readThroughWithWriteBackPolicy(String userID) { + if (cache.contains(userID)) { + System.out.println("# Cache Hit!"); + return cache.get(userID); + } + System.out.println("# Cache Miss!"); + UserAccount userAccount = DBManager.readFromDB(userID); + if (cache.isFull()) { + System.out.println("# Cache is FULL! Writing LRU data to DB..."); + UserAccount toBeWrittenToDB = cache.getLRUData(); + DBManager.upsertDB(toBeWrittenToDB); + } + cache.set(userID, userAccount); + return userAccount; + } + + public static void writeBehind(UserAccount userAccount) { + if (cache.isFull() && !cache.contains(userAccount.getUserID())) { + System.out.println("# Cache is FULL! Writing LRU data to DB..."); + UserAccount toBeWrittenToDB = cache.getLRUData(); + DBManager.upsertDB(toBeWrittenToDB); + } + cache.set(userAccount.getUserID(), userAccount); + } + + public static void clearCache() { + if (null != cache) + cache.clear(); + } + + /** + * Writes remaining content in the cache into the DB. + */ + public static void flushCache() { + System.out.println("# flushCache..."); + if (null == cache) + return; + ArrayList listOfUserAccounts = cache.getCacheDataInListForm(); + for (UserAccount userAccount : listOfUserAccounts) { + DBManager.upsertDB(userAccount); + } + } + + public static String print() { + ArrayList listOfUserAccounts = cache.getCacheDataInListForm(); + StringBuilder sb = new StringBuilder(); + sb.append("\n--CACHE CONTENT--\n"); + for (UserAccount userAccount : listOfUserAccounts) { + sb.append(userAccount.toString() + "\n"); + } + sb.append("----\n"); + return sb.toString(); + } +} diff --git a/caching/src/main/java/com/wssia/caching/CachingPolicy.java b/caching/src/main/java/com/wssia/caching/CachingPolicy.java new file mode 100644 index 00000000..ee51c036 --- /dev/null +++ b/caching/src/main/java/com/wssia/caching/CachingPolicy.java @@ -0,0 +1,20 @@ +package main.java.com.wssia.caching; + +/** + * + * Enum class containing the three caching strategies implemented in the pattern. + * + */ +public enum CachingPolicy { + THROUGH("through"), AROUND("around"), BEHIND("behind"); + + private String policy; + + private CachingPolicy(String policy) { + this.policy = policy; + } + + public String getPolicy() { + return policy; + } +} diff --git a/caching/src/main/java/com/wssia/caching/DBManager.java b/caching/src/main/java/com/wssia/caching/DBManager.java new file mode 100644 index 00000000..20918b22 --- /dev/null +++ b/caching/src/main/java/com/wssia/caching/DBManager.java @@ -0,0 +1,92 @@ +package main.java.com.wssia.caching; + +import java.text.ParseException; + +import org.bson.Document; + +import com.mongodb.MongoClient; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.UpdateOptions; + +/** + * + * DBManager handles the communication with the underlying data store i.e. Database. It contains the + * implemented methods for querying, inserting, and updating data. MongoDB was used as the database + * for the application. + * + */ +public class DBManager { + + private static MongoClient mongoClient; + private static MongoDatabase db; + + public static void connect() throws ParseException { + mongoClient = new MongoClient(); + db = mongoClient.getDatabase("test"); + } + + public static UserAccount readFromDB(String userID) { + if (null == db) { + try { + connect(); + } catch (ParseException e) { + e.printStackTrace(); + } + } + FindIterable iterable = + db.getCollection("user_accounts").find(new Document("userID", userID)); + if (iterable == null) + return null; + Document doc = iterable.first(); + UserAccount userAccount = + new UserAccount(userID, doc.getString("userName"), doc.getString("additionalInfo")); + return userAccount; + } + + public static void writeToDB(UserAccount userAccount) { + if (null == db) { + try { + connect(); + } catch (ParseException e) { + e.printStackTrace(); + } + } + db.getCollection("user_accounts").insertOne( + new Document("userID", userAccount.getUserID()).append("userName", + userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo())); + } + + public static void updateDB(UserAccount userAccount) { + if (null == db) { + try { + connect(); + } catch (ParseException e) { + e.printStackTrace(); + } + } + db.getCollection("user_accounts").updateOne( + new Document("userID", userAccount.getUserID()), + new Document("$set", new Document("userName", userAccount.getUserName()).append( + "additionalInfo", userAccount.getAdditionalInfo()))); + } + + /** + * + * Insert data into DB if it does not exist. Else, update it. + */ + public static void upsertDB(UserAccount userAccount) { + if (null == db) { + try { + connect(); + } catch (ParseException e) { + e.printStackTrace(); + } + } + db.getCollection("user_accounts").updateOne( + new Document("userID", userAccount.getUserID()), + new Document("$set", new Document("userID", userAccount.getUserID()).append("userName", + userAccount.getUserName()).append("additionalInfo", userAccount.getAdditionalInfo())), + new UpdateOptions().upsert(true)); + } +} diff --git a/caching/src/main/java/com/wssia/caching/LRUCache.java b/caching/src/main/java/com/wssia/caching/LRUCache.java new file mode 100644 index 00000000..c69e7e3f --- /dev/null +++ b/caching/src/main/java/com/wssia/caching/LRUCache.java @@ -0,0 +1,146 @@ +package main.java.com.wssia.caching; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * + * Data structure/implementation of the application's cache. The data structure consists of a hash + * table attached with a doubly linked-list. The linked-list helps in capturing and maintaining the + * LRU data in the cache. When a data is queried (from the cache), added (to the cache), or updated, + * the data is moved to the front of the list to depict itself as the most-recently-used data. The + * LRU data is always at the end of the list. + * + */ +public class LRUCache { + + class Node { + String userID; + UserAccount userAccount; + Node previous; + Node next; + + public Node(String userID, UserAccount userAccount) { + this.userID = userID; + this.userAccount = userAccount; + } + } + + int capacity; + HashMap cache = new HashMap(); + Node head = null; + Node end = null; + + public LRUCache(int capacity) { + this.capacity = capacity; + } + + public UserAccount get(String userID) { + if (cache.containsKey(userID)) { + Node node = cache.get(userID); + remove(node); + setHead(node); + return node.userAccount; + } + return null; + } + + /** + * + * Remove node from linked list. + */ + public void remove(Node node) { + if (node.previous != null) { + node.previous.next = node.next; + } else { + head = node.next; + } + if (node.next != null) { + node.next.previous = node.previous; + } else { + end = node.previous; + } + } + + /** + * + * Move node to the front of the list. + */ + public void setHead(Node node) { + node.next = head; + node.previous = null; + if (head != null) + head.previous = node; + head = node; + if (end == null) + end = head; + } + + public void set(String userID, UserAccount userAccount) { + if (cache.containsKey(userID)) { + Node old = cache.get(userID); + old.userAccount = userAccount; + remove(old); + setHead(old); + } else { + Node newNode = new Node(userID, userAccount); + if (cache.size() >= capacity) { + System.out.println("# Cache is FULL! Removing " + end.userID + " from cache..."); + cache.remove(end.userID); // remove LRU data from cache. + remove(end); + setHead(newNode); + } else { + setHead(newNode); + } + cache.put(userID, newNode); + } + } + + public boolean contains(String userID) { + return cache.containsKey(userID); + } + + public void invalidate(String userID) { + System.out.println("# " + userID + " has been updated! Removing older version from cache..."); + Node toBeRemoved = cache.get(userID); + remove(toBeRemoved); + cache.remove(userID); + } + + public boolean isFull() { + return cache.size() >= capacity; + } + + public UserAccount getLRUData() { + return end.userAccount; + } + + public void clear() { + head = null; + end = null; + cache.clear(); + } + + /** + * + * Returns cache data in list form. + */ + public ArrayList getCacheDataInListForm() { + ArrayList listOfCacheData = new ArrayList(); + Node temp = head; + while (temp != null) { + listOfCacheData.add(temp.userAccount); + temp = temp.next; + } + return listOfCacheData; + } + + public void setCapacity(int newCapacity) { + if (capacity > newCapacity) { + clear(); // Behavior can be modified to accommodate for decrease in cache size. For now, we'll + // just clear the cache. + } else { + this.capacity = newCapacity; + } + } +} diff --git a/caching/src/main/java/com/wssia/caching/UserAccount.java b/caching/src/main/java/com/wssia/caching/UserAccount.java new file mode 100644 index 00000000..a9fe36f7 --- /dev/null +++ b/caching/src/main/java/com/wssia/caching/UserAccount.java @@ -0,0 +1,47 @@ +package main.java.com.wssia.caching; + +/** + * + * Entity class (stored in cache and DB) used in the application. + * + */ +public class UserAccount { + private String userID; + private String userName; + private String additionalInfo; + + public UserAccount(String userID, String userName, String additionalInfo) { + this.userID = userID; + this.userName = userName; + this.additionalInfo = additionalInfo; + } + + public String getUserID() { + return userID; + } + + public void setUserID(String userID) { + this.userID = userID; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getAdditionalInfo() { + return additionalInfo; + } + + public void setAdditionalInfo(String additionalInfo) { + this.additionalInfo = additionalInfo; + } + + @Override + public String toString() { + return userID + ", " + userName + ", " + additionalInfo; + } +} diff --git a/caching/src/test/java/com/wssia/caching/AppTest.java b/caching/src/test/java/com/wssia/caching/AppTest.java new file mode 100644 index 00000000..3a93afec --- /dev/null +++ b/caching/src/test/java/com/wssia/caching/AppTest.java @@ -0,0 +1,41 @@ +package test.java.com.wssia.caching; + +import main.java.com.wssia.caching.App; +import main.java.com.wssia.caching.AppManager; + +import org.junit.Before; +import org.junit.Test; + +/** + * + * Application test + * + */ +public class AppTest { + App app; + + /** + * Setup of application test includes: initializing DB connection and cache size/capacity. + */ + @Before + public void setUp() { + AppManager.init(); + AppManager.initCacheCapacity(3); + app = new App(); + } + + @Test + public void testReadAndWriteThroughStrategy() { + app.useReadAndWriteThroughStrategy(); + } + + @Test + public void testReadThroughAndWriteAroundStrategy() { + app.useReadThroughAndWriteAroundStrategy(); + } + + @Test + public void testReadThroughAndWriteBehindStrategy() { + app.useReadThroughAndWriteBehindStrategy(); + } +} diff --git a/pom.xml b/pom.xml index 4cb30df3..36e43727 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,7 @@ message-channel fluentinterface reactor + caching From d0f50099968c685f05afab26bb771fad4ad831ee Mon Sep 17 00:00:00 2001 From: waisuan Date: Thu, 29 Oct 2015 00:57:41 +0800 Subject: [PATCH 2/4] Issue #273: Changed DB to internal Java data structure to avoid compilation errors + decrease in code coverage --- caching/etc/caching.png | Bin 51452 -> 56234 bytes caching/etc/caching.ucls | 2 +- caching/pom.xml | 6 ++-- .../java/com/wssia/caching/AppManager.java | 20 +++++++++--- .../java/com/wssia/caching/CacheStore.java | 2 +- .../java/com/wssia/caching/DBManager.java | 30 ++++++++++++++++++ .../main/java/com/wssia/caching/LRUCache.java | 2 +- .../test/java/com/wssia/caching/AppTest.java | 5 ++- 8 files changed, 55 insertions(+), 12 deletions(-) diff --git a/caching/etc/caching.png b/caching/etc/caching.png index e69df17ea47351789cce03c927b20c2c0ab88be1..6b3b2d0556c51b7c593028b2c9120a00c47716c1 100644 GIT binary patch literal 56234 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 literal 51452 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 - + diff --git a/caching/pom.xml b/caching/pom.xml index 180320ee..d2284a5f 100644 --- a/caching/pom.xml +++ b/caching/pom.xml @@ -33,8 +33,8 @@ @@ -43,7 +43,7 @@ maven-surefire-plugin 2.19 - true + false diff --git a/caching/src/main/java/com/wssia/caching/AppManager.java b/caching/src/main/java/com/wssia/caching/AppManager.java index 96b5fbdc..cc3c665c 100644 --- a/caching/src/main/java/com/wssia/caching/AppManager.java +++ b/caching/src/main/java/com/wssia/caching/AppManager.java @@ -15,11 +15,21 @@ public class AppManager { private static CachingPolicy cachingPolicy; - public static void init() { - try { - DBManager.connect(); - } catch (ParseException e) { - e.printStackTrace(); + /** + * + * Developer/Tester is able to choose whether the application should use MongoDB as its underlying + * data storage or a simple Java data structure to (temporarily) store the data/objects during + * runtime. + */ + public static void initDB(boolean useMongoDB) { + if (useMongoDB) { + try { + DBManager.connect(); + } catch (ParseException e) { + e.printStackTrace(); + } + } else { + DBManager.createVirtualDB(); } } diff --git a/caching/src/main/java/com/wssia/caching/CacheStore.java b/caching/src/main/java/com/wssia/caching/CacheStore.java index edb644bd..5eb231cc 100644 --- a/caching/src/main/java/com/wssia/caching/CacheStore.java +++ b/caching/src/main/java/com/wssia/caching/CacheStore.java @@ -42,7 +42,7 @@ public static void writeAround(UserAccount userAccount) { if (cache.contains(userAccount.getUserID())) { DBManager.updateDB(userAccount); cache.invalidate(userAccount.getUserID()); // Cache data has been updated -- remove older - // version from cache. + // version from cache. } else { DBManager.writeToDB(userAccount); } diff --git a/caching/src/main/java/com/wssia/caching/DBManager.java b/caching/src/main/java/com/wssia/caching/DBManager.java index 20918b22..0222b595 100644 --- a/caching/src/main/java/com/wssia/caching/DBManager.java +++ b/caching/src/main/java/com/wssia/caching/DBManager.java @@ -1,6 +1,7 @@ package main.java.com.wssia.caching; import java.text.ParseException; +import java.util.HashMap; import org.bson.Document; @@ -15,18 +16,35 @@ * implemented methods for querying, inserting, and updating data. MongoDB was used as the database * for the application. * + * Developer/Tester is able to choose whether the application should use MongoDB as its underlying + * data storage (connect()) or a simple Java data structure to (temporarily) store the data/objects + * during runtime (createVirtualDB()). */ public class DBManager { private static MongoClient mongoClient; private static MongoDatabase db; + private static boolean useMongoDB; + + private static HashMap virtualDB; + + public static void createVirtualDB() { + useMongoDB = false; + virtualDB = new HashMap(); + } public static void connect() throws ParseException { + useMongoDB = true; mongoClient = new MongoClient(); db = mongoClient.getDatabase("test"); } public static UserAccount readFromDB(String userID) { + if (!useMongoDB) { + if (virtualDB.containsKey(userID)) + return virtualDB.get(userID); + return null; + } if (null == db) { try { connect(); @@ -45,6 +63,10 @@ public static UserAccount readFromDB(String userID) { } public static void writeToDB(UserAccount userAccount) { + if (!useMongoDB) { + virtualDB.put(userAccount.getUserID(), userAccount); + return; + } if (null == db) { try { connect(); @@ -58,6 +80,10 @@ public static void writeToDB(UserAccount userAccount) { } public static void updateDB(UserAccount userAccount) { + if (!useMongoDB) { + virtualDB.put(userAccount.getUserID(), userAccount); + return; + } if (null == db) { try { connect(); @@ -76,6 +102,10 @@ public static void updateDB(UserAccount userAccount) { * Insert data into DB if it does not exist. Else, update it. */ public static void upsertDB(UserAccount userAccount) { + if (!useMongoDB) { + virtualDB.put(userAccount.getUserID(), userAccount); + return; + } if (null == db) { try { connect(); diff --git a/caching/src/main/java/com/wssia/caching/LRUCache.java b/caching/src/main/java/com/wssia/caching/LRUCache.java index c69e7e3f..1389a9bc 100644 --- a/caching/src/main/java/com/wssia/caching/LRUCache.java +++ b/caching/src/main/java/com/wssia/caching/LRUCache.java @@ -138,7 +138,7 @@ public ArrayList getCacheDataInListForm() { public void setCapacity(int newCapacity) { if (capacity > newCapacity) { clear(); // Behavior can be modified to accommodate for decrease in cache size. For now, we'll - // just clear the cache. + // just clear the cache. } else { this.capacity = newCapacity; } diff --git a/caching/src/test/java/com/wssia/caching/AppTest.java b/caching/src/test/java/com/wssia/caching/AppTest.java index 3a93afec..c2d13ce0 100644 --- a/caching/src/test/java/com/wssia/caching/AppTest.java +++ b/caching/src/test/java/com/wssia/caching/AppTest.java @@ -19,7 +19,10 @@ public class AppTest { */ @Before public void setUp() { - AppManager.init(); + AppManager.initDB(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests + // to avoid Maven compilation errors. Set flag to true to run the + // tests with MongoDB (provided that MongoDB is installed and socket + // connection is open). AppManager.initCacheCapacity(3); app = new App(); } From 6418a6c2b608035c7c00a37308ea6f9da36c5d77 Mon Sep 17 00:00:00 2001 From: waisuan Date: Mon, 2 Nov 2015 01:40:38 +0800 Subject: [PATCH 3/4] Issue #273: Fixed issues based on review remarks --- .../com/{wssia => iluwatar}/caching/App.java | 19 ++++++++++++++++++- .../caching/AppManager.java | 2 +- .../caching/CacheStore.java | 2 +- .../caching/CachingPolicy.java | 2 +- .../caching/DBManager.java | 7 +++++-- .../{wssia => iluwatar}/caching/LRUCache.java | 2 +- .../caching/UserAccount.java | 2 +- .../{wssia => iluwatar}/caching/AppTest.java | 5 +---- 8 files changed, 29 insertions(+), 12 deletions(-) rename caching/src/main/java/com/{wssia => iluwatar}/caching/App.java (86%) rename caching/src/main/java/com/{wssia => iluwatar}/caching/AppManager.java (98%) rename caching/src/main/java/com/{wssia => iluwatar}/caching/CacheStore.java (98%) rename caching/src/main/java/com/{wssia => iluwatar}/caching/CachingPolicy.java (90%) rename caching/src/main/java/com/{wssia => iluwatar}/caching/DBManager.java (98%) rename caching/src/main/java/com/{wssia => iluwatar}/caching/LRUCache.java (98%) rename caching/src/main/java/com/{wssia => iluwatar}/caching/UserAccount.java (96%) rename caching/src/test/java/com/{wssia => iluwatar}/caching/AppTest.java (88%) diff --git a/caching/src/main/java/com/wssia/caching/App.java b/caching/src/main/java/com/iluwatar/caching/App.java similarity index 86% rename from caching/src/main/java/com/wssia/caching/App.java rename to caching/src/main/java/com/iluwatar/caching/App.java index afdbd7d5..423e0ee8 100644 --- a/caching/src/main/java/com/wssia/caching/App.java +++ b/caching/src/main/java/com/iluwatar/caching/App.java @@ -1,4 +1,4 @@ -package main.java.com.wssia.caching; +package com.iluwatar.caching; /** * @@ -37,6 +37,23 @@ */ public class App { + /** + * Program entry point + * + * @param args command line args + */ + public static void main(String[] args) { + AppManager.initDB(false); // VirtualDB (instead of MongoDB) was used in running the JUnit tests + // and the App class to avoid Maven compilation errors. Set flag to + // true to run the tests with MongoDB (provided that MongoDB is + // installed and socket connection is open). + AppManager.initCacheCapacity(3); + App app = new App(); + app.useReadAndWriteThroughStrategy(); + app.useReadThroughAndWriteAroundStrategy(); + app.useReadThroughAndWriteBehindStrategy(); + } + /** * Read-through and write-through */ diff --git a/caching/src/main/java/com/wssia/caching/AppManager.java b/caching/src/main/java/com/iluwatar/caching/AppManager.java similarity index 98% rename from caching/src/main/java/com/wssia/caching/AppManager.java rename to caching/src/main/java/com/iluwatar/caching/AppManager.java index cc3c665c..08132e32 100644 --- a/caching/src/main/java/com/wssia/caching/AppManager.java +++ b/caching/src/main/java/com/iluwatar/caching/AppManager.java @@ -1,4 +1,4 @@ -package main.java.com.wssia.caching; +package com.iluwatar.caching; import java.text.ParseException; diff --git a/caching/src/main/java/com/wssia/caching/CacheStore.java b/caching/src/main/java/com/iluwatar/caching/CacheStore.java similarity index 98% rename from caching/src/main/java/com/wssia/caching/CacheStore.java rename to caching/src/main/java/com/iluwatar/caching/CacheStore.java index 5eb231cc..2041ac14 100644 --- a/caching/src/main/java/com/wssia/caching/CacheStore.java +++ b/caching/src/main/java/com/iluwatar/caching/CacheStore.java @@ -1,4 +1,4 @@ -package main.java.com.wssia.caching; +package com.iluwatar.caching; import java.util.ArrayList; diff --git a/caching/src/main/java/com/wssia/caching/CachingPolicy.java b/caching/src/main/java/com/iluwatar/caching/CachingPolicy.java similarity index 90% rename from caching/src/main/java/com/wssia/caching/CachingPolicy.java rename to caching/src/main/java/com/iluwatar/caching/CachingPolicy.java index ee51c036..314cfaa3 100644 --- a/caching/src/main/java/com/wssia/caching/CachingPolicy.java +++ b/caching/src/main/java/com/iluwatar/caching/CachingPolicy.java @@ -1,4 +1,4 @@ -package main.java.com.wssia.caching; +package com.iluwatar.caching; /** * diff --git a/caching/src/main/java/com/wssia/caching/DBManager.java b/caching/src/main/java/com/iluwatar/caching/DBManager.java similarity index 98% rename from caching/src/main/java/com/wssia/caching/DBManager.java rename to caching/src/main/java/com/iluwatar/caching/DBManager.java index 0222b595..d30ad756 100644 --- a/caching/src/main/java/com/wssia/caching/DBManager.java +++ b/caching/src/main/java/com/iluwatar/caching/DBManager.java @@ -1,4 +1,4 @@ -package main.java.com.wssia.caching; +package com.iluwatar.caching; import java.text.ParseException; import java.util.HashMap; @@ -12,13 +12,16 @@ /** * + *

* DBManager handles the communication with the underlying data store i.e. Database. It contains the * implemented methods for querying, inserting, and updating data. MongoDB was used as the database * for the application. - * + *

+ *

* Developer/Tester is able to choose whether the application should use MongoDB as its underlying * data storage (connect()) or a simple Java data structure to (temporarily) store the data/objects * during runtime (createVirtualDB()). + *

*/ public class DBManager { diff --git a/caching/src/main/java/com/wssia/caching/LRUCache.java b/caching/src/main/java/com/iluwatar/caching/LRUCache.java similarity index 98% rename from caching/src/main/java/com/wssia/caching/LRUCache.java rename to caching/src/main/java/com/iluwatar/caching/LRUCache.java index 1389a9bc..872f9725 100644 --- a/caching/src/main/java/com/wssia/caching/LRUCache.java +++ b/caching/src/main/java/com/iluwatar/caching/LRUCache.java @@ -1,4 +1,4 @@ -package main.java.com.wssia.caching; +package com.iluwatar.caching; import java.util.ArrayList; import java.util.HashMap; diff --git a/caching/src/main/java/com/wssia/caching/UserAccount.java b/caching/src/main/java/com/iluwatar/caching/UserAccount.java similarity index 96% rename from caching/src/main/java/com/wssia/caching/UserAccount.java rename to caching/src/main/java/com/iluwatar/caching/UserAccount.java index a9fe36f7..eff0878a 100644 --- a/caching/src/main/java/com/wssia/caching/UserAccount.java +++ b/caching/src/main/java/com/iluwatar/caching/UserAccount.java @@ -1,4 +1,4 @@ -package main.java.com.wssia.caching; +package com.iluwatar.caching; /** * diff --git a/caching/src/test/java/com/wssia/caching/AppTest.java b/caching/src/test/java/com/iluwatar/caching/AppTest.java similarity index 88% rename from caching/src/test/java/com/wssia/caching/AppTest.java rename to caching/src/test/java/com/iluwatar/caching/AppTest.java index c2d13ce0..ce5cddf0 100644 --- a/caching/src/test/java/com/wssia/caching/AppTest.java +++ b/caching/src/test/java/com/iluwatar/caching/AppTest.java @@ -1,7 +1,4 @@ -package test.java.com.wssia.caching; - -import main.java.com.wssia.caching.App; -import main.java.com.wssia.caching.AppManager; +package com.iluwatar.caching; import org.junit.Before; import org.junit.Test; From 998ba7e6e039275a5e08dff5cb07d47eddf2e503 Mon Sep 17 00:00:00 2001 From: waisuan Date: Mon, 2 Nov 2015 02:11:58 +0800 Subject: [PATCH 4/4] Issue #273: Fixed HTML tags in comments --- .../src/main/java/com/iluwatar/caching/App.java | 2 +- .../main/java/com/iluwatar/caching/DBManager.java | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/caching/src/main/java/com/iluwatar/caching/App.java b/caching/src/main/java/com/iluwatar/caching/App.java index 423e0ee8..c7f55db7 100644 --- a/caching/src/main/java/com/iluwatar/caching/App.java +++ b/caching/src/main/java/com/iluwatar/caching/App.java @@ -28,7 +28,7 @@ * (depending on the preferred caching policy/strategy). * * App --> AppManager --> CacheStore/LRUCache/CachingPolicy --> DBManager - *

+ *

* * @see CacheStore * @See LRUCache diff --git a/caching/src/main/java/com/iluwatar/caching/DBManager.java b/caching/src/main/java/com/iluwatar/caching/DBManager.java index d30ad756..07a5daea 100644 --- a/caching/src/main/java/com/iluwatar/caching/DBManager.java +++ b/caching/src/main/java/com/iluwatar/caching/DBManager.java @@ -12,16 +12,14 @@ /** * - *

- * DBManager handles the communication with the underlying data store i.e. Database. It contains the + *

DBManager handles the communication with the underlying data store i.e. Database. It contains the * implemented methods for querying, inserting, and updating data. MongoDB was used as the database - * for the application. - *

- *

- * Developer/Tester is able to choose whether the application should use MongoDB as its underlying + * for the application.

+ * + *

Developer/Tester is able to choose whether the application should use MongoDB as its underlying * data storage (connect()) or a simple Java data structure to (temporarily) store the data/objects - * during runtime (createVirtualDB()). - *

+ * during runtime (createVirtualDB()).

+ * */ public class DBManager {