Code Monkey home page Code Monkey logo

ehcache-jcache's Introduction

Ehcache-JCache For Ehcache 2.x.

Important: This project isn't maintained anymore as Ehcache 2.x will slowly retire. Please consider migrating to Ehcache 3.x which has built-in JSR107 support.

About

ehcache-jcache is a full implementation of the API and SPI from JSR-107 (aka JCache). It provides a wrapper around an Ehcache cache that allows allows you to use Ehcache as the caching provider using only JSR-107 APIs.

More detailed information about how to use this is found under the ehcache-jcache module

Modules

  • ehcache-jcache This contains the ehcache-jcache implementation
  • jcache-tck-runner This runs the JSR107 TCK suite against the ehcache-jcache implementation to verify compliance with the spec.

Build

  • Just run the following command line (provided you have maven 3 already installed) :

    mvn clean install

  • You may want to disable the run-tck profile (if you don't have the TCK in your local maven repository since it's not published to a maven repository) :

    mvn clean install -P -run-tck

  • Current build status: Build Status

Build Status

Development

Active development of the ehcache-jcache module follows changes to the spec. There will be no attempt to maintain backwards compatibility between release versions; the focus of each release will be compliance with the latest JSR107 spec.

Release

Following releases of the JSR107 spec APIs, an updated release milestone will be released and the latest stable release code will sit on the master branch of the ehcache-jcache github repository.

Issue tracker

Please log issues to: https://github.com/Terracotta-OSS/ehcache-jcache/issues

License

This software is provided under an Apache 2 open source license, read the LICENSE.txt file for details.

Contributors

This free, open source software was made possible by Terracotta, Inc.. See the CONTRIBUTORS.markdown file for details.

Copyright

Copyright (c) Terracotta

Using it

Maven

Releases are available from Maven Central.

Snapshots are available from the Sonatype OSS snapshot repository. In order to access the snapshots, you need to add the following repository to your pom.xml:

<repository>
    <id>sonatype-nexus-snapshots</id>
    <name>Sonatype Nexus Snapshots</name>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
    <releases>
        <enabled>false</enabled>
    </releases>
    <snapshots>
        <enabled>true</enabled>
    </snapshots>
</repository>

ehcache-jcache's People

Contributors

akomakom avatar alexsnaps avatar anthonydahanne avatar azure-pipelines[bot] avatar gregrluck avatar henri-tremblay avatar jdillon avatar jhouserizer avatar ljacomet avatar ryangardner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ehcache-jcache's Issues

Race Condition in JCacheManager between createCache() and getCache()

As far as I understand, jsr-107's CacheManager is supposed to be thread-safe, and it is only practical for it to be.

There is a possibility for the cache configuration created by JCacheManager.createCache() to be configured incorrectly if JCacheManager.getCache() is called at the same time with the same cache name. In particular, there is a realistic chance that the statistics and management beans are not created.

This works as follows:

  • createCache is called.
  • createCache makes sure allCaches does not include the cache
  • createCache adds the cache to the ehCache-backed cacheManager
  • Now, getCache(String, Class, Class) is called with the same argument.
  • getCache tries to find the same cache in allCaches but does it does not exist
  • getCache looks in the ehCache-backed cacheManager, and finds the cache as it's already added there
  • getCache creates a new JCache based on a JCacheConfiguration with the default configuration and puts it into allCaches
  • createCache creates a new JCache with the correct configuration and tries to add it with allCaches.putIfAbsent, but it already exists
  • createCache returns the misconfigured cache that is already present in allCaches, and does not call enableStatistics or enableManagement for it.

The same problem occurs when using the second overload, getCache(String):

  • createCache is called.
  • createCache makes sure allCaches does not include the cache
  • createCache adds the cache to the ehCache-backed cacheManager
  • getCache(String) is called with the same cache name as argument.
  • getCache looks in allCaches, but does not find the cache
  • getCache calls refreshAllCaches()
  • refreshAllCaches iterates over all caches in the ehCache-backed cacheManager, creates new JCache instances for them and puts them into allCaches
  • The problem is that new JCacheConfiguration() does not properly set the managementEnabled and statisticsEnabled attributes when a ehCache CacheConfiguration is provided as argument
  • createCache again uses the already existing, but misconfigured cache and returns that, enableStatistics and enableManagement are not called.

