Getting all the Cache Names - java

I am developing a REST application to read all the caches in a Cluster that uses J Cache with Hazel cast 3.3.3
This application will create another hazel cast node when I call the following line in the application:
cacheManager= Caching.getCachingProvider().getCacheManager();
The node get clustered with already created nodes. But when I try to get all the cache names of the cluster with the following command, It returns an empty iterable:
cacheManager.getCacheNames().iterator()
I went through the Java doc of the Jcache which contained:
May not provide all of the Caches managed by the CacheManager. For
example: Internally defined or platform specific Caches that may be
accessible by a call to getCache(java.lang.String) or
getCache(java.lang.String,java.lang.Class,java.lang.Class) may not be
present in an iteration.
But the caches that I am trying to access is not internally
defined or platform specific. They are created by other nodes.
I want a way to get all the names present in the cluster. Is there a way to this?
NB: No hazelcast.xml is used in the application. All is initialized by the default xml s.
Update:
I can access the cache if I know the name. And after accessing for the first time by giving the name directly, now it shows that cache in the cacheManager.getCacheNames().iterator()

CacheManager only provides names of caches it manages, so you cannot obtain all caches known to the cluster using JCache API.
In Hazelcast 3.7 (EA was released just yesterday), all Caches are available as DistributedObjects, so invoking HazelcastInstance.getDistributedObjects() and then checking for objects being instances of javax.cache.Cache or the Hazelcast-specific subclass com.hazelcast.cache.ICache you should be able to get references to all Caches in the cluster:
// works for 3.7
Collection<DistributedObject> distributedObjects = hazelcastInstance.getDistributedObjects();
for (DistributedObject distributedObject : distributedObjects) {
if (distributedObject instanceof ICache) {
System.out.println("Found cache with name " + distributedObject.getName());
}
}
In Hazelcast 3.6 it is possible to obtain all cache names known to the cluster only using internal classes, so there is no guarantee this will work with any other version.
// works for 3.6 using internal classes, most probably will not work for other versions
public static void main(String[] args) {
// start a hazelcast instance
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
// create a CacheManager and Cache on this instance
CachingProvider hazelcastCachingProvider = Caching.getCachingProvider("com.hazelcast.cache.HazelcastCachingProvider",
HazelcastCachingProvider.class.getClassLoader());
CacheManager cacheManager = hazelcastCachingProvider.getCacheManager();
cacheManager.createCache("test1", new CacheConfig<Object, Object>());
// hacky: obtain a reference to internal cache service
CacheDistributedObject cacheDistributedObject = hz.getDistributedObject("hz:impl:cacheService", "setupRef");
ICacheService cacheService = cacheDistributedObject.getService();
// obtain all CacheConfig's in the cluster
Collection<CacheConfig> cacheConfigs = cacheService.getCacheConfigs();
for (CacheConfig cacheConfig : cacheConfigs) {
System.out.println("Cache name: " + cacheConfig.getName() +
", fully qualified name: " + cacheConfig.getNameWithPrefix());
}
hz.shutdown();
}

But the caches that I am trying to access is not internally defined or
platform specific
Its good because this method should return all the others and some of the internally defined or platform specific ones.

Related

is there a Cacheable in C# similar to Java?

