properties.put(name, value);
}
+ /**
+ * Removes a property.
+ * @param name property name
+ */
+ public void removeProperty(String name) {
+ properties.remove(name);
+ }
+
/**
* Obtains the given property.
*
return null;
}
- CompletableFuture<OperationOutcome> future = retrievers.get(name);
- if (future != null) {
- return future;
- }
+ /*
+ * Return any existing future, if it wasn't canceled. Otherwise, start a new
+ * request.
+ */
- future = params.start();
+ // @formatter:off
+ CompletableFuture<OperationOutcome> oldFuture =
+ retrievers.computeIfPresent(name, (key, future) -> future.isCancelled() ? null : future);
+ // @formatter:on
- CompletableFuture<OperationOutcome> oldFuture = retrievers.putIfAbsent(name, future);
if (oldFuture != null) {
+ return oldFuture;
+ }
+
+ /*
+ * Note: must NOT invoke params.start() within retrievers.compute(), as start()
+ * may invoke obtain() which would cause a recursive update to the retrievers map.
+ */
+ CompletableFuture<OperationOutcome> future = params.start();
+
+ if ((oldFuture = retrievers.putIfAbsent(name, future)) != null) {
future.cancel(false);
return oldFuture;
}