I see three possibilities to solve this problem:

  • Use synchronized on all the methods touching or reading allCaches. This may lead to performance loss, but is the simplest to implement
  • Use ReadWriteLock so that concurrent e.g. getCache or getCacheNames can be called concurrently.
  • Lock cache names right when they are created using a concurrent set, and do not synchronize ehcaches to allCaches for those in this set. However, I don't think this will work because getCache is expected to wait for a cache being added to be completely configured befure returning it. That's only possible with locking.

I will create a pull request to fix this when we have agreed on a solution.

CacheLoaderException when reading from cache and no loader factory is specified

I'm having the following exception when I read an entry that doesn't exist in the cache while I'm expecting a null. Do I have to provide a factory for the cache loader when I create the cache? currently I'm not.

javax.cache.integration.CacheLoaderException: java.lang.NullPointerException
    at org.ehcache.jcache.JCache.load(JCache.java:123)
    at org.ehcache.jcache.JCache.get(JCache.java:105)
        ...

Here is my configuration:

CompleteConfiguration<ComposedKey, Object> config1 = new MutableConfiguration<ComposedKey, Object>()
    // Configure the cache to be typesafe
        .setTypes(ComposedKey.class, Object.class)
        // Configure to expire entries 30 secs after creation in the cache
        .setExpiryPolicyFactory(FactoryBuilder.factoryOf(new AccessedExpiryPolicy(new Duration(TimeUnit.MINUTES, 30))))
        // Configure read-through of the underlying store
        .setReadThrough(true)
        // Configure write-through to the underlying store
        .setWriteThrough(true)
        // Configure the javax.cache.integration.CacheLoader
        // .setCacheLoaderFactory(FactoryBuilder.factoryOf(new UserCacheLoader(userDao)))
        // Configure the javax.cache.integration.CacheWriter
        // .setCacheWriterFactory(FactoryBuilder.factoryOf(new UserCacheWriter(userDao)))
        // Configure the javax.cache.event.CacheEntryListener with no
        // javax.cache.event.CacheEntryEventFilter, to include old value
        // and to be executed synchronously
        .addCacheEntryListenerConfiguration(
            new MutableCacheEntryListenerConfiguration<ComposedKey, Object>(new CacheListenerManagerJSR107Factory(), null, true,
                true));

It looks like when readTrough is set to true then a cache loader should be provided.

Source files without license headers

Hi
The following source files are without license headers:
./ehcache-jcache/src/main/java/org/ehcache/jcache/JCacheManagementMXBean.java
./ehcache-jcache/src/main/java/org/ehcache/jcache/JCacheMXBean.java
./ehcache-jcache/src/main/java/org/ehcache/jcache/JCacheStatMXBean.java
./ehcache-jcache/src/main/java/org/ehcache/jcache/tck/TCKMBeanServerBuilder.java

./ehcache-jcache/src/test/java/org/ehcache/jcache/JCacheAndEhcacheAccessTest.java
./ehcache-jcache/src/test/java/org/ehcache/jcache/JCacheCachingProviderTest.java
./ehcache-jcache/src/test/java/org/ehcache/jcache/JCacheManagerTest.java

Please, confirm the licensing of code and/or content/s, and add license headers
https://fedoraproject.org/wiki/Packaging:LicensingGuidelines?rd=Packaging/LicensingGuidelines#License_Clarification

Thanks in advance
Regards

PR #45 introduced a failure

see https://ehcache.ci.cloudbees.com/job/ehcache-jcache/21/org.ehcache$jcache/testReport/junit/org.ehcache.jcache/JCacheCachingProviderTest/testLoadsXMLFile/

Error Message

 Expected: is <360>      got: <1000> 
Stacktrace

