You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by re...@apache.org on 2025/08/21 08:11:10 UTC
(sling-org-apache-sling-resourceresolver) branch SLING-12894 updated (69d57b9b -> 2296b7a7)
This is an automated email from the ASF dual-hosted git repository.
reschke pushed a change to branch SLING-12894
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git
from 69d57b9b SLING-12894: alias refactoring - support observation events while bg init not finished
new 69fdf154 SLING-12894: alias refactoring - support observation events while bg init not finished - wip
new 2296b7a7 SLING-12894: alias refactoring - support observation events while bg init not finished - wip
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../resourceresolver/impl/mapping/MapEntries.java | 105 ++++++++++++---------
.../impl/mapping/AliasMapEntriesTest.java | 17 ++--
.../impl/mapping/MapEntriesTest.java | 16 ++--
.../impl/mapping/VanityPathMapEntriesTest.java | 13 +--
4 files changed, 86 insertions(+), 65 deletions(-)
(sling-org-apache-sling-resourceresolver) 01/02: SLING-12894: alias refactoring - support observation events while bg init not finished - wip
Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
reschke pushed a commit to branch SLING-12894
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git
commit 69fdf154e020d5da17e5312fe1f06a344e72b34d
Author: Julian Reschke <re...@apache.org>
AuthorDate: Wed Aug 20 14:07:00 2025 +0100
SLING-12894: alias refactoring - support observation events while bg init not finished - wip
---
.../resourceresolver/impl/mapping/MapEntries.java | 105 ++++++++++++---------
.../impl/mapping/AliasMapEntriesTest.java | 17 ++--
.../impl/mapping/MapEntriesTest.java | 5 +-
.../impl/mapping/VanityPathMapEntriesTest.java | 13 +--
4 files changed, 80 insertions(+), 60 deletions(-)
diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
index c8e47673..7356058c 100644
--- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
+++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java
@@ -35,6 +35,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
+import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
@@ -101,7 +102,8 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
private final Map<String, List<MapEntry>> resolveMapsMap;
- private List<Map.Entry<String, ResourceChange.ChangeType>> resourceChangeQueue;
+ private List<Map.Entry<String, ResourceChange.ChangeType>> resourceChangeQueueForAliases;
+ private List<Map.Entry<String, ResourceChange.ChangeType>> resourceChangeQueueForVanityPaths;
private Collection<MapEntry> mapMaps;
@@ -133,7 +135,8 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
this.registration = registerResourceChangeListener(bundleContext);
- this.vph = new VanityPathHandler(this.factory, this.resolveMapsMap, this.initializing, this::drainQueue);
+ this.vph =
+ new VanityPathHandler(this.factory, this.resolveMapsMap, this.initializing, this::drainVanityPathQueue);
this.vph.initializeVanityPaths();
if (metrics.isPresent()) {
@@ -164,19 +167,22 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
log.info("Registering for {}", Arrays.toString(factory.getObservationPaths()));
- this.resourceChangeQueue = Collections.synchronizedList(new LinkedList<>());
+ this.resourceChangeQueueForAliases = Collections.synchronizedList(new LinkedList<>());
+ this.resourceChangeQueueForVanityPaths = Collections.synchronizedList(new LinkedList<>());
+
return bundleContext.registerService(ResourceChangeListener.class, this, props);
}
- private boolean addResource(final String path, final AtomicBoolean resolverRefreshed) {
+ private boolean addResource(String path, boolean forAlias, boolean forVanityPath, AtomicBoolean resolverRefreshed) {
this.initializing.lock();
try {
this.refreshResolverIfNecessary(resolverRefreshed);
- final Resource resource = this.resolver != null ? resolver.getResource(path) : null;
+
+ Resource resource = this.resolver != null ? resolver.getResource(path) : null;
if (resource != null) {
- boolean vanityPathAdded = vph.doAddVanity(resource);
- boolean aliasAdded = ah.doAddAlias(resource);
+ boolean vanityPathAdded = forVanityPath && vph.doAddVanity(resource);
+ boolean aliasAdded = forAlias && ah.doAddAlias(resource);
return vanityPathAdded || aliasAdded;
} else {
return false;
@@ -186,22 +192,23 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
}
}
- private boolean updateResource(final String path, final AtomicBoolean resolverRefreshed) {
+ private boolean updateResource(
+ String path, boolean forAlias, boolean forVanityPath, AtomicBoolean resolverRefreshed) {
this.initializing.lock();
try {
this.refreshResolverIfNecessary(resolverRefreshed);
- final Resource resource = this.resolver != null ? resolver.getResource(path) : null;
+ Resource resource = this.resolver != null ? resolver.getResource(path) : null;
- final boolean isValidVanityPath = vph.isValidVanityPath(path);
+ boolean isValidVanityPath = vph.isValidVanityPath(path);
if (resource != null) {
boolean vanityPathChanged = false;
- if (isValidVanityPath) {
+ if (forVanityPath && isValidVanityPath) {
// we remove the old vanity path first
vanityPathChanged |= vph.doRemoveVanity(path);
@@ -214,7 +221,7 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
vanityPathChanged |= vph.doAddVanity(contentRsrc != null ? contentRsrc : resource);
}
- boolean aliasChanged = ah.doUpdateAlias(resource);
+ boolean aliasChanged = forAlias && ah.doUpdateAlias(resource);
return vanityPathChanged || aliasChanged;
}
} finally {
@@ -224,24 +231,32 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
return false;
}
- private boolean removeResource(final String path, final AtomicBoolean resolverRefreshed) {
- final String actualContentPath = getActualContentPath(path);
- final String actualContentPathPrefix = actualContentPath + "/";
+ private boolean removeResource(
+ String path, boolean forAlias, boolean forVanityPath, AtomicBoolean resolverRefreshed) {
boolean vanityPathChanged = false;
boolean aliasChanged = false;
- for (final String target : vph.getVanityPathMappings().keySet()) {
- if (target.startsWith(actualContentPathPrefix) || target.equals(actualContentPath)) {
- vanityPathChanged |= vph.removeVanityPath(target);
+ if (forVanityPath) {
+ String actualContentPath = getActualContentPath(path);
+ String actualContentPathPrefix = actualContentPath + "/";
+
+ for (String target : vph.getVanityPathMappings().keySet()) {
+ if (target.startsWith(actualContentPathPrefix) || target.equals(actualContentPath)) {
+ vanityPathChanged |= vph.removeVanityPath(target);
+ }
}
}
- final String pathPrefix = path + "/";
- for (final String contentPath : ah.aliasMapsMap.keySet()) {
- if (path.startsWith(contentPath + "/") || path.equals(contentPath) || contentPath.startsWith(pathPrefix)) {
- aliasChanged |= ah.removeAlias(
- resolver, contentPath, path, () -> this.refreshResolverIfNecessary(resolverRefreshed));
+ if (forAlias) {
+ String pathPrefix = path + "/";
+ for (String contentPath : ah.aliasMapsMap.keySet()) {
+ if (path.startsWith(contentPath + "/")
+ || path.equals(contentPath)
+ || contentPath.startsWith(pathPrefix)) {
+ aliasChanged |= ah.removeAlias(
+ resolver, contentPath, path, () -> this.refreshResolverIfNecessary(resolverRefreshed));
+ }
}
}
@@ -426,8 +441,11 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
// ---------- ResourceChangeListener interface
+ private final Set<ResourceChange.ChangeType> RELEVANT_CHANGE_TYPES = Set.of(
+ ResourceChange.ChangeType.ADDED, ResourceChange.ChangeType.CHANGED, ResourceChange.ChangeType.REMOVED);
+
/**
- * Handles the change to any of the node properties relevant for vanity URL
+ * Handles the change to any of the node properties relevant for vanity paths or aliases
* mappings. The {@link #MapEntries(MapConfigurationProvider, BundleContext, EventAdmin, StringInterpolationProvider, Optional)}
* constructor makes sure the event listener is registered to only get
* appropriate events.
@@ -435,7 +453,8 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
@Override
public void onChange(final List<ResourceChange> changes) {
- final boolean inStartup = !vph.isReady();
+ final boolean ahInStartup = !ah.isReady();
+ final boolean vphInStartup = !vph.isReady();
final AtomicBoolean resolverRefreshed = new AtomicBoolean(false);
@@ -450,7 +469,7 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
final ResourceChange.ChangeType type = rc.getType();
final String path = rc.getPath();
- log.debug("onChange, type={}, path={}", rc.getType(), path);
+ log.debug("onChange, type={}, path={}", type, path);
// don't care for system area
if (path.startsWith(JCR_SYSTEM_PREFIX)) {
@@ -458,20 +477,14 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
}
// during startup: just enqueue the events
- if (inStartup) {
- if (type == ResourceChange.ChangeType.REMOVED
- || type == ResourceChange.ChangeType.ADDED
- || type == ResourceChange.ChangeType.CHANGED) {
+ if (vphInStartup) {
+ if (RELEVANT_CHANGE_TYPES.contains(type)) {
Map.Entry<String, ResourceChange.ChangeType> entry = new SimpleEntry<>(path, type);
- log.trace("enqueue: {}", entry);
- resourceChangeQueue.add(entry);
+ log.trace("enqueued for vanity paths {}", entry);
+ resourceChangeQueueForVanityPaths.add(entry);
}
} else {
- boolean changed = handleResourceChange(type, path, resolverRefreshed, hasReloadedConfig);
-
- if (changed) {
- sendEvent = true;
- }
+ sendEvent |= handleResourceChange(type, path, true, true, resolverRefreshed, hasReloadedConfig);
}
}
@@ -483,6 +496,8 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
private boolean handleResourceChange(
ResourceChange.ChangeType type,
String path,
+ boolean forAlias,
+ boolean forVanityPath,
AtomicBoolean resolverRefreshed,
AtomicBoolean hasReloadedConfig) {
boolean changed = false;
@@ -494,7 +509,7 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
if (result) {
changed = true;
} else {
- changed |= removeResource(path, resolverRefreshed);
+ changed |= removeResource(path, forAlias, forVanityPath, resolverRefreshed);
}
}
// session.move() is handled differently see also SLING-3713 and
@@ -504,7 +519,7 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
if (result) {
changed = true;
} else {
- changed |= addResource(path, resolverRefreshed);
+ changed |= addResource(path, forAlias, forVanityPath, resolverRefreshed);
}
}
} else if (type == ResourceChange.ChangeType.CHANGED) {
@@ -513,7 +528,7 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
if (result) {
changed = true;
} else {
- changed |= updateResource(path, resolverRefreshed);
+ changed |= updateResource(path, forAlias, forVanityPath, resolverRefreshed);
}
}
}
@@ -717,7 +732,7 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
}
}
- private void drainQueue() {
+ private void drainVanityPathQueue() {
final AtomicBoolean resolverRefreshed = new AtomicBoolean(false);
// send the change event only once
@@ -726,13 +741,13 @@ public class MapEntries implements MapEntriesHandler, ResourceChangeListener, Ex
// the config needs to be reloaded only once
final AtomicBoolean hasReloadedConfig = new AtomicBoolean(false);
- while (!resourceChangeQueue.isEmpty()) {
- Map.Entry<String, ResourceChange.ChangeType> entry = resourceChangeQueue.remove(0);
+ while (!resourceChangeQueueForVanityPaths.isEmpty()) {
+ Map.Entry<String, ResourceChange.ChangeType> entry = resourceChangeQueueForVanityPaths.remove(0);
final ResourceChange.ChangeType type = entry.getValue();
final String path = entry.getKey();
- log.trace("drain type={}, path={}", type, path);
- boolean changed = handleResourceChange(type, path, resolverRefreshed, hasReloadedConfig);
+ log.trace("drain vanity path queue - type={}, path={}", type, path);
+ boolean changed = handleResourceChange(type, path, false, true, resolverRefreshed, hasReloadedConfig);
if (changed) {
sendEvent = true;
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AliasMapEntriesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AliasMapEntriesTest.java
index b9ed9319..3090df85 100644
--- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AliasMapEntriesTest.java
+++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/AliasMapEntriesTest.java
@@ -178,16 +178,18 @@ public class AliasMapEntriesTest extends AbstractMappingMapEntriesTest {
private static void addResource(MapEntries mapEntries, String path, AtomicBoolean bool)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
- Method method = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class);
+ Method method = MapEntries.class.getDeclaredMethod(
+ "addResource", String.class, boolean.class, boolean.class, AtomicBoolean.class);
method.setAccessible(true);
- method.invoke(mapEntries, path, bool);
+ method.invoke(mapEntries, path, true, false, bool);
}
private static void removeResource(MapEntries mapEntries, String path, AtomicBoolean bool)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
- Method method = MapEntries.class.getDeclaredMethod("removeResource", String.class, AtomicBoolean.class);
+ Method method = MapEntries.class.getDeclaredMethod(
+ "removeResource", String.class, boolean.class, boolean.class, AtomicBoolean.class);
method.setAccessible(true);
- method.invoke(mapEntries, path, bool);
+ method.invoke(mapEntries, path, true, false, bool);
}
private static void removeAlias(
@@ -205,9 +207,10 @@ public class AliasMapEntriesTest extends AbstractMappingMapEntriesTest {
private static void updateResource(MapEntries mapEntries, String path, AtomicBoolean bool)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
- Method method = MapEntries.class.getDeclaredMethod("updateResource", String.class, AtomicBoolean.class);
+ Method method = MapEntries.class.getDeclaredMethod(
+ "updateResource", String.class, boolean.class, boolean.class, AtomicBoolean.class);
method.setAccessible(true);
- method.invoke(mapEntries, path, bool);
+ method.invoke(mapEntries, path, true, false, bool);
}
private void internal_test_simple_alias_support(boolean onJcrContent, boolean cached) {
@@ -1272,7 +1275,7 @@ public class AliasMapEntriesTest extends AbstractMappingMapEntriesTest {
Map<String, Collection<String>> aliasMapEntry = mapEntries.getAliasMap(top);
assertTrue(
"Alias Map for " + top.getPath()
- + " should be empty due to removal event during background init, bug got: " + aliasMapEntry,
+ + " should be empty due to removal event during background init, but got: " + aliasMapEntry,
aliasMapEntry.isEmpty());
}
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
index d5d37ed6..dbe7acf5 100644
--- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
+++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
@@ -135,10 +135,11 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest {
// tests SLING-6542
@Test
public void sessionConcurrency() throws Exception {
- final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class);
+ final Method addResource = MapEntries.class.getDeclaredMethod(
+ "addResource", String.class, boolean.class, boolean.class, AtomicBoolean.class);
addResource.setAccessible(true);
final Method updateResource =
- MapEntries.class.getDeclaredMethod("updateResource", String.class, AtomicBoolean.class);
+ MapEntries.class.getDeclaredMethod("updateResource", String.class, true, true, tomicBoolean.class);
updateResource.setAccessible(true);
final Method handleConfigurationUpdate = MapEntries.class.getDeclaredMethod(
"handleConfigurationUpdate", String.class, AtomicBoolean.class, AtomicBoolean.class, boolean.class);
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/VanityPathMapEntriesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/VanityPathMapEntriesTest.java
index fa03f4ce..102a41ee 100644
--- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/VanityPathMapEntriesTest.java
+++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/VanityPathMapEntriesTest.java
@@ -218,9 +218,10 @@ public class VanityPathMapEntriesTest extends AbstractMappingMapEntriesTest {
private static void addResource(MapEntries mapEntries, String path, AtomicBoolean bool)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
- Method method = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class);
+ Method method = MapEntries.class.getDeclaredMethod(
+ "addResource", String.class, boolean.class, boolean.class, AtomicBoolean.class);
method.setAccessible(true);
- method.invoke(mapEntries, path, bool);
+ method.invoke(mapEntries, path, false, true, bool);
}
private static void loadVanityPaths(MapEntries mapEntries, ResourceResolver resourceResolver)
@@ -742,8 +743,8 @@ public class VanityPathMapEntriesTest extends AbstractMappingMapEntriesTest {
Map<String, List<String>> vanityTargets = getVanityTargets(mapEntries);
assertEquals(0, vanityTargets.size());
- final Method updateResource =
- MapEntries.class.getDeclaredMethod("updateResource", String.class, AtomicBoolean.class);
+ final Method updateResource = MapEntries.class.getDeclaredMethod(
+ "updateResource", String.class, boolean.class, boolean.class, AtomicBoolean.class);
updateResource.setAccessible(true);
Resource justVanityPath = mock(Resource.class, "justVanityPath");
@@ -765,7 +766,7 @@ public class VanityPathMapEntriesTest extends AbstractMappingMapEntriesTest {
// update vanity path
when(justVanityPath.getValueMap())
.thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPathUpdated"));
- updateResource.invoke(mapEntries, "/justVanityPath", new AtomicBoolean());
+ updateResource.invoke(mapEntries, "/justVanityPath", false, true, new AtomicBoolean());
assertEquals(2, resolveMapsMap.size());
assertEquals(1, vanityTargets.size());
@@ -805,7 +806,7 @@ public class VanityPathMapEntriesTest extends AbstractMappingMapEntriesTest {
// update vanity path
when(vanityPathOnJcrContent.getValueMap())
.thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContentUpdated"));
- updateResource.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content", new AtomicBoolean());
+ updateResource.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content", false, true, new AtomicBoolean());
assertEquals(3, resolveMapsMap.size());
assertEquals(2, vanityTargets.size());
(sling-org-apache-sling-resourceresolver) 02/02: SLING-12894: alias refactoring - support observation events while bg init not finished - wip
Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
reschke pushed a commit to branch SLING-12894
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git
commit 2296b7a77dade1ddcaf6508f5cf6dc2cb876286b
Author: Julian Reschke <re...@apache.org>
AuthorDate: Thu Aug 21 09:10:54 2025 +0100
SLING-12894: alias refactoring - support observation events while bg init not finished - wip
---
.../sling/resourceresolver/impl/mapping/MapEntriesTest.java | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
index dbe7acf5..a9617bbb 100644
--- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
+++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java
@@ -125,10 +125,11 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest {
@Test
// SLING-4847
public void test_doNodeAdded1() throws Exception {
- final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class);
+ final Method addResource = MapEntries.class.getDeclaredMethod(
+ "addResource", String.class, boolean.class, boolean.class, AtomicBoolean.class);
addResource.setAccessible(true);
final AtomicBoolean refreshed = new AtomicBoolean(false);
- addResource.invoke(mapEntries, "/node", refreshed);
+ addResource.invoke(mapEntries, "/node", true, true, refreshed);
assertTrue(refreshed.get());
}
@@ -138,8 +139,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest {
final Method addResource = MapEntries.class.getDeclaredMethod(
"addResource", String.class, boolean.class, boolean.class, AtomicBoolean.class);
addResource.setAccessible(true);
- final Method updateResource =
- MapEntries.class.getDeclaredMethod("updateResource", String.class, true, true, tomicBoolean.class);
+ final Method updateResource = MapEntries.class.getDeclaredMethod(
+ "updateResource", String.class, boolean.class, boolean.class, AtomicBoolean.class);
updateResource.setAccessible(true);
final Method handleConfigurationUpdate = MapEntries.class.getDeclaredMethod(
"handleConfigurationUpdate", String.class, AtomicBoolean.class, AtomicBoolean.class, boolean.class);
@@ -175,8 +176,8 @@ public class MapEntriesTest extends AbstractMappingMapEntriesTest {
try {
Thread.sleep(randomWait);
for (int i1 = 0; i1 < 3; i1++) {
- addResource.invoke(mapEntries, "/node", new AtomicBoolean());
- updateResource.invoke(mapEntries, "/node", new AtomicBoolean());
+ addResource.invoke(mapEntries, "/node", true, true, new AtomicBoolean());
+ updateResource.invoke(mapEntries, "/node", true, true, new AtomicBoolean());
handleConfigurationUpdate.invoke(
mapEntries, "/node", new AtomicBoolean(), new AtomicBoolean(), false);
}