In Java Spring Boot, I can easily enable caching using the annotation #EnableCaching and make methods cache the result using #Cacheable, this way, any input to my method with the exact same parameters will NOT call the method, but return immediately using the cached result.
Is there something similar in C#?
What I did in the past was i had to implement my own caching class, my own data structures, its a big hassle. I just want an easy way for the program to cache the result and return the exact result if the input parameters are the same.
EDIT: I dont want to use any third party stuff, so no MemCached, no Redis, no RabbitMQ, etc... Just looking for a very simple and elegant solution like Java's #Cacheable.
Caches
A cache is the most valuable feature that Microsoft provides. It is a type of memory that is relatively small but can be accessed very quickly. It essentially stores information that is likely to be used again. For example, web browsers typically use a cache to make web pages load faster by storing a copy of the webpage files locally, such as on your local computer.
Caching
Caching is the process of storing data into cache. Caching with the C# language is very easy. System.Runtime.Caching.dll provides the feature for working with caching in C#. In this illustration I am using the following classes:
ObjectCache
MomoryCache
CacheItemPolicy
ObjectCache
: The CacheItem class provides a logical representation of a cache entry, that can include regions using the RegionName property. It exists in the System.Runtime.Caching.
MomoryCache
: This class also comes under System.Runtime.Caching and it represents the type that implements an in-cache memory.
CacheItemPolicy
: Represents a set of eviction and expiration details for a specific cache entry.
.NET provides
System.Web.Caching.Cache - default caching mechanizm in ASP.NET. You can get instance of this class via property Controller.HttpContext.Cache also you can get it via singleton HttpContext.Current.Cache. This class is not expected to be created explicitly because under the hood it uses another caching engine that is assigned internally. To make your code work the simplest way is to do the following:
public class DataController : System.Web.Mvc.Controller{
public System.Web.Mvc.ActionResult Index(){
List<object> list = new List<Object>();
HttpContext.Cache["ObjectList"] = list; // add
list = (List<object>)HttpContext.Cache["ObjectList"]; // retrieve
HttpContext.Cache.Remove("ObjectList"); // remove
return new System.Web.Mvc.EmptyResult();
}
}
System.Runtime.Caching.MemoryCache - this class can be constructed in user code. It has the different interface and more features like update\remove callbacks, regions, monitors etc. To use it you need to import library System.Runtime.Caching. It can be also used in ASP.net application, but you will have to manage its lifetime by yourself.
var cache = new System.Runtime.Caching.MemoryCache("MyTestCache");
cache["ObjectList"] = list; // add
list = (List<object>)cache["ObjectList"]; // retrieve
cache.Remove("ObjectList"); // remove
You can write a decorator with a get-or-create functionality. First, try to get value from cache, if it doesn't exist, calculate it and store in cache:
public static class CacheExtensions
{
public static async Task<T> GetOrSetValueAsync<T>(this ICacheClient cache, string key, Func<Task<T>> function)
where T : class
{
// try to get value from cache
var result = await cache.JsonGet<T>(key);
if (result != null)
{
return result;
}
// cache miss, run function and store result in cache
result = await function();
await cache.JsonSet(key, result);
return result;
}
}
ICacheClient is the interface you're extending. Now you can use:
await _cacheClient.GetOrSetValueAsync(key, () => Task.FromResult(value));

Unable to get good example of using memcached from Java boot