java.lang.AssertionError: 
Expected: is <360>
     got: <1000>

    at org.junit.Assert.assertThat(Assert.java:778)
    at org.junit.Assert.assertThat(Assert.java:736)
    at org.ehcache.jcache.JCacheCachingProviderTest.testLoadsXMLFile(JCacheCachingProviderTest.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:172)
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:78)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:70)

Use defaultCache to read default values for 107 unspecified props

Based on issue #30, we may want to read things like capacity control (and tiering?) from the defaultCache and merge it in with the Configuration provided to javax.cache.CacheManager#createCache.

Ehcache certainly requires a capacity to be set on the Cache, which now defaults to JCacheManager. DEFAULT_SIZE. There may well be other setting we may want to "copy" from there...

Now I find that capacity set this way seems to only address an implementation issue (i.e. Ehcache requiring this setting), but I don't see how one would actually configure this one single value for all programmatically configured javax.cache.Cache to anything meaningful...

Thoughts?

CachingProvider Exceptions

Hi,
I am new to caching, please help me solve cachingprovider exceptions.

I want to test this sample code.

String cacheName = "sampleCache";
CacheManager cacheManager = Caching.getCacheManager();
javax.cache.Cache cache = cacheManager.getCache(cacheName);
if (cache == null) {
cache = cacheManager.createCacheBuilder(cacheName).build();
}
cache.put("key","value for given key");
String fetchedcachevalue = cache.get("key");

System.out.println(fetchedcachevalue+" is the fetched cache value for given key");

in build path i path i gave cache-api-0.5.jar
When i run this, i got "No CachingProviders found in classpath." exception.

Then i gave "ehcache-jcache-1.5.0-0.5.jar" ,
then i got "Exception in thread "Main Thread" java.util.ServiceConfigurationError: javax.cache.spi.CachingProvider: Provider net.sf.ehcache.jcache.JCacheCachingProvider could not be instantiated: java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory"

then i gave "ehcache-core-2.6.2.jar" ," slf4j-api-1.6.1.jar" , "slf4j-jdk14-1.6.1.jar"
and got exception saying "Exception in thread "Main Thread" java.lang.NoClassDefFoundError: javax/cache/implementation/AbstractCacheManagerFactory"

then i gave "cache-ri-impl-0.5.jar" and got "Exception in thread "Main Thread" java.lang.IllegalStateException: Multiple CachingProviders found in classpath. There should only be one. CachingProviders found were: net.sf.ehcache.jcache.JCacheCachingProvider, javax.cache.implementation.RICachingProvider"

now if i remove either "ehcache-jcache-1.5.0-0.5.jar" or "cache-ri-impl-0.5.ja" , i am getting the same exception when run ,saying "Exception in thread "Main Thread" java.lang.NoClassDefFoundError: javax/cache/implementation/AbstractCacheManagerFactory".

and if i remove both "ehcache-jcache-1.5.0-0.5.jar" and "cache-ri-impl-0.5.ja" , then i am getting exception say "Exception in thread "Main Thread" java.lang.IllegalStateException: No CachingProviders found in classpath."

Please help me run this sample code.

Thanks

Could not create a cache named "default" through the JSR-107 API

I am trying to use a region named default using ehcache-jcache. When I tries to create it using the standard JSR-107 API, I get the following exception:

Caused by: net.sf.ehcache.ObjectExistsException: The Default Cache has already been configured
    at net.sf.ehcache.config.Configuration.addCache(Configuration.java:967) ~[ehcache-2.8.3.jar:2.8.3]
    at net.sf.ehcache.config.CacheConfiguration.registerCacheConfiguration(CacheConfiguration.java:1875) ~[ehcache-2.8.3.jar:2.8.3]
    at net.sf.ehcache.config.CacheConfiguration.setupFor(CacheConfiguration.java:1703) ~[ehcache-2.8.3.jar:2.8.3]
    at net.sf.ehcache.config.CacheConfiguration.setupFor(CacheConfiguration.java:1678) ~[ehcache-2.8.3.jar:2.8.3]
    at net.sf.ehcache.CacheManager.initializeEhcache(CacheManager.java:1328) ~[ehcache-2.8.3.jar:2.8.3]
    at net.sf.ehcache.CacheManager.addCacheNoCheck(CacheManager.java:1399) ~[ehcache-2.8.3.jar:2.8.3]
    at net.sf.ehcache.CacheManager.addCacheIfAbsent(CacheManager.java:1916) ~[ehcache-2.8.3.jar:2.8.3]
    at org.ehcache.jcache.JCacheManager.createCache(JCacheManager.java:108) ~[jcache-1.0.0.jar:na]

