ehcache based on date
Asked Answered
C

4

11

I'm working with ehcache 2.5.4.

I have an object that needs to be cached through out the day and refreshed with a new value at 00:00am every day.

Currently with ehcache configurations I can only set the time to live and time to idle, but that will depend on the time I created the object or when it's used. ie:

    <cache
    name="cache.expiry.application.date_status"
    maxElementsInMemory="10"
    eternal="false"
    timeToIdleSeconds="60"
    timeToLiveSeconds="50" />

Is there a way to get ehcache to expire specific caches based on specific times.

Charissecharita answered 18/12, 2012 at 22:53 Comment(1)
It's not possible directly. What about using an external CRON trigger (quartz-scheduler?) to clear that cache manually?Passing
D
11

I've done this by extending Ehcache's Element class like so:

class EvictOnGivenTimestampElement extends Element {

    private static final long serialVersionUID = ...;
    private final long evictOn;

    EvictOnGivenTimestampElement(final Serializable key, final Serializable value, final long evictOn) {
        super(key, value);
        this.evictOn = evictOn;
    }

    @Override
    public boolean isExpired() {
        return System.currentTimeMillis() > evictOn;
    }
}

The rest is as easy as putting new instance of EvictOnGivenTimestampElement object into the cache instead of Element.

Advantage of this approach is that you don't have to worry about external cronjobs, etc. And the obvious disadvantage is the attachment to Ehcache API which I hope won't change too often.

Delmadelmar answered 19/12, 2012 at 12:30 Comment(3)
That seems a really neat way of doing it. Can I do it with annotation? Or do I need to manually create the CacheManager. I'm using it with Spring and Hibernate.Charissecharita
Element is a very basic concept of Ehcache, and has no direct relationships to CacheManager. Regarding annotations - I have no idea as I don't use annotations... If you'd want to set expiration in annotation that's unlikely to be supported but you can always roll out your own extension which works the way you want.Delmadelmar
why can't we use setTimeToLive() while inserting the Element to cache. What is the need of creating EvictOnGivenTimestampElement class again?Varrian
C
5

EHCache only supports eviction after a certain period of time (either being in the cache or due to inactivity). However, you should be able to accomplish that fairly easily by scheduling the removal with something like this:

    Timer t = new Timer(true);
    Integer interval = 24 * 60 * 60 * 1000; //24 hours
    Calendar c = Calendar.getInstance();
    c.set(Calendar.HOUR, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);


    t.scheduleAtFixedRate( new TimerTask() {
            public void run() {
                Cache c = //retrieve cache                  
                c.removeAll();                                            
            }
        }, c.getTime(), interval);

This basic example uses the Java Timer class to illustrate, but any scheduler could be utilized. Every 24 hours, starting from midnight - this would run and remove all the elements from the specified cache. The actual run method could be modified to remove elements matching a certain criteria as well.

You'd just need to make sure you start it when the application is started.

Colver answered 18/12, 2012 at 23:15 Comment(0)
I
3

With Ehcache 3.2 I implemented an Expiry extension.

public class EvictAtMidnightExpiry implements Expiry {

    @Override
    public Duration getExpiryForCreation(Object key, Object value) {
        DateTime now = new DateTime();
        DateTime resetAt = now.plusDays(1).withTimeAtStartOfDay();
        long difference = resetAt.toDateTime().getMillis() - now.getMillis();
        return Duration.of(difference, TimeUnit.MILLISECONDS);
    }

    @Override
    public Duration getExpiryForAccess(Object key, ValueSupplier value) {
        return null;
    }

    @Override
    public Duration getExpiryForUpdate(Object key, ValueSupplier oldValue, Object newValue) {
        return null;
    }
}

Now, I have logging etc as well but I minimalized my code for cleanness.

Then you just need to configure it in your configuration builder.

CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class, ResourcePoolsBuilder.heap(1000)).withExpiry(new EvictAtMidnightExpiry()).build()

Clearly Ehcache improved on there API's somewhat from 2.5 to 3.2 as you don't need to create your own 'element' and ensure it's usage to initiate expiry or eviction policies. The policies are now cache bound.

Intertwine answered 18/12, 2016 at 0:43 Comment(0)
F
0

Implementation for ehcache 3.8 without additional libraries using LocalTime:

import java.time.Duration;
import java.time.LocalTime;
import java.util.function.Supplier;
import org.ehcache.expiry.ExpiryPolicy;

/**
 * XML configuration example:
 * <pre>
 *   {@code
 *   <cache alias="...
 *     <expiry>
 *       <class>org.example.MidnightExpiry</class>
 *     </expiry>
 *   </cache>
 *   }
 * </pre>
 */
public class MidnightExpiry implements ExpiryPolicy<Object, Object> {

  private static final LocalTime MIDNIGHT = LocalTime.of(23, 59, 59, 999999999);

  @Override
  public Duration getExpiryForCreation(Object key, Object value) {
    return Duration.between(LocalTime.now(), MIDNIGHT);
  }
  
  @Override
  public Duration getExpiryForAccess(Object key, Supplier value) {
    // do not change expiry on access
    return null;
  }

  @Override
  public Duration getExpiryForUpdate(Object key, Supplier oldValue, Object newValue) {
    // do not change expiry on update
    return null;
  }
}
Francophobe answered 12/5, 2023 at 7:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.