I am using java boot for my development. For now I have used 'EhCache' for caching , it is directly supported from Java boot. This is "in-process" cache, i.e., becomes part of your process. It is okay for now. But my server will run on multiple nodes in near future. Hence want to switch to 'Memcached' as common caching layer.
After spending good amount of time, I could not get good sample of using Memcached from java boot. I have looked at 'Simple Spring Memcached' which comes close to my requirement. But still it gives example using XML configuration in Spring way. Java boot does not use such XML configuration as far as possible. At least I could not map the example quickly to java boot world.
I want to use Memcahed ( directly or via cache-abstraction-layer) from java boot. If anybody points me to a relevant java boot example, it will save a lot of time for me.
You could also check Memcached Spring Boot library. It uses Memcached implementation for Spring Cache Abstraction.
In other words you use the same configuration and same annotations as you would use with any other Spring Cache implementation. You can check out here the usage of the library.
There are also example projects in Kotlin and Java.
I have already accepted answer given by #ragnor. But I think I should post a complete example here which has worked for me.
Make sure you have cache-enabled for your application by adding #EnableCaching
POM.xml should have following dependency:
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>spring-cache</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>spymemcached-provider</artifactId>
<version>3.6.1</version>
</dependency>
Add a config file to configure your memcached cache configuration, say MySSMConfig.java
#Configuration
#EnableAspectJAutoProxy
#ImportResource("simplesm-context.xml") // This line may or may not be needed,
// not sure
public class SSMConfig
{
private String _memcachedHost; //Machine where memcached is running
private int _memcachedPort; //Port on which memcached is running
#Bean
public CacheManager cacheManager()
{
//Extended manager used as it will give custom-expiry value facility in future if needed
ExtendedSSMCacheManager ssmCacheManager = new ExtendedSSMCacheManager();
//We can create more than one cache, hence list
List<SSMCache>cacheList = new ArrayList<SSMCache>();
//First cache: Testcache
SSMCache testCache = createNewCache(_memcachedHost, _memcachedPort,
"testcache", 5);
//One more dummy cache
SSMCache dummyCache = createNewCache(_memcachedHost,_memcachedPort,
"dummycache", 300);
cacheList.add(testCache);
cacheList.add(dummyCache);
//Adding cache list to cache manager
ssmCacheManager.setCaches(cacheList);
return ssmCacheManager;
}
//expiryTimeInSeconds: time(in seconds) after which a given element will expire
//
private SSMCache createNewCache(String memcachedServer, int port,
String cacheName, int expiryTimeInSeconds)
{
//Basic client factory to be used. This is SpyMemcached for now.
MemcacheClientFactoryImpl cacheClientFactory = new MemcacheClientFactoryImpl();
//Memcached server address parameters
//"127.0.0.1:11211"
String serverAddressStr = memcachedServer + ":" + String.valueOf(port);
AddressProvider addressProvider = new DefaultAddressProvider(serverAddressStr);
//Basic configuration object
CacheConfiguration cacheConfigToUse = getNewCacheConfiguration();
//Create cache factory
CacheFactory cacheFactory = new CacheFactory();
cacheFactory.setCacheName(cacheName);
cacheFactory.setCacheClientFactory(cacheClientFactory);
cacheFactory.setAddressProvider(addressProvider);
cacheFactory.setConfiguration(cacheConfigToUse);
//Get Cache object
Cache object = null;
try {
object = cacheFactory.getObject();
} catch (Exception e) {
}
//allow/disallow remove all entries from this cache!!
boolean allowClearFlag = false;
SSMCache ssmCache = new SSMCache(object, expiryTimeInSeconds, allowClearFlag);
return ssmCache;
}
private CacheConfiguration getNewCacheConfiguration()
{
CacheConfiguration ssmCacheConfiguration = new CacheConfiguration();
ssmCacheConfiguration.setConsistentHashing(true);
//ssmCacheConfiguration.setUseBinaryProtocol(true);
return ssmCacheConfiguration;
}
}
OK, we are ready to use our configured cache.
Sample methods in some other class to read from cache and to remove from cache
#Cacheable(value="dummycache, key="#givenId.concat('-dmy')", unless="#result == null")
public String getDummyDataFromMemCached(String givenId)
{
logger.warn("getDummyDataFromMemCached: Inside DUMMY method to actually get data");
return "Sample-" + String.valueOf(givenId);
}
#CacheEvict(value="dummycache",key="#givenId.concat('-dmy')")
public void removeDummyDataFromMemCached(String givenId)
{
//Do nothing
return;
}
Note that we have added suffix to the kache-keys. As Memcached does not support cache-zones, "dummycache" and "testcache" ultimately does not remain separate on a single server. (They may remain separate with some other cache implementation). Hence to avoid conflict, we append unique suffix to the cache-key.
If you want to cache objects of your own class, then make sure that they are serializable. Just change your class definition to 'XYZ implements Serializable'.
You can find some materials how to configure SSM using Java configuration instead of XML files here and here.
Basically you have to move definitions of all beans from XML to Java.

Reference annotation on bundle field