When I only try to access it (i.e. without creating it myself), I get:

java.lang.IllegalArgumentException: Cannot find cache named 'default' for CacheResultOperation[CacheMethodDetails[method=public java.lang.String demo.FooServiceImpl.defaultGet(long), [email protected](cacheKeyGenerator=interface javax.cache.annotation.CacheKeyGenerator, cacheName=default, cachedExceptions=[], skipGet=false, cacheResolverFactory=interface javax.cache.annotation.CacheResolverFactory, exceptionCacheName=, nonCachedExceptions=[]), cacheName='default']]
    at org.springframework.cache.interceptor.AbstractCacheResolver.resolveCaches(AbstractCacheResolver.java:81)
    at org.springframework.cache.jcache.interceptor.AbstractCacheInterceptor.resolveCache(AbstractCacheInterceptor.java:61)
    at org.springframework.cache.jcache.interceptor.CacheResultInterceptor.invoke(CacheResultInterceptor.java:49)
    at org.springframework.cache.jcache.interceptor.JCacheAspectSupport.execute(JCacheAspectSupport.java:131)
    at org.springframework.cache.jcache.interceptor.JCacheAspectSupport.execute(JCacheAspectSupport.java:102)
    at org.springframework.cache.jcache.interceptor.JCacheInterceptor.invoke(JCacheInterceptor.java:61)

Sample project available here

JCacheManager.enableManagement spec violation

The spec says:
"The platform MBeanServer is obtained using ManagementFactory.getPlatformMBeanServer()"

but the current enableManagement implementation uses registerObject which is implemented as follows

private void registerObject(final JCacheMXBean cacheMXBean) throws NotCompliantMBeanException,
        InstanceAlreadyExistsException, MBeanRegistrationException, MalformedObjectNameException {
        final ObjectName objectName = new ObjectName(cacheMXBean.getObjectName());
        if(mBeanServer.queryNames(objectName, null).isEmpty()) {
            mBeanServer.registerMBean(cacheMXBean, objectName);
        }
    }

mBeanServer is a newly created MBeanServer and is not obtained using ManagementFactory.getPlatformMBeanServer().

Arithmetic exception in JCacheStatistics

The two methods getCacheMissPercentage() and getCacheHitPercentage() throw an ArithmeticException (dividing by zero) if you want to print statistics after the cache just started (hit + miss count = 0).

Workarounds are:

@OverRide
public float getCacheMissPercentage() {
long sum = this.statistics.getCacheHitCount() + this.statistics.getCacheMissCount();
if (sum <= 0) {
return 0;
}
return (float) (this.statistics.getCacheMissCount() / ((double)sum)) * 100;
}

respectively

@OverRide
public float getCacheHitPercentage() {
long sum = this.statistics.getCacheHitCount() + this.statistics.getCacheMissCount();
if (sum <= 0) {
return 0;
}
return (float) ((this.statistics.getCacheHitCount() / ((double)sum)) * 100);
}

Update docs

At least readmes are outdated.
But potentially more

Push to Maven repository

Its great that somebody picked this up and is updating it to comply with the latest version of the spec. Do you have plans to release this to a Maven repo soon (even in SNAPSHOT form)?

Read configuration from file path

I like to externalize my ehcache.xml, so when I deploy to different environments (dev = no replication, prod = replication) I do not want have to repackage my wars. Is there another option besides classpath loading?

cacheManager.getCache(cacheName) is null

Trying to build a very simple example according to Greg's blog I came across this one:

