Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PassiveExpiringMap not expiring objects

I was expecting org.apache.commons.collections4.map.PassiveExpiringMap to work out of the box. Unfortunately it doesn't work for me in the most obvious use case of expiring objects on time. The code below creates an expiration policy of 5 seconds. The test waits for 10 seconds which is a time by which all map object should be expired and removed. But they're not.

import org.apache.commons.collections4.map.PassiveExpiringMap;
import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
    
public class PassiveExpiringMapTest {
    @Test
    public void givenDataMap_whenWrappingMapWithPassiveExpiringMap_thenObjectsAreRemovedWhenExpired() {
        
        final Map<String, Integer> m = new HashMap<>();
        m.put("one", Integer.valueOf(1));
        m.put("two", Integer.valueOf(2));
        m.put("three", Integer.valueOf(3));

        PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<String, Integer>
            expirationPolicy = new PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<>(
            5, TimeUnit.SECONDS);

        PassiveExpiringMap<String, Integer> expiringMap = new PassiveExpiringMap<>(expirationPolicy, m);

        int initialCapacity = expiringMap.size();
        System.out.println("initialCapacity = " + initialCapacity);
        Assert.assertEquals(3, initialCapacity);

        System.out.println("Sleeping...");
        try { Thread.sleep(10000L); } catch (InterruptedException e) { }

        int updatedCapacity = expiringMap.size();
        System.out.println("updatedCapacity = " + updatedCapacity);
        Integer one = expiringMap.get("one");
        Assert.assertNull(one);
        Assert.assertEquals(0, updatedCapacity);
    }
}

The test fails with the following output:

initialCapacity = 3
Sleeping...
updatedCapacity = 3

java.lang.AssertionError: expected null, but was:<1>

    at org.junit.Assert.fail(Assert.java:88)
    at org.junit.Assert.failNotNull(Assert.java:755)
    at org.junit.Assert.assertNull(Assert.java:737)
    at org.junit.Assert.assertNull(Assert.java:747)

Any idea what I am missing?

like image 790
Jacobs2000 Avatar asked Jul 31 '26 06:07

Jacobs2000


1 Answers

Looking at the source code of PassiveExpiringMap helped me figure out why my original version did not work. Initializing using a map causes an inner expirationMap field to be empty. expirationMap must contain an entry for every object in order for expired objects to be evicted. In order for this to happen the put method needs to be used. Modified code below works. Note that objects are added to expiringMap directly, rather than to the HashMap as before:

import org.apache.commons.collections4.map.PassiveExpiringMap;
import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

public class PassiveExpiringMapTest {

    @Test
    public void givenDataMap_whenWrappingMapWithPassiveExpiringMap_thenObjectsAreRemovedWhenExpired() {
        
        PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<String, Integer>
            expirationPolicy = new PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<>(
            5, TimeUnit.SECONDS);

        PassiveExpiringMap<String, Integer> expiringMap = new PassiveExpiringMap<>(expirationPolicy, new HashMap<>());
        expiringMap.put("one", Integer.valueOf(1));
        expiringMap.put("two", Integer.valueOf(2));
        expiringMap.put("three", Integer.valueOf(3));
        int initialCapacity = expiringMap.size();
        System.out.println("initialCapacity = " + initialCapacity);
        Assert.assertEquals(3, initialCapacity);

        System.out.println("Sleeping...");
        try { Thread.sleep(10000L); } catch (InterruptedException e) { }

        int updatedCapacity = expiringMap.size();
        System.out.println("updatedCapacity = " + updatedCapacity);
        Integer one = expiringMap.get("one");
        Assert.assertNull(one);
        Assert.assertEquals(0, updatedCapacity);
    }
}
like image 163
Jacobs2000 Avatar answered Aug 01 '26 19:08

Jacobs2000



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!