I'm developing an application with OSGi. Looking inside the OSGi compendium 6.0 (section 112.8.1) I've come across the declarative service; in particular I looked the following paragraph:
For a field, the defaults for the Reference annotation are:
The name
of the bind method or field is used for the name of the reference.
1:1 cardinality if the field is not a collection. 0..n cardinality if the field is a collection.
Static reluctant policy if the field is not declared volatile. Dynamic reluctant policy if the field is declared volatile
The requested service is the type of the field.
For example:
#Reference
volatile Collection<LogService> log;
Now, I read from Neil Bartlett's OSGi in practice (section 11.10.2) that synchronization and concurrency of bind and unbind methods of Reference annotation are a bit tricky (especially in dynamic policy scnearios). In particular, a thread-safe example of a reference of a service via annotation may be:
#Component( provide = MailboxListener.class, properties = { "service.ranking = 10"})
public class LogMailboxListener implements MailboxListener {
private final AtomicReference<Log> logRef = newAtomicReference <Log> () ;
public void messagesArrived ( String mboxName, Mailbox mbox, long [ ] ids ) {
Log log = logRef.get();
if (log != null )
log.log(Log.INFO, ids.length + "message(s) arrived in mailbox " + mboxName, null);
else
System.err.println("No log available!");
}
#Reference( service = Log.class, dynamic = true, optional = true )
public void setLog(Log log) {
logRef.set(log);
}
public void unsetLog(Log log) {
logRef.compareAndSet(log, null);
}
}
I think I grasped from the book why there the dynamic policy needs this adjustements from the multi-threading scenario. My question is: if the reference annotation were on a field (declarative service 1.3) how could I achieve thread-safety? Only by defining the reference as "volatile" (as compendium suggest)? Or there is some tricky part that will create problems in the application?
Thanks for any kind reply
When you use a dynamic policy reference on a field, the field must be volatile. In your example, each time the set of LogServices change, a new collection is injected into the field. So this will be safe since if your code is iterating over the old collection, the old collection is unaltered. When you code goes back to the log field, it will see the new collection.
So all you need to do is declare the field volatile and do not store the field value somewhere else since the field will be updated to a new collection whenever the set of bound services changes.

How to dynamically differentiate the memcahce instances in java code?

Can anyone suggest any design pattern to dynamically differentiate the memcahce instances in java code?
Previously in my application there is only one memcache instance configured this way
Step-1:
dev.memcached.location=33.10.77.88:11211
dev.memcached.poolsize=5
Step-2:
Then i am accessing that memcache in code as follows,
private MemcachedInterface() throws IOException {
String location =stringParam("memcached.location", "33.10.77.88:11211");
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(location));
}
Then i am invoking that memcache as follows in code using above MemcachedInterface(),
Step-3:
MemcachedInterface.getSoleInstance();
And then i am using that MemcachedInterface() to get/set data as follows,
MemcachedInterface.set(MEMCACHED_CUSTS, "{}");
resp = MemcachedInterface.gets(MEMCACHED_CUSTS);
My question is if i introduce an new memcache instance in our architechture,configuration is done as follows,
Step-1:
dev.memcached.location=33.10.77.89:11211
dev.memcached.poolsize=5
So, first memcache instance is in 33.10.77.88:11211 and second memcache instance is in 33.10.77.89:11211
until this its ok...but....
how to handle Step-2 and Step-3 in this case,To get the MemcachedInterface dynamically.
1)should i use one more interface called MemcachedInterface2() in step-2
Now the actual problem comes in,
I am having 4 webservers in my application.Previoulsy all are writing to MemcachedInterface(),but now as i will introduce one more memcache instance ex:MemcachedInterface2() ws1 and ws2 should write in MemcachedInterface() and ws3 and ws4 should write in ex:MemcachedInterface2()
So,if i use one more interface called MemcachedInterface2() as mentioned above,
This an code burden as i should change all the classes using WS3 and WS4 to Ex:MemcachedInterface2() .
Can anyone suggest one approach with limited code changes??
xmemcached supports constistent hashing which will allow your client to choose the right memcached server instance from the pool. You can refer to this answer for a bit more detail Do client need to worry about multiple memcache servers?
So, if I understood correctly, you'll have to
use only one memcached client in all your webapps
since you have your own wrapper class around the memcached client MemcachedInterface, you'll have to add some method to this interface, that enables to add/remove server to an existing client. See the user guide (scroll down a little): https://code.google.com/p/xmemcached/wiki/User_Guide#JMX_Support
as far as i can see is, you have duplicate code running on different machines as like parallel web services. thus, i recommend this to differentiate each;
Use Singleton Facade service for wrapping your memcached client. (I think you are already doing this)
Use Encapsulation. Encapsulate your memcached client for de-couple from your code. interface L2Cache
For each server, give them a name in global variable. Assign those values via JVM or your own configuration files via jar or whatever. JVM: --Dcom.projectname.servername=server-1
Use this global variable as a parameter, configure your Service getInstance method.
public static L2Cache getCache() {
if (System.getProperty("com.projectname.servername").equals("server-1"))
return new L2CacheImpl(SERVER_1_L2_REACHIBILITY_ADDRESSES, POOL_SIZE);
}
good luck with your design!
You should list all memcached server instances as space separated in your config.
e.g.
33.10.77.88:11211 33.10.77.89:11211
So, in your code (Step2):
private MemcachedInterface() throws IOException
{
String location =stringParam("memcached.location", "33.10.77.88:11211 33.10.77.89:11211");
MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(location));
}
Then in Step3 you don't need to change anything...e.g. MemcachedInterface.getSoleInstance(); .
You can read more in memcached tutorial article:
Use Memcached for Java enterprise performance, Part 1: Architecture and setup
http://www.javaworld.com/javaworld/jw-04-2012/120418-memcached-for-java-enterprise-performance.html
Use Memcached for Java enterprise performance, Part 2: Database-driven web apps
http://www.javaworld.com/javaworld/jw-05-2012/120515-memcached-for-java-enterprise-performance-2.html