Cache<Integer, String> cache = cacheManager.getCache(cacheName);

cache == null

If I use the createCacheBuilder I actually get the cache instance ...

  • M

JCacheManager.unwrap

Hi, I think someone forgot to return the casted cacheManager.
So instead of

@Override
    public <T> T unwrap(final Class<T> clazz) {
        if(clazz.isAssignableFrom(getClass())) {
            return clazz.cast(this);
        }
        if(clazz.isAssignableFrom(cacheManager.getClass())) {
            clazz.cast(cacheManager);
        }
        throw new IllegalArgumentException();
    }

it should be

@Override
    public <T> T unwrap(final Class<T> clazz) {
        if(clazz.isAssignableFrom(getClass())) {
            return clazz.cast(this);
        }
        if(clazz.isAssignableFrom(cacheManager.getClass())) {
            return clazz.cast(cacheManager);
        }
        throw new IllegalArgumentException();
    }

Or am I missing something?

Error creating caches with a TTL

This works :

JCacheConfiguration jCacheConfiguration = new JCacheConfiguration(null, null, null, null);
cache = cacheManager.createCache(this.name, jCacheConfiguration);

while this gives me a NPE :

CacheConfiguration cacheConfiguration = new CacheConfiguration();
cacheConfiguration.setTimeToLiveSeconds(NO_EXPIRE);
cacheConfiguration.setTimeToIdleSeconds(NO_EXPIRE);
JCacheConfiguration jCacheConfiguration = new JCacheConfiguration(cacheConfiguration);
cache = cacheManager.createCache(this.name, jCacheConfiguration);

where NO_EXPIRE is equal to 60 * 60 * 24 * 365 * 10

The only difference I see on code paths is that the second doesn't set an expire factory, while the first path does.

ExpiryPolicy on existing caches lost after calling getCache on non-existing cache

Had a problem with caches that seem to loose their expiry information.
Tracked down the problem to be caused by calling getCache on a non-existing cache.
It was used to check if the cache existed and if not, create it.

It looks like when JCacheManager.getCache() are not finding a cache in allCaches it
calls refreshallCaches() which will recreate them, but the expiry-configuration seems to be lost.

This test will show the error as the last assert will fail because the expiry-policy is lost.

@Test
public void testRefreshAllCachesError() {
    final CachingProvider cachingProvider = Caching.getCachingProvider();
    final CacheManager cacheManager = cachingProvider.getCacheManager();

    String cacheNameExisting = "existingCache";
    String cacheNameNonExisting = "nonExistingCache";

    MutableConfiguration configuration = new MutableConfiguration();
    configuration.setExpiryPolicyFactory(ModifiedExpiryPolicy.factoryOf(new Duration(TimeUnit.MINUTES, 60)));

    configuration.setExpiryPolicyFactory(ModifiedExpiryPolicy.factoryOf(new Duration(TimeUnit.MINUTES, 60)));
    cacheManager.createCache(cacheNameExisting, new JCacheConfiguration(configuration));

    Cache<Object, Object> sampleCache = cacheManager.getCache(cacheNameExisting);
    assertNotNull(sampleCache);
    assertThat(sampleCache.getConfiguration(JCacheConfiguration.class).getExpiryPolicy().getExpiryForCreation().getDurationAmount(), is(60l));

    // this will trigger refreshAllCaches which recreates caches
    assertNull(cacheManager.getCache(cacheNameNonExisting));

    // existing cache is OK but ...
    assertThat(sampleCache.getConfiguration(JCacheConfiguration.class).getExpiryPolicy().getExpiryForCreation().getDurationAmount(), is(60l));

    // ... if we fetch it again from cacheManager:
    // this will fail as cache existingCache has been recreated and lost its expiry-policy
    sampleCache = cacheManager.getCache(cacheNameExisting);
    assertThat(sampleCache.getConfiguration(JCacheConfiguration.class).getExpiryPolicy().getExpiryForCreation().getDurationAmount(), is(60l));
}

Re-enable TCK runner

