Skip to content

Commit 6be13d6

Browse files
committed
Fixes for the JCache 1.1 preview, except for 1.0 TCK breaking changes
A preview of JCache 1.1 has been made available for review until 11/18. This update includes JavaDoc fixes, spec corrections, additional tests, and fixes incorrect tests. The 1.1 TCK is not compatible with 1.0's TCK. Some tests assert the opposite behavior, such as relaxing types to not throw exceptions or changing the statistics of putIfAbsent. Since 1.1 is in preview, we maintain 1.0 compatibility with the acceptable fixes uncovered by the later TCK. In particular the specification requires that a loader, writer, expiry, and listeners are closed if they implement Closable. This was in the JavaDoc but not the TCK, making it easy to overlook. https://jcp.org/aboutJava/communityprocess/maintenance/jsr107/107MR1-summary.html
1 parent 74a3dc3 commit 6be13d6

File tree

5 files changed

+61
-11
lines changed

5 files changed

+61
-11
lines changed

jcache/src/main/java/com/github/benmanes/caffeine/jcache/CacheFactory.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,6 @@
4747
* @author [email protected] (Ben Manes)
4848
*/
4949
final class CacheFactory {
50-
// Avoid asynchronous executions due to the TCK's poor test practices
51-
// https://github.com/jsr107/jsr107tck/issues/78
52-
static final boolean USE_DIRECT_EXECUTOR =
53-
System.getProperties().containsKey("org.jsr107.tck.management.agentId");
54-
5550
final Config rootConfig;
5651
final CacheManager cacheManager;
5752

@@ -143,8 +138,8 @@ private final class Builder<K, V> {
143138
this.caffeine = Caffeine.newBuilder();
144139
this.statistics = new JCacheStatisticsMXBean();
145140
this.ticker = config.getTickerFactory().create();
141+
this.executor = config.getExecutorFactory().create();
146142
this.expiryPolicy = config.getExpiryPolicyFactory().create();
147-
this.executor = USE_DIRECT_EXECUTOR ? Runnable::run : config.getExecutorFactory().create();
148143
this.dispatcher = new EventDispatcher<>(executor);
149144

150145
caffeine.executor(executor);

jcache/src/main/java/com/github/benmanes/caffeine/jcache/CacheProxy.java

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static java.util.stream.Collectors.toList;
2020
import static java.util.stream.Collectors.toMap;
2121

22+
import java.io.Closeable;
2223
import java.util.ArrayList;
2324
import java.util.HashMap;
2425
import java.util.HashSet;
@@ -57,6 +58,7 @@
5758
import com.github.benmanes.caffeine.jcache.configuration.CaffeineConfiguration;
5859
import com.github.benmanes.caffeine.jcache.copy.Copier;
5960
import com.github.benmanes.caffeine.jcache.event.EventDispatcher;
61+
import com.github.benmanes.caffeine.jcache.event.Registration;
6062
import com.github.benmanes.caffeine.jcache.integration.DisabledCacheWriter;
6163
import com.github.benmanes.caffeine.jcache.management.JCacheMXBean;
6264
import com.github.benmanes.caffeine.jcache.management.JCacheStatisticsMXBean;
@@ -864,6 +866,11 @@ public CacheManager getCacheManager() {
864866
return cacheManager;
865867
}
866868

869+
@Override
870+
public boolean isClosed() {
871+
return closed;
872+
}
873+
867874
@Override
868875
public void close() {
869876
if (isClosed()) {
@@ -875,14 +882,43 @@ public void close() {
875882
enableStatistics(false);
876883
cacheManager.destroyCache(name);
877884
closed = true;
885+
886+
Throwable thrown = null;
887+
thrown = tryClose(expiry, thrown);
888+
thrown = tryClose(writer, thrown);
889+
thrown = tryClose(cacheLoader.orElse(null), thrown);
890+
for (Registration<K, V> registration : dispatcher.registrations()) {
891+
thrown = tryClose(registration.getCacheEntryListener(), thrown);
892+
}
893+
if (thrown != null) {
894+
logger.log(Level.WARNING, "Failure when closing cache resources", thrown);
895+
}
878896
}
879897
}
880898
cache.invalidateAll();
881899
}
882900

883-
@Override
884-
public boolean isClosed() {
885-
return closed;
901+
/**
902+
* Attempts to close the resource. If an error occurs and an outermost exception is set, then adds
903+
* the error to the suppression list.
904+
*
905+
* @param o the resource to close if Closeable
906+
* @param outer the outermost error, or null if unset
907+
* @return the outermost error, or null if unset and successful
908+
*/
909+
private static Throwable tryClose(Object o, @Nullable Throwable outer) {
910+
if (o instanceof Closeable) {
911+
try {
912+
((Closeable) o).close();
913+
} catch (Throwable t) {
914+
if (outer == null) {
915+
return t;
916+
}
917+
outer.addSuppressed(t);
918+
return outer;
919+
}
920+
}
921+
return null;
886922
}
887923

888924
@Override

jcache/src/main/java/com/github/benmanes/caffeine/jcache/event/EventDispatcher.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
import static java.util.Objects.requireNonNull;
1919

2020
import java.util.ArrayList;
21+
import java.util.Collections;
2122
import java.util.List;
2223
import java.util.Map;
24+
import java.util.Set;
2325
import java.util.concurrent.CompletableFuture;
2426
import java.util.concurrent.CompletionException;
2527
import java.util.concurrent.ConcurrentHashMap;
@@ -62,6 +64,11 @@ public EventDispatcher(Executor exectuor) {
6264
this.exectuor = requireNonNull(exectuor);
6365
}
6466

67+
/** Returns the cache entry listener registrations. */
68+
public Set<Registration<K, V>> registrations() {
69+
return Collections.unmodifiableSet(dispatchQueues.keySet());
70+
}
71+
6572
/**
6673
* Registers a cache entry listener based on the supplied configuration.
6774
*

jcache/src/main/java/com/github/benmanes/caffeine/jcache/event/EventTypeAwareListener.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import static java.util.Objects.requireNonNull;
1919

20+
import java.io.Closeable;
21+
import java.io.IOException;
2022
import java.util.logging.Level;
2123
import java.util.logging.Logger;
2224

@@ -36,7 +38,7 @@
3638
*/
3739
final class EventTypeAwareListener<K, V> implements CacheEntryCreatedListener<K, V>,
3840
CacheEntryUpdatedListener<K, V>, CacheEntryRemovedListener<K, V>,
39-
CacheEntryExpiredListener<K, V> {
41+
CacheEntryExpiredListener<K, V>, Closeable {
4042
static final Logger logger = Logger.getLogger(EventTypeAwareListener.class.getName());
4143

4244
final CacheEntryListener<? super K, ? super V> listener;
@@ -63,6 +65,9 @@ public boolean isCompatible(@Nonnull EventType eventType) {
6365
/** Processes the event and logs if an exception is thrown. */
6466
public void dispatch(@Nonnull JCacheEntryEvent<K, V> event) {
6567
try {
68+
if (event.getSource().isClosed()) {
69+
return;
70+
}
6671
switch (event.getEventType()) {
6772
case CREATED:
6873
onCreated(event);
@@ -116,4 +121,11 @@ public void onExpired(Iterable<CacheEntryEvent<? extends K, ? extends V>> events
116121
((CacheEntryExpiredListener<K, V>) listener).onExpired(events);
117122
}
118123
}
124+
125+
@Override
126+
public void close() throws IOException {
127+
if (listener instanceof Closeable) {
128+
((Closeable) listener).close();
129+
}
130+
}
119131
}

jcache/src/main/java/com/github/benmanes/caffeine/jcache/event/Registration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
* @author [email protected] (Ben Manes)
2828
*/
29-
final class Registration<K, V> {
29+
public final class Registration<K, V> {
3030
private final CacheEntryListenerConfiguration<K, V> configuration;
3131
private final EventTypeAwareListener<K, V> listener;
3232
private final CacheEntryEventFilter<K, V> filter;

0 commit comments

Comments
 (0)