Vert.x and Neo4j in multithread cucumber environment

I try to run cucumber tests in a JRuby environment. I configured the cucumber rake task to startup an embedded Vert.x application server in another thread but in the same JVM.
During the application startup, an embedded instance of Neo4j is initialized.
So finally, there are Cucumber, Vert.x and Neo4j all running in the same JVM (tada!).
At the end of some test scenarios, I would like to check if certian data has been placed in the database base. And since the Neo4j docs say...
The EmbeddedGraphDatabase instance can be shared among multiple threads. Note however that you can’t create multiple instances pointing to the same database.
...I try to get the already initialized Neo4j instance and use it for these checks. To make that happen, I wrote the following factory.
public class ConcurrentGraphDatabaseFactory {
private static HashMap<String, GraphDatabaseService> databases = new HashMap<String, GraphDatabaseService>();
public static synchronized GraphDatabaseService getOrCreateDatabase(String path, String autoIndexFields) {
System.out.println("databases: " + databases.toString());
if (databases.containsKey(path)) {
return databases.get(path);
} else {
final GraphDatabaseService database = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(path).
setConfig(GraphDatabaseSettings.node_keys_indexable, autoIndexFields).
setConfig(GraphDatabaseSettings.node_auto_indexing, GraphDatabaseSetting.TRUE).
newGraphDatabase();
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
database.shutdown();
}
});
databases.put(path, database);
return database;
}
}
}
This factory should ensure that only on instance per path is initialized. But if the function getOrCreateDatabase accessed the second time, the internal databases HashMap is still empty. That cause the code to initialize a second Neo4j instance on the same data, which fails with
NativeException: java.lang.IllegalStateException: Unable to lock store
It's all running in the same JVM, but it seems, that the different threads have separated memory.
What am I doing wrong here?
Are you sure you are only running one single neo4j instance from all threads? Otherwise, several neo4j instances will fight on locking the store files. Neo4j is thread safe, but not doing several embedded instances on the same store, for scaling it, you use the High Availability setup, see http://docs.neo4j.org/chunked/snapshot/ha.html
I've spend some time on the problem and finally found a solution.
The verticles in Vert.x create strictly isolated environments. This causes a second version of my factory (see the code above) to be initialized. And the second factory tries to initialized a second Neo4j instance.
The solution was, to separate the Neo4j code into a dedicated storage verticle and write test code that accesses that verticle via the event bus.

Categories

Resources