We probably should either remove or upgrade the TCK from this project.
I may be in favor of the former... Probably better if we use the JSR's TCK directly (what I did for this 1.0.0-rc upgrade btw)

JCacheListenerAdapter not working at all because of wrong usage of isAssignableFrom()

About:

net.sf.ehcache.jcache.JCacheListenerAdapter.implementsMethods

This function is called like this:

    removedListener = implementsMethods(CacheEntryRemovedListener.class);
    createdListener = implementsMethods(CacheEntryCreatedListener.class);
    updatedListener = implementsMethods(CacheEntryUpdatedListener.class);
    expiredListener = implementsMethods(CacheEntryExpiredListener.class);

Though implemented like this:

private boolean implementsMethods(Class cls) {
    return cacheListener.getClass().isAssignableFrom(cls);
}

But should be implemented like this:

private boolean implementsMethods(Class cls) {
    return cls.isAssignableFrom(cacheListener.getClass());
}

See: http://www.ralfebert.de/blog/java/isassignablefrom/

This stops any EventListeners from working at all.

Default configuration in ehcache.xml is not used on created JCache instances

I have the following default configuration that I want to be applied to all caches created by CacheManager.createCache(). Here is my ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect"  dynamicConfig="true"> 
  <!-- see http://www.ehcache.org/ehcache.xml -->
  <defaultCache 
    maxEntriesLocalHeap="200000" 
    eternal="false"
    timeToIdleSeconds="1200"
    timeToLiveSeconds="1200">    
    <persistence strategy="localTempSwap"/>
  </defaultCache>
</ehcache>

I try to create the cache as follows:

String providerName = "org.ehcache.jcache.JCacheCachingProvider";
CachingProvider cachingProvider = Caching.getCachingProvider(providerName);
CacheManager cacheManager = cachingProvider.getCacheManager();
CompleteConfiguration<ComposedKey, Object> config = new MutableConfiguration<ComposedKey, Object>()
    .setTypes(ComposedKey.class, Object.class)
    .setExpiryPolicyFactory(FactoryBuilder.factoryOf(new AccessedExpiryPolicy(new Duration(TimeUnit.MINUTES, 30))))
    .setReadThrough(false)
    .setWriteThrough(false)
    .addCacheEntryListenerConfiguration(
        new MutableCacheEntryListenerConfiguration<ComposedKey, Object>(new CacheListenerManagerJSR107Factory(), null, true,
            true));
;
Cache<ComposedKey, Object> cache = cacheManager.createCache("cache", config);

But it seems the default cache configuration is not used as when debugging the cache has the following attributes:

[ name = orACJ2rF-1 status = STATUS_ALIVE eternal = false overflowToDisk = false maxEntriesLocalHeap = 1000 maxEntriesLocalDisk = 0 memoryStoreEvictionPolicy = LRU timeToLiveSeconds = 0 timeToIdleSeconds = 0 persistence = none diskExpiryThreadIntervalSeconds = 120 cacheEventListeners: org.ehcache.jcache.JCacheListenerAdapter ; orderedCacheEventListeners:  maxBytesLocalHeap = 0 overflowToOffHeap = false maxBytesLocalOffHeap = 0 maxBytesLocalDisk = 0 pinned = false ]

Also, When I declare a named cache in ehcache.xml and give the same name to CacheManager.createCache() I get a javax.cache.CacheException at org.ehcache.jcache.JCacheManager.createCache(JCacheManager.java:106)

Update ehcache-jcache to use the 0.5 api

in the branch 0.5-api-changes there is a version that currently compiles against the 0.5 spec but doesn't pass the TCK tests yet.

(most notably because the CacheEntryProcessor isn't implemented yet - it's just a stubbed method throwing an exception right now)

