How to create a write-behind cache from inmemory to database? - java

My goal is to cache data inmemory for 60s. As soon as the entry is read again from cache, I want to remove it from cache (permit single reads only).
If those 60s expired in the meantime and the entry is still available in cache, I want to writebehind the entry into a database.
Is there any existing technology/spring/apache framework that already offers such a cache?
(sidenote: I don't want to use complex libraries like redis, ehcache etc for such a simple usecase).
If set up manually, I'd be doing as follows. But probably there are better options?
#Service
public class WriteBehindCache {
static class ObjectEntry {
Object data;
LocalDateTime timestamp;
public ObjectEntry(Object data) {
this.data = data;
timestamp = LocalDateTime.now();
}
}
Map<String, ObjectEntry> cache = new ConcurrentHashMap<>();
//batch every minute
#Scheduled(fixedRate = 60000)
public void writeBehind() {
LocalDateTime now = LocalDateTime.now();
List<ObjectEntry> outdated = cache.values()
.filter(entry -> entry.getValue().timestamp.plusSeconds(60).isBefore(now))
.collect(Collectors.toList());
databaseService.persist(outdated);
cache.removeAll(outdated); //pseudocode
}
//always keep most recent entry
public void add(String key, Object data) {
cache.put(key, new ObjectEntry(data));
}
//fallback lookup to database if cache is empty
public Object get(String key) {
ObjectEntry entry = cache.remove(key);
if (entry == null) {
entry = databaseService.query(key);
if (entry != null) databaseService.remove(entry);
}
return entry;
}
}

Your solution has two problems:
You are doing a sequential scan for persisting, which will get costly when there are a lot of entries
The code has race conditions
Due to the race conditions the code does not satisfy your requirements. Its possible to construct a concurrent access sequence where an entry is removed from the cache but as well was written to the database
Is there any existing technology/spring/apache framework that already offers such a cache? (sidenote: I don't want to use complex libraries like redis, ehcache etc for such a simple usecase).
I think you can solve the concurrency issues based on the ConcurrentHashMap. But I don't know an elegant way for the timeout. Still, a possible solution is to use a caching library. I'd like to offer an example based on cache2k which is not heavy (about a 400k jar) and has other nice use cases as well. As an extra there is also good support for the Spring caching abstraction.
public static class WriteBehindCache {
Cache<String, Object> cache = Cache2kBuilder.of(String.class, Object.class)
.addListener((CacheEntryExpiredListener<String, Object>) (cache, entry)
-> persist(entry.getKey(), entry.getValue()))
.expireAfterWrite(60, TimeUnit.SECONDS)
.build();
public void add(String key, Object data) {
cache.put(key, data);
}
public Object get(String key) {
return cache.invoke(key, e -> {
if (e.exists()) {
Object v = e.getValue();
e.remove();
return v;
}
return loadAndRemove(e.getKey());
});
}
// stubs
protected void persist(String key, Object value) {
}
protected Object loadAndRemove(String key) {
return null;
}
}
With this wiring the cache blocks out concurrent operation on one entry, so it is certain that only one database operation runs for one entry at a time.
You can do it in similar ways with other caching libraries. Using the JCache/JSR107 API the code would look almost identical.
A more "lighter" approach is to use jhalterman's expiringmap
Personally, I believe a cache should be in every developers toolbox. However, I am the author of cache2k. Of course, I need to say that.

Related

Batch delete all entities with given property (or properties)

This code below is our code to delete property for a given Entity type:
#Override
public boolean deleteProperty(String instance, String storeName, String propertyName) {
final boolean[] success = {false};
final PersistentEntityStore entityStore = manager.getPersistentEntityStore(xodusRoot, instance);
try {
entityStore.executeInTransaction(new StoreTransactionalExecutable() {
#Override
public void execute(#NotNull final StoreTransaction txn) {
EntityIterable entities = txn.findWithProp(storeName, propertyName);
final boolean[] hasError = {false};
entities.forEach(entity -> {
if(!entity.deleteProperty(propertyName)) {
hasError[0] = true;
}
});
success[0] = hasError[0];
}
});
} finally {
//entityStore.close();
}
return success[0];
}
I understand that Xodus is transactional and that if one of the deleteProperty operation here fails it will roll back (I may need to know if this is confirmed).
Still, is there a official way to delete a property for all existing entities of a given type?
I understand that Xodus is transactional and that if one of the deleteProperty operation here fails it will roll back (I may need to know if this is confirmed).
Yes, it's true. Here transaction will be flushed after StoreTransactionalExecutable performs there job. But you can split EntityIterable into batches (of size 100 for example) and after processing each batch execute txn.flush() method. Do not forget to check flush result since it returns boolean.
Still, is there a official way to delete a property for all existing entities of a given type?
No, there isn't. Only manually like I described above.

Sharing a hashmaps and some other data structures among different classes

In a web application I want to execute some methods, that belong to different classes. Method calls will be made in a chain (1st method calls 2nd, 2nd calls 3rd... and so on). Each method is going to make some entries or updates in some hashmaps or other data structures. After all the methods are executed, I have to make some updates in my database. Based on values stored in hashmaps.
As per my understanding, I have below options to achieve this:
Keep passing the hashmaps, from one method to other.
I think it's a bad approach.
Keep those hashmaps in separate class. Create an object of that class and keep that object passing from one method to other and so on.
This approach looks better than 1st to me but it still involves passing an object from one object to other leading to a tightly coupled design.
Using static hashmaps
(or hashtables) or static object of the seperate class made as in option 2.
(This I think is worse approach because static variables will be shared aming different users).
Please help me in understanding the best approach.
You can apply builder pattern to avoid passing parameters between methods. It gives the opportunity of building all your necessary operations in one class and calling them in chain.
Assuming you have 3 operations on the map, I have demonstrated the use of builder design pattern in this scenario
public class MyMap {
Map<String, String> map;
public MyMap(MyMapBuilder builder) {
this.map = builder.map;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public static class MyMapBuilder {
Map<String, String> map;
public MyMapBuilder() {
this.map = new HashMap<String,String>();
}
public MyMapBuilder doOperationOne() {
new OperationOne().run(map);
return this;
}
public MyMapBuilder doOperationTwo() {
new OperationTwo().run(map);
return this;
}
public MyMapBuilder doOperationThree() {
new OperationThree().run(map);
return this;
}
public MyMap build() {
return new MyMap(this);
}
}
}
Here is your operation classes (dummy operations as example)
public class OperationOne {
public void run(Map<String, String> map) {
map.put("OpOne", "1");
}
}
public class OperationThree {
public void run(Map<String, String> map) {
map.put("OpThree", "3");
}
}
public class OperationTwo {
public void run(Map<String, String> map) {
map.put("OpTwo", "2");
}
}
And here is how it is called at final
MyMap resultMap = new MyMap.MyMapBuilder().doOperationOne().doOperationTwo().doOperationThree().build();
The resultMap object keeps the result Map.
If you want to go the OO route, you shouldn't think about the problem as "data" going through transformations.
Think about what all of that means. Make it a collaboration between objects that mean something in your domain. What is the thing that you want in the end? A Report? A Chart? A Price? Call it by name and create it.
Similarly, do not have transformations. You can name (and create) intermediary results, if that makes sense from the domain's point of view. For example to create a Report, you might need a Template first, or whatever.
In short, neither of those solutions look particularly object-oriented to me. But, you can call it functional (if the methods are pure functions), in which case solution #1 or #2 both could work.
Changing multiple internal data structures (belonging to different classes) makes the processing of the incoming web request as fully stateful. It might lead into concurrency issues OR slowness (if you take care of all locks). If the final goal is to make some updates to a database, then either you make them synchronously within the flow OR 'queue' up those events (internally/externally) and process them asynchronously. Each queue record, can hold the info about the DB update. To me, your use case is very similar to 'logging'. A logging framework also needs to make updates to a log file from multiple methods (while processing a single request).

HashMap with weak values

I'm implementing a cache for Objects stored persistently. The idea is:
Method getObjectFromPersistence(long id); ///Takes about 3 seconds
Method getObjectFromCache(long id) //Instantly
And have a method: getObject(long id) with the following pseudocode:
synchronized(this){
CustomObject result= getObjectFromCache(id)
if (result==null){
result=getObjectFromPersistence(id);
addToCache(result);
}
return result;
}
But I need to allow the CustomObject to be collected by the garbage collector. Until now I was using an HashMap<Long,WeakReference<CustomObject> for the implementation. The problem is that over the time the HashMap becomes filled of empty WeakReferences.
I've checked WeakHashMap but there the keys are weak (and the values are still strong references) so having the longs with WeakReferences have no sense.
Whats the best solution for solving this problem? Is there some "inverse WeakHashMap" or something similar?
Thanks
You can use the Guava MapMaker for this:
ConcurrentMap<Long, CustomObject> graphs = new MapMaker()
.weakValues()
.makeMap();
You can even include the computation part by replacing makeMap() with this:
.makeComputingMap(
new Function<Long, CustomObject>() {
public CustomObject apply(Long id) {
return getObjectFromPersistence(id);
}
});
Since what you are writing looks a lot like a cache, the newer, more specialized Cache (built via a CacheBuilder) might be even more relevant to you. It doesn't implement the Map interface directly, but provides even more controls that you might want for a cache.
You can refer to this for a detailed how to work for CacheBuilder and here is an example for fast access:
LoadingCache<Integer, String> cache = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(
new CacheLoader<Integer, String>() {
#Override
public String load(Integer id) throws Exception {
return "value";
}
}
);
A WeakReference is added to its ReferenceQueue supplied at the construction time when its reference is collected.
You could poll the ReferenceQueue whenever you access the cache, and hold a HashMap<WeakReference<CustomObject>,Long> to know which entry to remove if a reference is found in the queue.
Alternatively, if the cache is not frequently used, you can watch the queue in a separate thread.
Have you tried android.util.LruCache (its a SDK11 class but it's also in the compatibility package as android.support.v4.util.LruCache). It does not implement java.util.Map but works like a Map and you can define how much memory will it take and it will flush old (unused cached objects by itself).
You could start a "cleanup" - Thread every once in a while. Perhaps if your map size exceeds a threshold but at most every 5 minutes .... something like that.
Keep the cleanup cycles short to not block the main functionality.
You can also test WeakValueHashMap from jboss-common http://docs.jboss.org/jbossas/javadoc/4.0.2/org/jboss/util/collection/WeakValueHashMap.java.html
I think the best option (if a dependency on Guava is undesirable) would be to use a custom subclass of WeakReference that remembers its ID, so that your cleanup thread can remove the weak values during cleanup of the WeakReferences.
The implementation of the weak reference, with the necessary ReferenceQueue and cleanup thread would look something like this:
class CustomObjectAccess {
private static final ReferenceQueue<CustomObject> releasedCustomObjects =
new ReferenceQueue<>();
static {
Thread cleanupThread = new Thread("CustomObject cleanup thread")
while (true) {
CustomObjectWeakReference freed = (CustomObjectWeakReference)
CustomObjectWeakReference.releasedCustomObjects.remove();
cache.remove(freed.id);
}
};
cleanupThread.start();
}
private Map<CustomObjectID, CustomObjectWeakReference> cache;
public CustomObject get(CustomObjectID id) {
synchronized(this){
CustomObject result= getFromCache(id);
if (result==null) {
result=getObjectFromPersistence(id);
addToCache(result);
}
}
return result;
}
private addToCache(CustomObject co) {
cache.put(CustomObject.getID(), new CustomObjectWeakReference(co));
}
private getFromCache(CustomObjectID id) {
WeakReference<CustomObject> weak = cache.get(id);
if (weak != null) {
return weak.get();
}
return null;
}
class CustomObjectWeakReference extends WeakReference<CustomObject> {
private final CustomObjectID id;
CustomObjectWeakReference(CustomObject co) {
super(co, releasedCustomObjects);
this.id = co.getID();
}
}
}
I had the need to store tagged weak objects and figured instead of using WeakHashMap<String, T>, I could just use WeakHashMap<T, String> instead.
This is Kotlin, but should apply to Java equally:
abstract class InstanceFactory<T> {
#Volatile
private var instances: MutableMap<T, String> = WeakHashMap<T, String>()
protected fun getOrCreate(tag: String = SINGLETON, creator: () -> T): T =
findByTag(tag)?.let {
it
} ?: synchronized(this) {
findByTag(tag)?.let {
it
} ?: run {
creator().also {
instances[it] = tag
}
}
}
private fun findByTag(tag: String): T? = instances.entries.find { it.value == tag }?.key
companion object {
const val SINGLETON = "singleton"
}
}
This can be used as follows:
class Thing(private val dependency: Dep) { ... }
class ThingFactory(private val dependency: Dep) : InstanceFactory<Thing>() {
createInstance(tag: String): Thing = getOrCreate(tag) { Thing(dependency) }
}
Simple singletons can be done like this:
object ThingFactory {
getInstance(dependency: Dependency): Thing = getOrCreate { Thing(dependency) }
}
There is ReferenceMap in Apache Commons Collections, this is a map implementation with hard keys and soft values (the opposite of WeakHashMap).

Java: Reflection overuse?

I am wondering whether I am overusing java reflection.
I have a class which is a data holder for a couple of maps. I have public get(...) methods which given a key as input return the value associated with it in the corresponding map.
Since the maps are large I load them only when I actually want to access them. So, in every get(...) methods, I check whether the map is null. If it is, I call the corresponding loadMap(..) method.
Here is a sample code snippet
public getId(String name)
{
try
{
if(nameMap1 == null)
loadNameMap1();
} catch(...) {....}
return nameMap1.getId(name);
}
The problem is that I have multiple maps. So, for loading each map I have a different loadMap(..) method and the try catch block in the get(...) methods. So, instead of that I wrote a method called loadMap(Object map, String methodName) which uses reflection to call the appropriate method, and handles all exceptions.
private synchronized void loadMap(Object map, String methodName)
{
if (map == null)
try
{
Method method = this.getClass().getDeclaredMethod(methodName, new Class[0]);
method.invoke(this, new Object[0]);
}
catch (..)
}
Am I overusing reflection here? Is there a better way to do this? Does this qualify as "limited use of reflection" as written in Effective Java by Joshua Bloch
(Side note: I cannot refactor the class into multiple classes )
// could also be static
private Map<String, Callable<Map>> myLoaders;
private synchronized void loadMap(Object map, String mapName)
{
if (map == null)
try
{
Callable<Map> mapLoader = myLoaders.get(mapName);
map = mapLoader.call();
}
catch (..)
}
// and in the constructor or other init code
myLoaders.put("map1", new Callable<Map>(){
Map call(){
// load map 1
}});
I think, though that if all you are doing is move a common try/catch logic from a couple of methods were it needs to be repeated to a single place, this is the wrong approach. You lose a lot of compiler error checking support this way. Some people would use a tool like Aspect/J for this, but I think you just have to live with the fact that Java has no real facility for this, reduce the clutter to a minimum by using shared private functions, and accept the couple of copy/pasted lines. As long as there is no "real code" in those lines, it is not really harmful code duplication.
So:
public getId(String name){
try{
if (nameMap1 == null)
loadNameMap1();
}
catch (....){
privateHelperFunctionThatCutsThisDownToOneLine(name, "id", "nameMap1");
}
}
// you are left with the above repetitive three (or seven) lines,
// but that is Java for you...
// in return, you get nice, static compile-time error checking
private void privateHelperFunctionThatCutsThisDownToOneLine(){
// all the long repeated code in the exception handler
// goes here.
}
You don't want to load all the maps because they are too large. But using your method you're gonna end up with everything loaded in memory eventually. You may have a look at ehcache which may be configured a a lazy map system with element eviction when no longer needed.
I'd say yes you are overusing reflection.
Perhaps you should take a more OO approach
public interface MapMaker <K,V> {
public Map<K,V> create();
}
public class LazyMap<K,V> implements Map<K,V> {
private MapMaker<K,V> creation;
private Map<K,V> theMap = null;
public LazyMap( MapMaker<K,V> creation) {
this.creation=creation;
}
protected Map<K,V> getMap() {
if( theMap == null) {
synchronized(this) {
if( theMap == null ) {
theMap = creation.create();
}
}
}
return theMap;
}
//Map interface
public V get(Object key) { return getMap().get(key); }
//repeat for all
}

How build my own Application Setting

I want to build a ApplicationSetting for my application. The ApplicationSetting can be stored in a properties file or in a database table. The settings are stored in key-value pairs. E.g.
ftp.host = blade
ftp.username = dummy
ftp.pass = pass
content.row_pagination = 20
content.title = How to train your dragon.
I have designed it as follows:
Application settings reader:
interface IApplicationSettingReader {
Map read();
}
DatabaseApplicationSettingReader implements IApplicationSettingReader {
dao appSettingDao;
Map read() {
List<AppSettingEntity> listEntity = appSettingsDao.findAll();
Map<String, String> map = new HaspMap<String, String>();
foreach (AppSettingEntity entity : listEntity) {
map.put(entity.getConfigName(), entity.getConfigValue());
}
return new AppSettings(map);
}
}
DatabaseApplicationSettingReader implements IApplicationSettingReader {
dao appSettingDao;
Map read() {
//read from some properties file
return new AppSettings(map);
}
}
Application settings class:
AppSettings {
private static AppSettings instance = new AppSettings();
private Map map;
private AppSettings() {
}
public static AppSettings getInstance() {
if (instance == null) {
throw new RuntimeException("Object not configure yet");
}
return instance;
}
public static configure(IApplicationSettingReader reader) {
this.map = reader.read();
}
public String getFtpSetting(String param) {
return map.get("ftp." + param);
}
public String getContentSetting(String param) {
return map.get("content." + param);
}
}
Test class:
AppSettingsTest {
IApplicationSettingReader reader;
#Before
public void setUp() throws Exception {
reader = new DatabaseApplicationSettingReader();
}
#Test
public void getContentSetting_should_get_content_title() {
AppSettings.configure(reader);
Instance settings = AppSettings.getInstance();
String title = settings.getContentSetting("title");
assertNotNull(title);
Sysout(title);
}
}
My questions are:
Can you give your opinion about my code, is there something wrong ?????
I configure my application setting once, while the application start, I configure the application setting with appropriate reader (DbReader or PropertiesReader), I make it singleton because the application just have one instance of ApplicationSettngs. The problem is, when some user edit the database or file directly to database or file, I can't get the changed values. Now, I want to implement something like ApplicationSettingChangeListener. So if the data changes, I will refresh my application settings. Do you have any suggestions how this can be implementedb ????
I haven't throughly inspected your code, but there seems to be a concurrency issue. The map is thread-unsafe (HashMap), so if you mutate it through config() and have other threads access map, you have a problem.
Though you could use a ConcurrentHashMap instead HashMap, a batch operation on ConcurrentHashMap is not atomic. Meaning that, if you use it, you will see a "half-way" modified config. That could not be okay depending on your app.
So, the solution for this is to use this:
private volatile ImmutableMap map;
public config(){
ImmutableMap newMap = createNewMap();
this.map = newMap;
}
This will change your configs atomically (no intermediate state is visible).
As for updating your config on the fly, log4j does it using a background thread that monitors the config file. You could of course monitor a db table instead by polling it periodically.
In that case, your Config class will have preferably a ScheduledExecutor with a task that will monitor files/db and call config() periodically.
The answer to question #2 is to use a thread and check periodically if the file has been changed or to simply reinitialize your settings with the file contents.

Categories

Resources