The CacheEntryProcessor might not be that hard to implement (I haven't spent any time trying to do it yet)

Potential Unreleased Lock

In V load(K key) method of org.ehcache.jcache.JCache class ehcache.acquireWriteLockOnKey(key) lock doesn't released when value exists.
Lock must be acquired if value not exists in cache.

V load(K key) {
        V value;
        final Element e = ehcache.get(key);
        if(e != null) {
            return (V)e.getObjectValue();
        }
        try {
            ehcache.acquireWriteLockOnKey(key);
            try {
                value = cacheLoader.load(key);
            } catch (Exception ex) {
                throw new CacheLoaderException(ex);
            }
            if(value != null) {
                putWithoutWriter(key, value);
            }
        } finally{
            ehcache.releaseWriteLockOnKey(key);
        }
        return value;
    }

cache-annotations-cdi: java.lang.IllegalArgumentException: cacheValueParameter cannot be null

Hi,

using following artefacts

    <dependency>
        <groupId>org.ehcache</groupId>
        <artifactId>jcache</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>

    <dependency>
        <groupId>org.jsr107.ri</groupId>
        <artifactId>cache-annotations-ri-cdi</artifactId>
        <version>1.0.0</version>
    </dependency>

I get the following Exception when returning null from an
@CachePut(cacheName = CacheNames.USER_DAO_CACHE)

java.lang.IllegalArgumentException: cacheValueParameter cannot be null
2014-05-07 15:24:11.669231+00:00 app web.1 - - at org.jsr107.ri.annotations.CachePutMethodDetails.(CachePutMethodDetails.java:49)
2014-05-07 15:24:11.669233+00:00 app web.1 - - at org.jsr107.ri.annotations.AbstractCacheLookupUtil.createCachePutMethodDetails(AbstractCacheLookupUtil.java:332)
2014-05-07 15:24:11.669235+00:00 app web.1 - - at org.jsr107.ri.annotations.AbstractCacheLookupUtil.getMethodDetails(AbstractCacheLookupUtil.java:193)
2014-05-07 15:24:11.669236+00:00 app web.1 - - at org.jsr107.ri.annotations.AbstractCacheLookupUtil.getCacheKeyInvocationContext(AbstractCacheLookupUtil.java:72)
2014-05-07 15:24:11.669238+00:00 app web.1 - - at org.jsr107.ri.annotations.AbstractCachePutInterceptor.cachePut(AbstractCachePutInterceptor.java:48)
2014-05-07 15:24:11.669239+00:00 app web.1 - - at org.jsr107.ri.annotations.cdi.CachePutInterceptor.cachePut(CachePutInterceptor.java:51)
2014-05-07 15:24:11.669241+00:00 app web.1 - - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2014-05-07 15:24:11.669243+00:00 app web.1 - - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
2014-05-07 15:24:11.669244+00:00 app web.1 - - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2014-05-07 15:24:11.669246+00:00 app web.1 - - at java.lang.reflect.Method.invoke(Method.java:606)
2014-05-07 15:24:11.669247+00:00 app web.1 - - at org.jboss.weld.interceptor.proxy.SimpleMethodInvocation.invoke(SimpleMethodInvocation.java:30)
2014-05-07 15:24:11.669249+00:00 app web.1 - - at org.jboss.weld.interceptor.proxy.SimpleInterceptionChain.invokeNextInterceptor(SimpleInterceptionChain.java:69)
2014-05-07 15:24:11.669250+00:00 app web.1 - - at org.jboss.weld.interceptor.proxy.InterceptorMethodHandler.executeInterception(InterceptorMethodHandler.java:112)
2014-05-07 15:24:11.669252+00:00 app web.1 - - at org.jboss.weld.interceptor.proxy.InterceptorMethodHandler.invoke(InterceptorMethodHandler.java:88)
2014-05-07 15:24:11.669254+00:00 app web.1 - - at org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler.invoke(CombinedInterceptorAndDecoratorStackMethodHandler.java:55)
2014-05-07 15:24:11.669255+00:00 app web.1 - - at org.remedia.foxydeal.clickserver.persistence.domain.UserDAO$Proxy$_$$WeldSubclass.get(UserDAO$Proxy$$$_WeldSubclass.java)

Expiration configured in ehcache.xml in not honoured

Cache element expiry does not seem to work properly when the JCache API is used with a cache that is configured through ehcache.xml.

ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true">
    <cache name="cache123"
           maxEntriesLocalHeap="123"
           eternal="false"
           overflowToDisk="false"
           timeToIdleSeconds="1"
           timeToLiveSeconds="1"
           memoryStoreEvictionPolicy="LRU">
    </cache>
</ehcache>

My understanding is that the above config file creates an in-memory cache with 123 elements, and that elements time out after 1 second. I believe the following test case verifies my assumptions, note that the second test case uses the unwrapped ehcache instance from the JCache API:

EhCache test case:

package org.example;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.ehcache.jcache.JCache;
import org.junit.Assert;
import org.junit.Test;

import javax.cache.Caching;

public class EhCacheTest {

    private final String cacheName = "cache123";

    private void checkCache(Cache cache) throws InterruptedException {
        Assert.assertNull("Cache should initially be empty", cache.get("test"));
        cache.put(new Element("test", new Object()));
        Assert.assertNotNull("Should not have timed out", cache.get("test"));
        Thread.sleep(2000);
        Assert.assertNull("Should have timed out", cache.get("test"));
    }

    @Test
    public void testEhCacheDirect() throws InterruptedException {
        CacheManager manager = CacheManager.newInstance();
        Cache cache = manager.getCache(cacheName);
        checkCache(cache);
    }

    @Test
    public void testEhCacheFromJCache() throws InterruptedException {
        JCache jcache = Caching.getCachingProvider().getCacheManager().getCache(cacheName).unwrap(JCache.class);
        Cache cache = (Cache) jcache.unwrap(Cache.class);
        checkCache(cache);
    }
}

The above tests are both successful. When accessing the "same" cache through the JCache API however, the elements does not seem to expire. The test testJCacheXmlConfigured below consistently fails on the third assert ("Should have timed out by now").

JCache test case:

package org.example;

import org.junit.Assert;
import org.junit.Test;

import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.expiry.Duration;
import javax.cache.expiry.ModifiedExpiryPolicy;
import javax.cache.spi.CachingProvider;
import java.util.concurrent.TimeUnit;

public class JCacheTest {

    CachingProvider provider = Caching.getCachingProvider();
    CacheManager manager = provider.getCacheManager();

    protected void checkCache(Cache cache) throws InterruptedException {
        final String key = "test";
        Assert.assertNull("Cache should initially be empty", cache.get(key));
        cache.put(key, new Object());
        Assert.assertNotNull("Should not have timed out yet", cache.get(key));
        Thread.sleep(2000);
        Assert.assertNull("Should have timed out by now", cache.get(key));
    }

    @Test
    public void testJCacheManuallyConfigured() throws InterruptedException {
        CachingProvider provider = Caching.getCachingProvider();
        CacheManager manager = provider.getCacheManager();
        Cache cache = manager.createCache("myManuallyConfiguredCache",
                new MutableConfiguration()
                        .setStoreByValue(false)
                        .setExpiryPolicyFactory(
                                ModifiedExpiryPolicy.factoryOf(new Duration(TimeUnit.MILLISECONDS, 1000))
                        ));
        checkCache(cache);
    }

    @Test
    public void testJCacheXmlConfigured() throws InterruptedException {
        final String cacheName = "cache123";
        Cache cache = manager.getCache(cacheName);
        checkCache(cache);
    }
}

Updating cache with EntryProcessor does not update

I use a cache configured with

copyOnRead="true"
copyOnWrite="true"

In the processor the code looks more or less like this:

Value value = entry.getValue();
value.modifySomehow();
entry.setValue(value);

after this, the cache remains unchanged.

Looking at the code it's easy to see why

in JCache, line 884

        void apply(final JCache<K, V> jCache) {
            if(deleted && !skipDelete) {
                jCache.remove(key);
            }
            if(newValue != initialValue && newValue != null) {
                jCache.put(key, newValue);
            }
        }

So in my case newValue == initialValue but it should still do a put as the value was modified. Maybe if it's using copyOnRead/copyOnWrite it should always put the value? Or is there something I missed/another way I can force an update (besides actually creating a new Value object which I'd rather not do).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.