This is an automated email from the ASF dual-hosted git repository.

snazy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git


The following commit(s) were added to refs/heads/main by this push:
     new 253321c74 Add ResolutionManifestFactory (#2210)
253321c74 is described below

commit 253321c74a308781298a13d4617e490903799162
Author: Christopher Lambert <xn...@gmx.de>
AuthorDate: Mon Aug 4 09:25:09 2025 +0200

    Add ResolutionManifestFactory (#2210)
    
    after 95358a99221778b85905e5ea51afe90474378ce7 very little functionality
    was left in `PolarisEntityManager`.
    
    by splitting out the more dedicated `ResolutionManifestFactory` we can 
remove
    `PolarisEntityManager` and `RealmEntityManagerFactory` completely it seems.
---
 .../core/persistence/PolarisEntityManager.java     | 112 ---------------------
 .../resolver/PolarisResolutionManifest.java        |  21 ++--
 .../resolver/ResolutionManifestFactory.java        |  34 +++++++
 .../resolver/ResolutionManifestFactoryImpl.java    |  44 ++++++++
 .../service/quarkus/config/QuarkusProducers.java   |  17 ++--
 .../quarkus/admin/ManagementServiceTest.java       |   2 +-
 .../admin/PolarisAdminServiceAuthzTest.java        |   2 +-
 .../quarkus/admin/PolarisAuthzTestBase.java        |  11 +-
 .../catalog/AbstractIcebergCatalogTest.java        |  11 +-
 .../catalog/AbstractIcebergCatalogViewTest.java    |  10 +-
 .../AbstractPolarisGenericTableCatalogTest.java    |  10 +-
 .../quarkus/catalog/AbstractPolicyCatalogTest.java |  10 +-
 .../catalog/IcebergCatalogHandlerAuthzTest.java    |   6 +-
 ...PolarisGenericTableCatalogHandlerAuthzTest.java |   2 +-
 .../catalog/PolicyCatalogHandlerAuthzTest.java     |   2 +-
 .../polaris/service/admin/PolarisAdminService.java |  37 ++++---
 .../polaris/service/admin/PolarisServiceImpl.java  |  13 +--
 .../service/catalog/common/CatalogHandler.java     |  26 +++--
 .../generic/GenericTableCatalogAdapter.java        |  10 +-
 .../generic/GenericTableCatalogHandler.java        |   6 +-
 .../catalog/iceberg/IcebergCatalogAdapter.java     |  10 +-
 .../catalog/iceberg/IcebergCatalogHandler.java     |   6 +-
 .../catalog/policy/PolicyCatalogAdapter.java       |  10 +-
 .../catalog/policy/PolicyCatalogHandler.java       |  15 +--
 .../service/config/RealmEntityManagerFactory.java  |  64 ------------
 .../service/admin/PolarisAdminServiceTest.java     |  16 +--
 .../service/admin/PolarisServiceImplTest.java      |   8 +-
 .../service/catalog/io/FileIOFactoryTest.java      |   2 +-
 .../org/apache/polaris/service/TestServices.java   |  18 ++--
 .../catalog/PolarisPassthroughResolutionView.java  |  23 +++--
 30 files changed, 229 insertions(+), 329 deletions(-)

diff --git 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolarisEntityManager.java
 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolarisEntityManager.java
deleted file mode 100644
index c2e347a19..000000000
--- 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/PolarisEntityManager.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.core.persistence;
-
-import jakarta.annotation.Nonnull;
-import jakarta.annotation.Nullable;
-import jakarta.ws.rs.core.SecurityContext;
-import java.util.List;
-import org.apache.polaris.core.context.CallContext;
-import org.apache.polaris.core.entity.PolarisEntity;
-import org.apache.polaris.core.entity.PolarisEntityConstants;
-import org.apache.polaris.core.entity.PolarisEntityType;
-import org.apache.polaris.core.entity.PolarisGrantRecord;
-import org.apache.polaris.core.entity.PolarisPrivilege;
-import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest;
-import org.apache.polaris.core.persistence.resolver.ResolverFactory;
-
-/**
- * Wraps logic of handling name-caching and entity-caching against a concrete 
underlying entity
- * store while exposing methods more natural for the Catalog layer to use. 
Encapsulates the various
- * id and name resolution mechanics around PolarisEntities.
- */
-public class PolarisEntityManager {
-  private final PolarisMetaStoreManager metaStoreManager;
-  private final ResolverFactory resolverFactory;
-
-  // Lazily instantiated only a single time per entity manager.
-  private ResolvedPolarisEntity implicitResolvedRootContainerEntity = null;
-
-  /**
-   * @param metaStoreManager the metastore manager for the current realm
-   * @param resolverFactory the resolver factory to use
-   */
-  public PolarisEntityManager(
-      @Nonnull PolarisMetaStoreManager metaStoreManager, @Nonnull 
ResolverFactory resolverFactory) {
-    this.metaStoreManager = metaStoreManager;
-    this.resolverFactory = resolverFactory;
-  }
-
-  public PolarisResolutionManifest prepareResolutionManifest(
-      @Nonnull CallContext callContext,
-      @Nonnull SecurityContext securityContext,
-      @Nullable String referenceCatalogName) {
-    PolarisResolutionManifest manifest =
-        new PolarisResolutionManifest(
-            callContext, resolverFactory, securityContext, 
referenceCatalogName);
-    manifest.setSimulatedResolvedRootContainerEntity(
-        getSimulatedResolvedRootContainerEntity(callContext));
-    return manifest;
-  }
-
-  /**
-   * Returns a ResolvedPolarisEntity representing the realm-level "root" 
entity that is the implicit
-   * parent container of all things in this realm.
-   */
-  private synchronized ResolvedPolarisEntity 
getSimulatedResolvedRootContainerEntity(
-      CallContext callContext) {
-    if (implicitResolvedRootContainerEntity == null) {
-      // For now, the root container is only implicit and doesn't exist in the 
entity store, and
-      // only
-      // the service_admin PrincipalRole has the SERVICE_MANAGE_ACCESS grant 
on this entity. If it
-      // becomes
-      // possible to grant other PrincipalRoles with SERVICE_MANAGE_ACCESS or 
other privileges on
-      // this
-      // root entity, then we must actually create a representation of this 
root entity in the
-      // entity store itself.
-      PolarisEntity serviceAdminPrincipalRole =
-          metaStoreManager
-              .findPrincipalRoleByName(
-                  callContext.getPolarisCallContext(),
-                  PolarisEntityConstants.getNameOfPrincipalServiceAdminRole())
-              .orElse(null);
-      if (serviceAdminPrincipalRole == null) {
-        throw new IllegalStateException("Failed to resolve service_admin 
PrincipalRole");
-      }
-      PolarisEntity rootContainerEntity =
-          new PolarisEntity.Builder()
-              .setId(0L)
-              .setCatalogId(0L)
-              .setType(PolarisEntityType.ROOT)
-              .setName("root")
-              .build();
-      PolarisGrantRecord serviceAdminGrant =
-          new PolarisGrantRecord(
-              0L,
-              0L,
-              serviceAdminPrincipalRole.getCatalogId(),
-              serviceAdminPrincipalRole.getId(),
-              PolarisPrivilege.SERVICE_MANAGE_ACCESS.getCode());
-
-      implicitResolvedRootContainerEntity =
-          new ResolvedPolarisEntity(rootContainerEntity, null, 
List.of(serviceAdminGrant));
-    }
-    return implicitResolvedRootContainerEntity;
-  }
-}
diff --git 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
index f8e18341a..e5c149c82 100644
--- 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
+++ 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
@@ -20,6 +20,7 @@ package org.apache.polaris.core.persistence.resolver;
 
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
+import jakarta.annotation.Nullable;
 import jakarta.ws.rs.core.SecurityContext;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -63,13 +64,6 @@ public class PolarisResolutionManifest implements 
PolarisResolutionManifestCatal
 
   private final Map<Object, ResolverPath> passthroughPaths = new HashMap<>();
 
-  // For applicable operations, this represents the topmost root entity which 
services as an
-  // authorization parent for all other entities that reside at the root 
level, such as
-  // Catalog, Principal, and PrincipalRole.
-  // This simulated entity will be used if the actual resolver fails to 
resolve the rootContainer
-  // on the backend due to compatibility mismatches.
-  private ResolvedPolarisEntity simulatedResolvedRootContainerEntity = null;
-
   private int currentPathIndex = 0;
 
   // Set when resolveAll is called
@@ -268,12 +262,7 @@ public class PolarisResolutionManifest implements 
PolarisResolutionManifestCatal
     return activatedEntities;
   }
 
-  public void setSimulatedResolvedRootContainerEntity(
-      ResolvedPolarisEntity simulatedResolvedRootContainerEntity) {
-    this.simulatedResolvedRootContainerEntity = 
simulatedResolvedRootContainerEntity;
-  }
-
-  private ResolvedPolarisEntity getResolvedRootContainerEntity() {
+  private @Nullable ResolvedPolarisEntity getResolvedRootContainerEntity() {
     if (primaryResolverStatus.getStatus() != 
ResolverStatus.StatusEnum.SUCCESS) {
       return null;
     }
@@ -281,8 +270,10 @@ public class PolarisResolutionManifest implements 
PolarisResolutionManifestCatal
         primaryResolver.getResolvedEntity(
             PolarisEntityType.ROOT, 
PolarisEntityConstants.getRootContainerName());
     if (resolvedEntity == null) {
-      LOGGER.debug("Failed to find rootContainer, so using simulated 
rootContainer instead.");
-      return simulatedResolvedRootContainerEntity;
+      LOGGER.warn(
+          "Failed to find rootContainer for realm: {} and catalog: {}",
+          callContext.getRealmContext().getRealmIdentifier(),
+          catalogName);
     }
     return resolvedEntity;
   }
diff --git 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactory.java
 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactory.java
new file mode 100644
index 000000000..c67d08cbe
--- /dev/null
+++ 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.core.persistence.resolver;
+
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import jakarta.ws.rs.core.SecurityContext;
+import org.apache.polaris.core.context.CallContext;
+
+public interface ResolutionManifestFactory {
+
+  @Nonnull
+  PolarisResolutionManifest createResolutionManifest(
+      @Nonnull CallContext callContext,
+      @Nonnull SecurityContext securityContext,
+      @Nullable String referenceCatalogName);
+}
diff --git 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactoryImpl.java
 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactoryImpl.java
new file mode 100644
index 000000000..dc148a723
--- /dev/null
+++ 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/ResolutionManifestFactoryImpl.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.polaris.core.persistence.resolver;
+
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import jakarta.ws.rs.core.SecurityContext;
+import org.apache.polaris.core.context.CallContext;
+
+public class ResolutionManifestFactoryImpl implements 
ResolutionManifestFactory {
+
+  private final ResolverFactory resolverFactory;
+
+  public ResolutionManifestFactoryImpl(@Nonnull ResolverFactory 
resolverFactory) {
+    this.resolverFactory = resolverFactory;
+  }
+
+  @Nonnull
+  @Override
+  public PolarisResolutionManifest createResolutionManifest(
+      @Nonnull CallContext callContext,
+      @Nonnull SecurityContext securityContext,
+      @Nullable String referenceCatalogName) {
+    return new PolarisResolutionManifest(
+        callContext, resolverFactory, securityContext, referenceCatalogName);
+  }
+}
diff --git 
a/runtime/service/src/main/java/org/apache/polaris/service/quarkus/config/QuarkusProducers.java
 
b/runtime/service/src/main/java/org/apache/polaris/service/quarkus/config/QuarkusProducers.java
index 8b75bfc89..c08126a31 100644
--- 
a/runtime/service/src/main/java/org/apache/polaris/service/quarkus/config/QuarkusProducers.java
+++ 
b/runtime/service/src/main/java/org/apache/polaris/service/quarkus/config/QuarkusProducers.java
@@ -46,10 +46,11 @@ import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.context.RealmContext;
 import org.apache.polaris.core.persistence.BasePersistence;
 import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.bootstrap.RootCredentialsSet;
 import org.apache.polaris.core.persistence.cache.EntityCache;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
+import 
org.apache.polaris.core.persistence.resolver.ResolutionManifestFactoryImpl;
 import org.apache.polaris.core.persistence.resolver.Resolver;
 import org.apache.polaris.core.persistence.resolver.ResolverFactory;
 import org.apache.polaris.core.secrets.UserSecretsManager;
@@ -64,7 +65,6 @@ import org.apache.polaris.service.auth.TokenBroker;
 import org.apache.polaris.service.auth.TokenBrokerFactory;
 import org.apache.polaris.service.catalog.api.IcebergRestOAuth2ApiService;
 import org.apache.polaris.service.catalog.io.FileIOFactory;
-import org.apache.polaris.service.config.RealmEntityManagerFactory;
 import org.apache.polaris.service.context.RealmContextConfiguration;
 import org.apache.polaris.service.context.RealmContextResolver;
 import org.apache.polaris.service.events.PolarisEventListener;
@@ -127,6 +127,12 @@ public class QuarkusProducers {
     };
   }
 
+  @Produces
+  @ApplicationScoped
+  public ResolutionManifestFactory resolutionManifestFactory(ResolverFactory 
resolverFactory) {
+    return new ResolutionManifestFactoryImpl(resolverFactory);
+  }
+
   @Produces
   @ApplicationScoped
   public PolarisAuthorizer polarisAuthorizer() {
@@ -386,13 +392,6 @@ public class QuarkusProducers {
     return metaStoreManagerFactory.getOrCreateSession(realmContext);
   }
 
-  @Produces
-  @RequestScoped
-  public PolarisEntityManager polarisEntityManager(
-      RealmContext realmContext, RealmEntityManagerFactory factory) {
-    return factory.getOrCreateEntityManager(realmContext);
-  }
-
   @Produces
   @RequestScoped
   public QuarkusAuthenticationRealmConfiguration realmAuthConfig(
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/ManagementServiceTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/ManagementServiceTest.java
index 4446652b0..cdda50f45 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/ManagementServiceTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/ManagementServiceTest.java
@@ -186,7 +186,7 @@ public class ManagementServiceTest {
       PolarisMetaStoreManager metaStoreManager, PolarisCallContext 
callContext) {
     return new PolarisAdminService(
         callContext,
-        
services.entityManagerFactory().getOrCreateEntityManager(callContext.getRealmContext()),
+        services.resolutionManifestFactory(),
         metaStoreManager,
         new UnsafeInMemorySecretsManager(),
         new SecurityContext() {
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAdminServiceAuthzTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAdminServiceAuthzTest.java
index d74447b53..473ba45a8 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAdminServiceAuthzTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAdminServiceAuthzTest.java
@@ -51,7 +51,7 @@ public class PolarisAdminServiceAuthzTest extends 
PolarisAuthzTestBase {
         new AuthenticatedPolarisPrincipal(principalEntity, 
activatedPrincipalRoles);
     return new PolarisAdminService(
         callContext,
-        entityManager,
+        resolutionManifestFactory,
         metaStoreManager,
         userSecretsManager,
         securityContext(authenticatedPrincipal, activatedPrincipalRoles),
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java
index f84471ca4..eed9d652f 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/admin/PolarisAuthzTestBase.java
@@ -66,10 +66,10 @@ import org.apache.polaris.core.entity.PolarisPrivilege;
 import org.apache.polaris.core.entity.PrincipalEntity;
 import org.apache.polaris.core.entity.PrincipalRoleEntity;
 import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.dao.entity.EntityResult;
 import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverFactory;
 import org.apache.polaris.core.policy.PredefinedPolicyTypes;
 import org.apache.polaris.core.secrets.UserSecretsManager;
@@ -82,7 +82,6 @@ import 
org.apache.polaris.service.catalog.iceberg.CatalogHandlerUtils;
 import org.apache.polaris.service.catalog.iceberg.IcebergCatalog;
 import org.apache.polaris.service.catalog.io.FileIOFactory;
 import org.apache.polaris.service.catalog.policy.PolicyCatalog;
-import org.apache.polaris.service.config.RealmEntityManagerFactory;
 import org.apache.polaris.service.config.ReservedProperties;
 import org.apache.polaris.service.context.catalog.CallContextCatalogFactory;
 import 
org.apache.polaris.service.context.catalog.PolarisCallContextCatalogFactory;
@@ -182,7 +181,7 @@ public abstract class PolarisAuthzTestBase {
   protected final ReservedProperties reservedProperties = 
ReservedProperties.NONE;
 
   @Inject protected MetaStoreManagerFactory managerFactory;
-  @Inject protected RealmEntityManagerFactory realmEntityManagerFactory;
+  @Inject protected ResolutionManifestFactory resolutionManifestFactory;
   @Inject protected CallContextCatalogFactory callContextCatalogFactory;
   @Inject protected UserSecretsManagerFactory userSecretsManagerFactory;
   @Inject protected PolarisDiagnostics diagServices;
@@ -198,7 +197,6 @@ public abstract class PolarisAuthzTestBase {
   protected PolarisGenericTableCatalog genericTableCatalog;
   protected PolicyCatalog policyCatalog;
   protected PolarisAdminService adminService;
-  protected PolarisEntityManager entityManager;
   protected PolarisMetaStoreManager metaStoreManager;
   protected UserSecretsManager userSecretsManager;
   protected PolarisBaseEntity catalogEntity;
@@ -238,7 +236,6 @@ public abstract class PolarisAuthzTestBase {
             diagServices,
             configurationStore,
             clock);
-    this.entityManager = 
realmEntityManagerFactory.getOrCreateEntityManager(realmContext);
 
     callContext = polarisContext;
 
@@ -249,7 +246,7 @@ public abstract class PolarisAuthzTestBase {
     this.adminService =
         new PolarisAdminService(
             callContext,
-            entityManager,
+            resolutionManifestFactory,
             metaStoreManager,
             userSecretsManager,
             securityContext(authenticatedRoot, Set.of()),
@@ -438,7 +435,7 @@ public abstract class PolarisAuthzTestBase {
     
Mockito.when(securityContext.isUserInRole(Mockito.anyString())).thenReturn(true);
     PolarisPassthroughResolutionView passthroughView =
         new PolarisPassthroughResolutionView(
-            callContext, entityManager, securityContext, CATALOG_NAME);
+            callContext, resolutionManifestFactory, securityContext, 
CATALOG_NAME);
     this.baseCatalog =
         new IcebergCatalog(
             storageCredentialCache,
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractIcebergCatalogTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractIcebergCatalogTest.java
index 05460d12e..6abe889ef 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractIcebergCatalogTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractIcebergCatalogTest.java
@@ -107,7 +107,6 @@ import org.apache.polaris.core.entity.PrincipalEntity;
 import org.apache.polaris.core.entity.TaskEntity;
 import org.apache.polaris.core.exceptions.CommitConflictException;
 import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
 import org.apache.polaris.core.persistence.cache.EntityCache;
@@ -115,6 +114,8 @@ import 
org.apache.polaris.core.persistence.dao.entity.BaseResult;
 import org.apache.polaris.core.persistence.dao.entity.EntityResult;
 import org.apache.polaris.core.persistence.pagination.Page;
 import org.apache.polaris.core.persistence.pagination.PageToken;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
+import 
org.apache.polaris.core.persistence.resolver.ResolutionManifestFactoryImpl;
 import org.apache.polaris.core.persistence.resolver.Resolver;
 import org.apache.polaris.core.persistence.resolver.ResolverFactory;
 import org.apache.polaris.core.secrets.UserSecretsManager;
@@ -237,7 +238,7 @@ public abstract class AbstractIcebergCatalogTest extends 
CatalogTests<IcebergCat
   private PolarisCallContext polarisContext;
   private PolarisAdminService adminService;
   private ResolverFactory resolverFactory;
-  private PolarisEntityManager entityManager;
+  private ResolutionManifestFactory resolutionManifestFactory;
   private FileIOFactory fileIOFactory;
   private InMemoryFileIO fileIO;
   private PolarisEntity catalogEntity;
@@ -292,7 +293,7 @@ public abstract class AbstractIcebergCatalogTest extends 
CatalogTests<IcebergCat
                 referenceCatalogName);
     QuarkusMock.installMockForType(resolverFactory, ResolverFactory.class);
 
-    entityManager = new PolarisEntityManager(metaStoreManager, 
resolverFactory);
+    resolutionManifestFactory = new 
ResolutionManifestFactoryImpl(resolverFactory);
 
     PrincipalEntity rootPrincipal =
         metaStoreManager.findRootPrincipal(polarisContext).orElseThrow();
@@ -308,7 +309,7 @@ public abstract class AbstractIcebergCatalogTest extends 
CatalogTests<IcebergCat
     adminService =
         new PolarisAdminService(
             polarisContext,
-            entityManager,
+            resolutionManifestFactory,
             metaStoreManager,
             userSecretsManager,
             securityContext,
@@ -431,7 +432,7 @@ public abstract class AbstractIcebergCatalogTest extends 
CatalogTests<IcebergCat
       String catalogName, PolarisMetaStoreManager metaStoreManager, 
FileIOFactory fileIOFactory) {
     PolarisPassthroughResolutionView passthroughView =
         new PolarisPassthroughResolutionView(
-            polarisContext, entityManager, securityContext, catalogName);
+            polarisContext, resolutionManifestFactory, securityContext, 
catalogName);
     TaskExecutor taskExecutor = Mockito.mock(TaskExecutor.class);
     return new IcebergCatalog(
         storageCredentialCache,
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractIcebergCatalogViewTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractIcebergCatalogViewTest.java
index 55ada4088..95c23617f 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractIcebergCatalogViewTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractIcebergCatalogViewTest.java
@@ -49,8 +49,8 @@ import org.apache.polaris.core.context.RealmContext;
 import org.apache.polaris.core.entity.CatalogEntity;
 import org.apache.polaris.core.entity.PrincipalEntity;
 import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverFactory;
 import org.apache.polaris.core.secrets.UserSecretsManager;
 import org.apache.polaris.core.secrets.UserSecretsManagerFactory;
@@ -114,6 +114,7 @@ public abstract class AbstractIcebergCatalogViewTest 
extends ViewCatalogTests<Ic
   @Inject PolarisDiagnostics diagServices;
   @Inject PolarisEventListener polarisEventListener;
   @Inject ResolverFactory resolverFactory;
+  @Inject ResolutionManifestFactory resolutionManifestFactory;
 
   private IcebergCatalog catalog;
 
@@ -163,9 +164,6 @@ public abstract class AbstractIcebergCatalogViewTest 
extends ViewCatalogTests<Ic
             configurationStore,
             Clock.systemDefaultZone());
 
-    PolarisEntityManager entityManager =
-        new PolarisEntityManager(metaStoreManager, resolverFactory);
-
     PrincipalEntity rootPrincipal =
         metaStoreManager.findRootPrincipal(polarisContext).orElseThrow();
     AuthenticatedPolarisPrincipal authenticatedRoot =
@@ -180,7 +178,7 @@ public abstract class AbstractIcebergCatalogViewTest 
extends ViewCatalogTests<Ic
     PolarisAdminService adminService =
         new PolarisAdminService(
             polarisContext,
-            entityManager,
+            resolutionManifestFactory,
             metaStoreManager,
             userSecretsManager,
             securityContext,
@@ -206,7 +204,7 @@ public abstract class AbstractIcebergCatalogViewTest 
extends ViewCatalogTests<Ic
 
     PolarisPassthroughResolutionView passthroughView =
         new PolarisPassthroughResolutionView(
-            polarisContext, entityManager, securityContext, CATALOG_NAME);
+            polarisContext, resolutionManifestFactory, securityContext, 
CATALOG_NAME);
     FileIOFactory fileIOFactory =
         new DefaultFileIOFactory(storageCredentialCache, 
metaStoreManagerFactory);
 
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractPolarisGenericTableCatalogTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractPolarisGenericTableCatalogTest.java
index 5b216ceac..c0fd2c9a7 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractPolarisGenericTableCatalogTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractPolarisGenericTableCatalogTest.java
@@ -52,8 +52,8 @@ import org.apache.polaris.core.entity.PolarisEntity;
 import org.apache.polaris.core.entity.PrincipalEntity;
 import org.apache.polaris.core.entity.table.GenericTableEntity;
 import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverFactory;
 import org.apache.polaris.core.secrets.UserSecretsManager;
 import org.apache.polaris.core.secrets.UserSecretsManagerFactory;
@@ -103,6 +103,7 @@ public abstract class 
AbstractPolarisGenericTableCatalogTest {
   @Inject PolarisStorageIntegrationProvider storageIntegrationProvider;
   @Inject PolarisDiagnostics diagServices;
   @Inject ResolverFactory resolverFactory;
+  @Inject ResolutionManifestFactory resolutionManifestFactory;
 
   private PolarisGenericTableCatalog genericTableCatalog;
   private IcebergCatalog icebergCatalog;
@@ -112,7 +113,6 @@ public abstract class 
AbstractPolarisGenericTableCatalogTest {
   private UserSecretsManager userSecretsManager;
   private PolarisCallContext polarisContext;
   private PolarisAdminService adminService;
-  private PolarisEntityManager entityManager;
   private FileIOFactory fileIOFactory;
   private AuthenticatedPolarisPrincipal authenticatedRoot;
   private PolarisEntity catalogEntity;
@@ -156,8 +156,6 @@ public abstract class 
AbstractPolarisGenericTableCatalogTest {
             configurationStore,
             Clock.systemDefaultZone());
 
-    entityManager = new PolarisEntityManager(metaStoreManager, 
resolverFactory);
-
     PrincipalEntity rootPrincipal =
         metaStoreManager.findRootPrincipal(polarisContext).orElseThrow();
     authenticatedRoot = new AuthenticatedPolarisPrincipal(rootPrincipal, 
Set.of());
@@ -171,7 +169,7 @@ public abstract class 
AbstractPolarisGenericTableCatalogTest {
     adminService =
         new PolarisAdminService(
             polarisContext,
-            entityManager,
+            resolutionManifestFactory,
             metaStoreManager,
             userSecretsManager,
             securityContext,
@@ -208,7 +206,7 @@ public abstract class 
AbstractPolarisGenericTableCatalogTest {
 
     PolarisPassthroughResolutionView passthroughView =
         new PolarisPassthroughResolutionView(
-            polarisContext, entityManager, securityContext, CATALOG_NAME);
+            polarisContext, resolutionManifestFactory, securityContext, 
CATALOG_NAME);
     TaskExecutor taskExecutor = Mockito.mock();
     this.fileIOFactory = new DefaultFileIOFactory(storageCredentialCache, 
metaStoreManagerFactory);
 
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractPolicyCatalogTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractPolicyCatalogTest.java
index 3853b4efd..1b3315bff 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractPolicyCatalogTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/AbstractPolicyCatalogTest.java
@@ -59,9 +59,9 @@ import org.apache.polaris.core.entity.CatalogEntity;
 import org.apache.polaris.core.entity.PolarisEntity;
 import org.apache.polaris.core.entity.PrincipalEntity;
 import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.PolicyMappingAlreadyExistsException;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverFactory;
 import org.apache.polaris.core.policy.PredefinedPolicyTypes;
 import org.apache.polaris.core.policy.exceptions.NoSuchPolicyException;
@@ -130,6 +130,7 @@ public abstract class AbstractPolicyCatalogTest {
   @Inject PolarisStorageIntegrationProvider storageIntegrationProvider;
   @Inject PolarisDiagnostics diagServices;
   @Inject ResolverFactory resolverFactory;
+  @Inject ResolutionManifestFactory resolutionManifestFactory;
 
   private PolicyCatalog policyCatalog;
   private IcebergCatalog icebergCatalog;
@@ -140,7 +141,6 @@ public abstract class AbstractPolicyCatalogTest {
   private UserSecretsManager userSecretsManager;
   private PolarisCallContext polarisContext;
   private PolarisAdminService adminService;
-  private PolarisEntityManager entityManager;
   private FileIOFactory fileIOFactory;
   private AuthenticatedPolarisPrincipal authenticatedRoot;
   private PolarisEntity catalogEntity;
@@ -179,8 +179,6 @@ public abstract class AbstractPolicyCatalogTest {
             configurationStore,
             Clock.systemDefaultZone());
 
-    entityManager = new PolarisEntityManager(metaStoreManager, 
resolverFactory);
-
     callContext = polarisContext;
 
     PrincipalEntity rootPrincipal =
@@ -196,7 +194,7 @@ public abstract class AbstractPolicyCatalogTest {
     adminService =
         new PolarisAdminService(
             callContext,
-            entityManager,
+            resolutionManifestFactory,
             metaStoreManager,
             userSecretsManager,
             securityContext,
@@ -231,7 +229,7 @@ public abstract class AbstractPolicyCatalogTest {
 
     PolarisPassthroughResolutionView passthroughView =
         new PolarisPassthroughResolutionView(
-            callContext, entityManager, securityContext, CATALOG_NAME);
+            callContext, resolutionManifestFactory, securityContext, 
CATALOG_NAME);
     TaskExecutor taskExecutor = Mockito.mock();
     this.fileIOFactory = new DefaultFileIOFactory(storageCredentialCache, 
metaStoreManagerFactory);
 
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogHandlerAuthzTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogHandlerAuthzTest.java
index 90c985f71..e3b3dc3f3 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogHandlerAuthzTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogHandlerAuthzTest.java
@@ -93,7 +93,7 @@ public class IcebergCatalogHandlerAuthzTest extends 
PolarisAuthzTestBase {
         new AuthenticatedPolarisPrincipal(principalEntity, 
activatedPrincipalRoles);
     return new IcebergCatalogHandler(
         callContext,
-        entityManager,
+        resolutionManifestFactory,
         metaStoreManager,
         userSecretsManager,
         securityContext(authenticatedPrincipal, activatedPrincipalRoles),
@@ -234,7 +234,7 @@ public class IcebergCatalogHandlerAuthzTest extends 
PolarisAuthzTestBase {
     IcebergCatalogHandler wrapper =
         new IcebergCatalogHandler(
             callContext,
-            entityManager,
+            resolutionManifestFactory,
             metaStoreManager,
             userSecretsManager,
             securityContext(authenticatedPrincipal, Set.of(PRINCIPAL_ROLE1, 
PRINCIPAL_ROLE2)),
@@ -269,7 +269,7 @@ public class IcebergCatalogHandlerAuthzTest extends 
PolarisAuthzTestBase {
     IcebergCatalogHandler refreshedWrapper =
         new IcebergCatalogHandler(
             callContext,
-            entityManager,
+            resolutionManifestFactory,
             metaStoreManager,
             userSecretsManager,
             securityContext(authenticatedPrincipal1, Set.of(PRINCIPAL_ROLE1, 
PRINCIPAL_ROLE2)),
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogHandlerAuthzTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogHandlerAuthzTest.java
index 446e5505b..8bd713291 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogHandlerAuthzTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolarisGenericTableCatalogHandlerAuthzTest.java
@@ -49,7 +49,7 @@ public class PolarisGenericTableCatalogHandlerAuthzTest 
extends PolarisAuthzTest
         new AuthenticatedPolarisPrincipal(principalEntity, 
activatedPrincipalRoles);
     return new GenericTableCatalogHandler(
         callContext,
-        entityManager,
+        resolutionManifestFactory,
         metaStoreManager,
         securityContext(authenticatedPrincipal, activatedPrincipalRoles),
         catalogName,
diff --git 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java
 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java
index 46b5bee7f..63203b95b 100644
--- 
a/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java
+++ 
b/runtime/service/src/test/java/org/apache/polaris/service/quarkus/catalog/PolicyCatalogHandlerAuthzTest.java
@@ -54,7 +54,7 @@ public class PolicyCatalogHandlerAuthzTest extends 
PolarisAuthzTestBase {
         new AuthenticatedPolarisPrincipal(principalEntity, 
activatedPrincipalRoles);
     return new PolicyCatalogHandler(
         callContext,
-        entityManager,
+        resolutionManifestFactory,
         metaStoreManager,
         securityContext(authenticatedPrincipal, activatedPrincipalRoles),
         catalogName,
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java
 
b/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java
index 59a05d614..816fc6798 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java
@@ -92,7 +92,6 @@ import org.apache.polaris.core.entity.PrincipalRoleEntity;
 import org.apache.polaris.core.entity.table.IcebergTableLikeEntity;
 import org.apache.polaris.core.entity.table.federated.FederatedEntities;
 import org.apache.polaris.core.exceptions.CommitConflictException;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
 import org.apache.polaris.core.persistence.dao.entity.CreateCatalogResult;
@@ -102,6 +101,7 @@ import 
org.apache.polaris.core.persistence.dao.entity.EntityResult;
 import org.apache.polaris.core.persistence.dao.entity.LoadGrantsResult;
 import org.apache.polaris.core.persistence.pagination.PageToken;
 import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverPath;
 import org.apache.polaris.core.persistence.resolver.ResolverStatus;
 import org.apache.polaris.core.policy.PolicyEntity;
@@ -132,7 +132,7 @@ public class PolarisAdminService {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(PolarisAdminService.class);
 
   private final CallContext callContext;
-  private final PolarisEntityManager entityManager;
+  private final ResolutionManifestFactory resolutionManifestFactory;
   private final SecurityContext securityContext;
   private final AuthenticatedPolarisPrincipal authenticatedPrincipal;
   private final PolarisAuthorizer authorizer;
@@ -145,14 +145,14 @@ public class PolarisAdminService {
 
   public PolarisAdminService(
       @NotNull CallContext callContext,
-      @NotNull PolarisEntityManager entityManager,
+      @NotNull ResolutionManifestFactory resolutionManifestFactory,
       @NotNull PolarisMetaStoreManager metaStoreManager,
       @NotNull UserSecretsManager userSecretsManager,
       @NotNull SecurityContext securityContext,
       @NotNull PolarisAuthorizer authorizer,
       @NotNull ReservedProperties reservedProperties) {
     this.callContext = callContext;
-    this.entityManager = entityManager;
+    this.resolutionManifestFactory = resolutionManifestFactory;
     this.metaStoreManager = metaStoreManager;
     this.securityContext = securityContext;
     PolarisDiagnostics diagServices = 
callContext.getPolarisCallContext().getDiagServices();
@@ -202,7 +202,7 @@ public class PolarisAdminService {
 
   private void authorizeBasicRootOperationOrThrow(PolarisAuthorizableOperation 
op) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(
+        resolutionManifestFactory.createResolutionManifest(
             callContext, securityContext, null /* referenceCatalogName */);
     resolutionManifest.resolveAll();
     PolarisResolvedPathWrapper rootContainerWrapper =
@@ -230,7 +230,8 @@ public class PolarisAdminService {
       PolarisEntityType entityType,
       @Nullable String referenceCatalogName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
referenceCatalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, referenceCatalogName);
     resolutionManifest.addTopLevelName(topLevelEntityName, entityType, false 
/* isOptional */);
     ResolverStatus status = resolutionManifest.resolveAll();
     if (status.getStatus() == 
ResolverStatus.StatusEnum.ENTITY_COULD_NOT_BE_RESOLVED) {
@@ -264,7 +265,8 @@ public class PolarisAdminService {
   private void authorizeBasicCatalogRoleOperationOrThrow(
       PolarisAuthorizableOperation op, String catalogName, String 
catalogRoleName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addPath(
         new ResolverPath(List.of(catalogRoleName), 
PolarisEntityType.CATALOG_ROLE),
         catalogRoleName);
@@ -285,7 +287,7 @@ public class PolarisAdminService {
   private void authorizeGrantOnRootContainerToPrincipalRoleOperationOrThrow(
       PolarisAuthorizableOperation op, String principalRoleName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
null);
+        resolutionManifestFactory.createResolutionManifest(callContext, 
securityContext, null);
     resolutionManifest.addTopLevelName(
         principalRoleName, PolarisEntityType.PRINCIPAL_ROLE, false /* 
isOptional */);
     ResolverStatus status = resolutionManifest.resolveAll();
@@ -319,7 +321,7 @@ public class PolarisAdminService {
       PolarisEntityType topLevelEntityType,
       String principalRoleName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
null);
+        resolutionManifestFactory.createResolutionManifest(callContext, 
securityContext, null);
     resolutionManifest.addTopLevelName(
         topLevelEntityName, topLevelEntityType, false /* isOptional */);
     resolutionManifest.addTopLevelName(
@@ -353,7 +355,7 @@ public class PolarisAdminService {
   private void authorizeGrantOnPrincipalRoleToPrincipalOperationOrThrow(
       PolarisAuthorizableOperation op, String principalRoleName, String 
principalName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
null);
+        resolutionManifestFactory.createResolutionManifest(callContext, 
securityContext, null);
     resolutionManifest.addTopLevelName(
         principalRoleName, PolarisEntityType.PRINCIPAL_ROLE, false /* 
isOptional */);
     resolutionManifest.addTopLevelName(
@@ -387,7 +389,8 @@ public class PolarisAdminService {
       String catalogRoleName,
       String principalRoleName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addPath(
         new ResolverPath(List.of(catalogRoleName), 
PolarisEntityType.CATALOG_ROLE),
         catalogRoleName);
@@ -423,7 +426,8 @@ public class PolarisAdminService {
   private void authorizeGrantOnCatalogOperationOrThrow(
       PolarisAuthorizableOperation op, String catalogName, String 
catalogRoleName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addTopLevelName(
         catalogName, PolarisEntityType.CATALOG, false /* isOptional */);
     resolutionManifest.addPath(
@@ -456,7 +460,8 @@ public class PolarisAdminService {
       Namespace namespace,
       String catalogRoleName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addPath(
         new ResolverPath(Arrays.asList(namespace.levels()), 
PolarisEntityType.NAMESPACE),
         namespace);
@@ -497,7 +502,8 @@ public class PolarisAdminService {
       TableIdentifier identifier,
       String catalogRoleName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addPath(
         new ResolverPath(
             PolarisCatalogHelpers.tableIdentifierToList(identifier), 
PolarisEntityType.TABLE_LIKE),
@@ -542,7 +548,8 @@ public class PolarisAdminService {
       PolicyIdentifier identifier,
       String catalogRoleName) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addPath(
         new ResolverPath(
             PolarisCatalogHelpers.identifierToList(identifier.getNamespace(), 
identifier.getName()),
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/admin/PolarisServiceImpl.java
 
b/service/common/src/main/java/org/apache/polaris/service/admin/PolarisServiceImpl.java
index 0f001d123..8670b1aeb 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/admin/PolarisServiceImpl.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/admin/PolarisServiceImpl.java
@@ -70,14 +70,13 @@ import org.apache.polaris.core.entity.PolarisPrivilege;
 import org.apache.polaris.core.entity.PrincipalEntity;
 import org.apache.polaris.core.entity.PrincipalRoleEntity;
 import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.secrets.UserSecretsManager;
 import org.apache.polaris.core.secrets.UserSecretsManagerFactory;
 import org.apache.polaris.service.admin.api.PolarisCatalogsApiService;
 import org.apache.polaris.service.admin.api.PolarisPrincipalRolesApiService;
 import org.apache.polaris.service.admin.api.PolarisPrincipalsApiService;
-import org.apache.polaris.service.config.RealmEntityManagerFactory;
 import org.apache.polaris.service.config.ReservedProperties;
 import org.apache.polaris.service.types.PolicyIdentifier;
 import org.slf4j.Logger;
@@ -90,7 +89,7 @@ public class PolarisServiceImpl
         PolarisPrincipalsApiService,
         PolarisPrincipalRolesApiService {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(PolarisServiceImpl.class);
-  private final RealmEntityManagerFactory entityManagerFactory;
+  private final ResolutionManifestFactory resolutionManifestFactory;
   private final PolarisAuthorizer polarisAuthorizer;
   private final MetaStoreManagerFactory metaStoreManagerFactory;
   private final UserSecretsManagerFactory userSecretsManagerFactory;
@@ -99,13 +98,13 @@ public class PolarisServiceImpl
 
   @Inject
   public PolarisServiceImpl(
-      RealmEntityManagerFactory entityManagerFactory,
+      ResolutionManifestFactory resolutionManifestFactory,
       MetaStoreManagerFactory metaStoreManagerFactory,
       UserSecretsManagerFactory userSecretsManagerFactory,
       PolarisAuthorizer polarisAuthorizer,
       CallContext callContext,
       ReservedProperties reservedProperties) {
-    this.entityManagerFactory = entityManagerFactory;
+    this.resolutionManifestFactory = resolutionManifestFactory;
     this.metaStoreManagerFactory = metaStoreManagerFactory;
     this.userSecretsManagerFactory = userSecretsManagerFactory;
     this.polarisAuthorizer = polarisAuthorizer;
@@ -121,15 +120,13 @@ public class PolarisServiceImpl
       throw new NotAuthorizedException("Failed to find authenticatedPrincipal 
in SecurityContext");
     }
 
-    PolarisEntityManager entityManager =
-        entityManagerFactory.getOrCreateEntityManager(realmContext);
     PolarisMetaStoreManager metaStoreManager =
         metaStoreManagerFactory.getOrCreateMetaStoreManager(realmContext);
     UserSecretsManager userSecretsManager =
         userSecretsManagerFactory.getOrCreateUserSecretsManager(realmContext);
     return new PolarisAdminService(
         callContext,
-        entityManager,
+        resolutionManifestFactory,
         metaStoreManager,
         userSecretsManager,
         securityContext,
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/catalog/common/CatalogHandler.java
 
b/service/common/src/main/java/org/apache/polaris/service/catalog/common/CatalogHandler.java
index bc1163bbd..523369c7c 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/catalog/common/CatalogHandler.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/catalog/common/CatalogHandler.java
@@ -38,9 +38,9 @@ import org.apache.polaris.core.catalog.PolarisCatalogHelpers;
 import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.entity.PolarisEntitySubType;
 import org.apache.polaris.core.entity.PolarisEntityType;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
 import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverPath;
 import org.apache.polaris.core.persistence.resolver.ResolverStatus;
 import org.apache.polaris.service.types.PolicyIdentifier;
@@ -55,7 +55,7 @@ public abstract class CatalogHandler {
   // Initialized in the authorize methods.
   protected PolarisResolutionManifest resolutionManifest = null;
 
-  protected final PolarisEntityManager entityManager;
+  protected final ResolutionManifestFactory resolutionManifestFactory;
   protected final String catalogName;
   protected final PolarisAuthorizer authorizer;
 
@@ -65,12 +65,12 @@ public abstract class CatalogHandler {
 
   public CatalogHandler(
       CallContext callContext,
-      PolarisEntityManager entityManager,
+      ResolutionManifestFactory resolutionManifestFactory,
       SecurityContext securityContext,
       String catalogName,
       PolarisAuthorizer authorizer) {
     this.callContext = callContext;
-    this.entityManager = entityManager;
+    this.resolutionManifestFactory = resolutionManifestFactory;
     this.catalogName = catalogName;
     PolarisDiagnostics diagServices = 
callContext.getPolarisCallContext().getDiagServices();
     diagServices.checkNotNull(securityContext, "null_security_context");
@@ -100,7 +100,8 @@ public abstract class CatalogHandler {
       List<TableIdentifier> extraPassthroughTableLikes,
       List<PolicyIdentifier> extraPassThroughPolicies) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addPath(
         new ResolverPath(Arrays.asList(namespace.levels()), 
PolarisEntityType.NAMESPACE),
         namespace);
@@ -154,7 +155,8 @@ public abstract class CatalogHandler {
   protected void authorizeCreateNamespaceUnderNamespaceOperationOrThrow(
       PolarisAuthorizableOperation op, Namespace namespace) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
 
     Namespace parentNamespace = 
PolarisCatalogHelpers.getParentNamespace(namespace);
     resolutionManifest.addPath(
@@ -190,7 +192,8 @@ public abstract class CatalogHandler {
     Namespace namespace = identifier.namespace();
 
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addPath(
         new ResolverPath(Arrays.asList(namespace.levels()), 
PolarisEntityType.NAMESPACE),
         namespace);
@@ -226,7 +229,8 @@ public abstract class CatalogHandler {
   protected void authorizeBasicTableLikeOperationOrThrow(
       PolarisAuthorizableOperation op, PolarisEntitySubType subType, 
TableIdentifier identifier) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
 
     // The underlying Catalog is also allowed to fetch "fresh" versions of the 
target entity.
     resolutionManifest.addPassthroughPath(
@@ -257,7 +261,8 @@ public abstract class CatalogHandler {
       final PolarisEntitySubType subType,
       List<TableIdentifier> ids) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     ids.forEach(
         identifier ->
             resolutionManifest.addPassthroughPath(
@@ -309,7 +314,8 @@ public abstract class CatalogHandler {
       TableIdentifier src,
       TableIdentifier dst) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     // Add src, dstParent, and dst(optional)
     resolutionManifest.addPath(
         new ResolverPath(
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogAdapter.java
 
b/service/common/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogAdapter.java
index c36cb1730..d1aa4fa8b 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogAdapter.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogAdapter.java
@@ -27,8 +27,8 @@ import org.apache.polaris.core.auth.PolarisAuthorizer;
 import org.apache.polaris.core.config.FeatureConfiguration;
 import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.context.RealmContext;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.service.catalog.CatalogPrefixParser;
 import 
org.apache.polaris.service.catalog.api.PolarisCatalogGenericTableApiService;
 import org.apache.polaris.service.catalog.common.CatalogAdapter;
@@ -47,7 +47,7 @@ public class GenericTableCatalogAdapter
 
   private final RealmContext realmContext;
   private final CallContext callContext;
-  private final PolarisEntityManager entityManager;
+  private final ResolutionManifestFactory resolutionManifestFactory;
   private final PolarisMetaStoreManager metaStoreManager;
   private final PolarisAuthorizer polarisAuthorizer;
   private final ReservedProperties reservedProperties;
@@ -57,14 +57,14 @@ public class GenericTableCatalogAdapter
   public GenericTableCatalogAdapter(
       RealmContext realmContext,
       CallContext callContext,
-      PolarisEntityManager entityManager,
+      ResolutionManifestFactory resolutionManifestFactory,
       PolarisMetaStoreManager metaStoreManager,
       PolarisAuthorizer polarisAuthorizer,
       CatalogPrefixParser prefixParser,
       ReservedProperties reservedProperties) {
     this.realmContext = realmContext;
     this.callContext = callContext;
-    this.entityManager = entityManager;
+    this.resolutionManifestFactory = resolutionManifestFactory;
     this.metaStoreManager = metaStoreManager;
     this.polarisAuthorizer = polarisAuthorizer;
     this.prefixParser = prefixParser;
@@ -79,7 +79,7 @@ public class GenericTableCatalogAdapter
 
     return new GenericTableCatalogHandler(
         callContext,
-        entityManager,
+        resolutionManifestFactory,
         metaStoreManager,
         securityContext,
         prefixParser.prefixToCatalogName(realmContext, prefix),
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java
 
b/service/common/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java
index 670cddbb0..cf5879fe6 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java
@@ -28,8 +28,8 @@ import org.apache.polaris.core.auth.PolarisAuthorizer;
 import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.entity.PolarisEntitySubType;
 import org.apache.polaris.core.entity.table.GenericTableEntity;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.service.catalog.common.CatalogHandler;
 import org.apache.polaris.service.types.GenericTable;
 import org.apache.polaris.service.types.ListGenericTablesResponse;
@@ -43,12 +43,12 @@ public class GenericTableCatalogHandler extends 
CatalogHandler {
 
   public GenericTableCatalogHandler(
       CallContext callContext,
-      PolarisEntityManager entityManager,
+      ResolutionManifestFactory resolutionManifestFactory,
       PolarisMetaStoreManager metaStoreManager,
       SecurityContext securityContext,
       String catalogName,
       PolarisAuthorizer authorizer) {
-    super(callContext, entityManager, securityContext, catalogName, 
authorizer);
+    super(callContext, resolutionManifestFactory, securityContext, 
catalogName, authorizer);
     this.metaStoreManager = metaStoreManager;
   }
 
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java
 
b/service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java
index 482e891c2..99aea64d9 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogAdapter.java
@@ -64,9 +64,9 @@ import org.apache.polaris.core.auth.PolarisAuthorizer;
 import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.context.RealmContext;
 import org.apache.polaris.core.entity.PolarisEntity;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.ResolvedPolarisEntity;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.Resolver;
 import org.apache.polaris.core.persistence.resolver.ResolverFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverStatus;
@@ -136,7 +136,7 @@ public class IcebergCatalogAdapter
   private final RealmContext realmContext;
   private final CallContext callContext;
   private final CallContextCatalogFactory catalogFactory;
-  private final PolarisEntityManager entityManager;
+  private final ResolutionManifestFactory resolutionManifestFactory;
   private final ResolverFactory resolverFactory;
   private final PolarisMetaStoreManager metaStoreManager;
   private final UserSecretsManager userSecretsManager;
@@ -150,8 +150,8 @@ public class IcebergCatalogAdapter
       RealmContext realmContext,
       CallContext callContext,
       CallContextCatalogFactory catalogFactory,
-      PolarisEntityManager entityManager,
       ResolverFactory resolverFactory,
+      ResolutionManifestFactory resolutionManifestFactory,
       PolarisMetaStoreManager metaStoreManager,
       UserSecretsManager userSecretsManager,
       PolarisAuthorizer polarisAuthorizer,
@@ -161,7 +161,7 @@ public class IcebergCatalogAdapter
     this.realmContext = realmContext;
     this.callContext = callContext;
     this.catalogFactory = catalogFactory;
-    this.entityManager = entityManager;
+    this.resolutionManifestFactory = resolutionManifestFactory;
     this.resolverFactory = resolverFactory;
     this.metaStoreManager = metaStoreManager;
     this.userSecretsManager = userSecretsManager;
@@ -197,7 +197,7 @@ public class IcebergCatalogAdapter
 
     return new IcebergCatalogHandler(
         callContext,
-        entityManager,
+        resolutionManifestFactory,
         metaStoreManager,
         userSecretsManager,
         securityContext,
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java
 
b/service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java
index ebcbd4bc7..90b019a65 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalogHandler.java
@@ -84,7 +84,6 @@ import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.entity.CatalogEntity;
 import org.apache.polaris.core.entity.PolarisEntitySubType;
 import org.apache.polaris.core.entity.table.IcebergTableLikeEntity;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
 import 
org.apache.polaris.core.persistence.TransactionWorkspaceMetaStoreManager;
@@ -92,6 +91,7 @@ import 
org.apache.polaris.core.persistence.dao.entity.EntitiesResult;
 import org.apache.polaris.core.persistence.dao.entity.EntityWithPath;
 import org.apache.polaris.core.persistence.pagination.Page;
 import org.apache.polaris.core.persistence.pagination.PageToken;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.secrets.UserSecretsManager;
 import org.apache.polaris.core.storage.AccessConfig;
 import org.apache.polaris.core.storage.PolarisStorageActions;
@@ -140,7 +140,7 @@ public class IcebergCatalogHandler extends CatalogHandler 
implements AutoCloseab
 
   public IcebergCatalogHandler(
       CallContext callContext,
-      PolarisEntityManager entityManager,
+      ResolutionManifestFactory resolutionManifestFactory,
       PolarisMetaStoreManager metaStoreManager,
       UserSecretsManager userSecretsManager,
       SecurityContext securityContext,
@@ -149,7 +149,7 @@ public class IcebergCatalogHandler extends CatalogHandler 
implements AutoCloseab
       PolarisAuthorizer authorizer,
       ReservedProperties reservedProperties,
       CatalogHandlerUtils catalogHandlerUtils) {
-    super(callContext, entityManager, securityContext, catalogName, 
authorizer);
+    super(callContext, resolutionManifestFactory, securityContext, 
catalogName, authorizer);
     this.metaStoreManager = metaStoreManager;
     this.userSecretsManager = userSecretsManager;
     this.catalogFactory = catalogFactory;
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogAdapter.java
 
b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogAdapter.java
index ef000add5..751e34af8 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogAdapter.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogAdapter.java
@@ -28,8 +28,8 @@ import org.apache.polaris.core.auth.PolarisAuthorizer;
 import org.apache.polaris.core.config.FeatureConfiguration;
 import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.context.RealmContext;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.policy.PolicyType;
 import org.apache.polaris.service.catalog.CatalogPrefixParser;
 import org.apache.polaris.service.catalog.api.PolarisCatalogPolicyApiService;
@@ -51,7 +51,7 @@ public class PolicyCatalogAdapter implements 
PolarisCatalogPolicyApiService, Cat
 
   private final RealmContext realmContext;
   private final CallContext callContext;
-  private final PolarisEntityManager entityManager;
+  private final ResolutionManifestFactory resolutionManifestFactory;
   private final PolarisMetaStoreManager metaStoreManager;
   private final PolarisAuthorizer polarisAuthorizer;
   private final CatalogPrefixParser prefixParser;
@@ -60,13 +60,13 @@ public class PolicyCatalogAdapter implements 
PolarisCatalogPolicyApiService, Cat
   public PolicyCatalogAdapter(
       RealmContext realmContext,
       CallContext callContext,
-      PolarisEntityManager entityManager,
+      ResolutionManifestFactory resolutionManifestFactory,
       PolarisMetaStoreManager metaStoreManager,
       PolarisAuthorizer polarisAuthorizer,
       CatalogPrefixParser prefixParser) {
     this.realmContext = realmContext;
     this.callContext = callContext;
-    this.entityManager = entityManager;
+    this.resolutionManifestFactory = resolutionManifestFactory;
     this.metaStoreManager = metaStoreManager;
     this.polarisAuthorizer = polarisAuthorizer;
     this.prefixParser = prefixParser;
@@ -79,7 +79,7 @@ public class PolicyCatalogAdapter implements 
PolarisCatalogPolicyApiService, Cat
 
     return new PolicyCatalogHandler(
         callContext,
-        entityManager,
+        resolutionManifestFactory,
         metaStoreManager,
         securityContext,
         prefixParser.prefixToCatalogName(realmContext, prefix),
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java
 
b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java
index 5a2cc7a53..c967f8971 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogHandler.java
@@ -35,9 +35,9 @@ import org.apache.polaris.core.catalog.PolarisCatalogHelpers;
 import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.entity.PolarisEntitySubType;
 import org.apache.polaris.core.entity.PolarisEntityType;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverPath;
 import org.apache.polaris.core.persistence.resolver.ResolverStatus;
 import org.apache.polaris.core.policy.PolicyType;
@@ -61,12 +61,12 @@ public class PolicyCatalogHandler extends CatalogHandler {
 
   public PolicyCatalogHandler(
       CallContext callContext,
-      PolarisEntityManager entityManager,
+      ResolutionManifestFactory resolutionManifestFactory,
       PolarisMetaStoreManager metaStoreManager,
       SecurityContext securityContext,
       String catalogName,
       PolarisAuthorizer authorizer) {
-    super(callContext, entityManager, securityContext, catalogName, 
authorizer);
+    super(callContext, resolutionManifestFactory, securityContext, 
catalogName, authorizer);
     this.metaStoreManager = metaStoreManager;
   }
 
@@ -151,7 +151,8 @@ public class PolicyCatalogHandler extends CatalogHandler {
   private void authorizeBasicPolicyOperationOrThrow(
       PolarisAuthorizableOperation op, PolicyIdentifier identifier) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addPassthroughPath(
         new ResolverPath(
             PolarisCatalogHelpers.identifierToList(identifier.getNamespace(), 
identifier.getName()),
@@ -201,7 +202,8 @@ public class PolicyCatalogHandler extends CatalogHandler {
 
   private void 
authorizeBasicCatalogOperationOrThrow(PolarisAuthorizableOperation op) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.resolveAll();
 
     PolarisResolvedPathWrapper targetCatalog =
@@ -223,7 +225,8 @@ public class PolicyCatalogHandler extends CatalogHandler {
   private void authorizePolicyMappingOperationOrThrow(
       PolicyIdentifier identifier, PolicyAttachmentTarget target, boolean 
isAttach) {
     resolutionManifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     resolutionManifest.addPassthroughPath(
         new ResolverPath(
             PolarisCatalogHelpers.identifierToList(identifier.getNamespace(), 
identifier.getName()),
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/config/RealmEntityManagerFactory.java
 
b/service/common/src/main/java/org/apache/polaris/service/config/RealmEntityManagerFactory.java
deleted file mode 100644
index 7c72625df..000000000
--- 
a/service/common/src/main/java/org/apache/polaris/service/config/RealmEntityManagerFactory.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.service.config;
-
-import jakarta.enterprise.context.ApplicationScoped;
-import jakarta.inject.Inject;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import org.apache.polaris.core.context.RealmContext;
-import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
-import org.apache.polaris.core.persistence.resolver.ResolverFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/** Gets or creates PolarisEntityManager instances based on config values and 
RealmContext. */
-@ApplicationScoped
-public class RealmEntityManagerFactory {
-
-  private static final Logger LOGGER = 
LoggerFactory.getLogger(RealmEntityManagerFactory.class);
-
-  private final MetaStoreManagerFactory metaStoreManagerFactory;
-  private final ResolverFactory resolverFactory;
-
-  // Key: realmIdentifier
-  private final Map<String, PolarisEntityManager> cachedEntityManagers = new 
ConcurrentHashMap<>();
-
-  @Inject
-  public RealmEntityManagerFactory(
-      MetaStoreManagerFactory metaStoreManagerFactory, ResolverFactory 
resolverFactory) {
-    this.metaStoreManagerFactory = metaStoreManagerFactory;
-    this.resolverFactory = resolverFactory;
-  }
-
-  public PolarisEntityManager getOrCreateEntityManager(RealmContext context) {
-    String realm = context.getRealmIdentifier();
-
-    LOGGER.debug("Looking up PolarisEntityManager for realm {}", realm);
-
-    return cachedEntityManagers.computeIfAbsent(
-        realm,
-        r -> {
-          LOGGER.info("Initializing new PolarisEntityManager for realm {}", r);
-          return new PolarisEntityManager(
-              metaStoreManagerFactory.getOrCreateMetaStoreManager(context), 
resolverFactory);
-        });
-  }
-}
diff --git 
a/service/common/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceTest.java
 
b/service/common/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceTest.java
index 58b7a0c6d..c5744a8de 100644
--- 
a/service/common/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceTest.java
+++ 
b/service/common/src/test/java/org/apache/polaris/service/admin/PolarisAdminServiceTest.java
@@ -37,11 +37,11 @@ import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.entity.PolarisEntity;
 import org.apache.polaris.core.entity.PolarisEntityType;
 import org.apache.polaris.core.entity.PolarisPrivilege;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
 import org.apache.polaris.core.persistence.dao.entity.PrivilegeResult;
 import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverStatus;
 import org.apache.polaris.core.secrets.UserSecretsManager;
 import org.apache.polaris.service.config.ReservedProperties;
@@ -55,7 +55,7 @@ public class PolarisAdminServiceTest {
   @Mock private CallContext callContext;
   @Mock private PolarisCallContext polarisCallContext;
   @Mock private PolarisDiagnostics polarisDiagnostics;
-  @Mock private PolarisEntityManager entityManager;
+  @Mock private ResolutionManifestFactory resolutionManifestFactory;
   @Mock private PolarisMetaStoreManager metaStoreManager;
   @Mock private UserSecretsManager userSecretsManager;
   @Mock private SecurityContext securityContext;
@@ -77,7 +77,7 @@ public class PolarisAdminServiceTest {
     adminService =
         new PolarisAdminService(
             callContext,
-            entityManager,
+            resolutionManifestFactory,
             metaStoreManager,
             userSecretsManager,
             securityContext,
@@ -113,7 +113,7 @@ public class PolarisAdminServiceTest {
     Namespace namespace = Namespace.of("non-existent-ns");
     PolarisPrivilege privilege = PolarisPrivilege.NAMESPACE_FULL_METADATA;
 
-    when(entityManager.prepareResolutionManifest(any(), any(), 
eq(catalogName)))
+    when(resolutionManifestFactory.createResolutionManifest(any(), any(), 
eq(catalogName)))
         .thenReturn(resolutionManifest);
     
when(resolutionManifest.resolveAll()).thenReturn(createSuccessfulResolverStatus());
 
@@ -140,7 +140,7 @@ public class PolarisAdminServiceTest {
     Namespace namespace = Namespace.of("complete-ns", "incomplete-ns");
     PolarisPrivilege privilege = PolarisPrivilege.NAMESPACE_FULL_METADATA;
 
-    when(entityManager.prepareResolutionManifest(any(), any(), 
eq(catalogName)))
+    when(resolutionManifestFactory.createResolutionManifest(any(), any(), 
eq(catalogName)))
         .thenReturn(resolutionManifest);
     
when(resolutionManifest.resolveAll()).thenReturn(createSuccessfulResolverStatus());
 
@@ -194,7 +194,7 @@ public class PolarisAdminServiceTest {
     Namespace namespace = Namespace.of("non-existent-ns");
     PolarisPrivilege privilege = PolarisPrivilege.NAMESPACE_FULL_METADATA;
 
-    when(entityManager.prepareResolutionManifest(any(), any(), 
eq(catalogName)))
+    when(resolutionManifestFactory.createResolutionManifest(any(), any(), 
eq(catalogName)))
         .thenReturn(resolutionManifest);
     
when(resolutionManifest.resolveAll()).thenReturn(createSuccessfulResolverStatus());
 
@@ -221,7 +221,7 @@ public class PolarisAdminServiceTest {
     Namespace namespace = Namespace.of("incomplete-ns");
     PolarisPrivilege privilege = PolarisPrivilege.NAMESPACE_FULL_METADATA;
 
-    when(entityManager.prepareResolutionManifest(any(), any(), 
eq(catalogName)))
+    when(resolutionManifestFactory.createResolutionManifest(any(), any(), 
eq(catalogName)))
         .thenReturn(resolutionManifest);
     
when(resolutionManifest.resolveAll()).thenReturn(createSuccessfulResolverStatus());
 
@@ -262,7 +262,7 @@ public class PolarisAdminServiceTest {
   private void setupSuccessfulNamespaceResolution(
       String catalogName, String catalogRoleName, Namespace namespace) throws 
Exception {
 
-    when(entityManager.prepareResolutionManifest(any(), any(), 
eq(catalogName)))
+    when(resolutionManifestFactory.createResolutionManifest(any(), any(), 
eq(catalogName)))
         .thenReturn(resolutionManifest);
     
when(resolutionManifest.resolveAll()).thenReturn(createSuccessfulResolverStatus());
     
when(resolutionManifest.getResolvedPath(eq(namespace))).thenReturn(resolvedPathWrapper);
diff --git 
a/service/common/src/test/java/org/apache/polaris/service/admin/PolarisServiceImplTest.java
 
b/service/common/src/test/java/org/apache/polaris/service/admin/PolarisServiceImplTest.java
index a6d01ede4..75adb59f5 100644
--- 
a/service/common/src/test/java/org/apache/polaris/service/admin/PolarisServiceImplTest.java
+++ 
b/service/common/src/test/java/org/apache/polaris/service/admin/PolarisServiceImplTest.java
@@ -37,8 +37,8 @@ import org.apache.polaris.core.config.FeatureConfiguration;
 import org.apache.polaris.core.config.RealmConfig;
 import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.secrets.UserSecretsManagerFactory;
-import org.apache.polaris.service.config.RealmEntityManagerFactory;
 import org.apache.polaris.service.config.ReservedProperties;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -46,7 +46,7 @@ import org.mockito.Mockito;
 
 public class PolarisServiceImplTest {
 
-  private RealmEntityManagerFactory entityManagerFactory;
+  private ResolutionManifestFactory resolutionManifestFactory;
   private MetaStoreManagerFactory metaStoreManagerFactory;
   private UserSecretsManagerFactory userSecretsManagerFactory;
   private PolarisAuthorizer polarisAuthorizer;
@@ -58,7 +58,7 @@ public class PolarisServiceImplTest {
 
   @BeforeEach
   void setUp() {
-    entityManagerFactory = Mockito.mock(RealmEntityManagerFactory.class);
+    resolutionManifestFactory = Mockito.mock(ResolutionManifestFactory.class);
     metaStoreManagerFactory = Mockito.mock(MetaStoreManagerFactory.class);
     userSecretsManagerFactory = Mockito.mock(UserSecretsManagerFactory.class);
     polarisAuthorizer = Mockito.mock(PolarisAuthorizer.class);
@@ -75,7 +75,7 @@ public class PolarisServiceImplTest {
 
     polarisService =
         new PolarisServiceImpl(
-            entityManagerFactory,
+            resolutionManifestFactory,
             metaStoreManagerFactory,
             userSecretsManagerFactory,
             polarisAuthorizer,
diff --git 
a/service/common/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java
 
b/service/common/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java
index 7e320dbbf..96dc25600 100644
--- 
a/service/common/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java
+++ 
b/service/common/src/test/java/org/apache/polaris/service/catalog/io/FileIOFactoryTest.java
@@ -228,7 +228,7 @@ public class FileIOFactoryTest {
     PolarisPassthroughResolutionView passthroughView =
         new PolarisPassthroughResolutionView(
             callContext,
-            
services.entityManagerFactory().getOrCreateEntityManager(realmContext),
+            services.resolutionManifestFactory(),
             services.securityContext(),
             CATALOG_NAME);
     IcebergCatalog polarisCatalog =
diff --git 
a/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java
 
b/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java
index a10e78d2b..8bd031bfd 100644
--- 
a/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java
+++ 
b/service/common/src/testFixtures/java/org/apache/polaris/service/TestServices.java
@@ -42,10 +42,11 @@ import org.apache.polaris.core.entity.PolarisEntity;
 import org.apache.polaris.core.entity.PrincipalEntity;
 import org.apache.polaris.core.persistence.BasePersistence;
 import org.apache.polaris.core.persistence.MetaStoreManagerFactory;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisMetaStoreManager;
 import org.apache.polaris.core.persistence.cache.EntityCache;
 import org.apache.polaris.core.persistence.dao.entity.CreatePrincipalResult;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
+import 
org.apache.polaris.core.persistence.resolver.ResolutionManifestFactoryImpl;
 import org.apache.polaris.core.persistence.resolver.Resolver;
 import org.apache.polaris.core.persistence.resolver.ResolverFactory;
 import org.apache.polaris.core.secrets.UserSecretsManager;
@@ -61,7 +62,6 @@ import 
org.apache.polaris.service.catalog.iceberg.CatalogHandlerUtils;
 import org.apache.polaris.service.catalog.iceberg.IcebergCatalogAdapter;
 import org.apache.polaris.service.catalog.io.FileIOFactory;
 import org.apache.polaris.service.catalog.io.MeasuredFileIOFactory;
-import org.apache.polaris.service.config.RealmEntityManagerFactory;
 import org.apache.polaris.service.config.ReservedProperties;
 import org.apache.polaris.service.context.catalog.CallContextCatalogFactory;
 import 
org.apache.polaris.service.context.catalog.PolarisCallContextCatalogFactory;
@@ -83,7 +83,7 @@ public record TestServices(
     PolarisDiagnostics polarisDiagnostics,
     StorageCredentialCache storageCredentialCache,
     ResolverFactory resolverFactory,
-    RealmEntityManagerFactory entityManagerFactory,
+    ResolutionManifestFactory resolutionManifestFactory,
     MetaStoreManagerFactory metaStoreManagerFactory,
     RealmContext realmContext,
     SecurityContext securityContext,
@@ -191,10 +191,8 @@ public record TestServices(
                   entityCache,
                   referenceCatalogName);
 
-      RealmEntityManagerFactory realmEntityManagerFactory =
-          new RealmEntityManagerFactory(metaStoreManagerFactory, 
resolverFactory);
-      PolarisEntityManager entityManager =
-          realmEntityManagerFactory.getOrCreateEntityManager(realmContext);
+      ResolutionManifestFactory resolutionManifestFactory =
+          new ResolutionManifestFactoryImpl(resolverFactory);
       UserSecretsManager userSecretsManager =
           
userSecretsManagerFactory.getOrCreateUserSecretsManager(realmContext);
 
@@ -223,8 +221,8 @@ public record TestServices(
               realmContext,
               callContext,
               callContextFactory,
-              entityManager,
               resolverFactory,
+              resolutionManifestFactory,
               metaStoreManager,
               userSecretsManager,
               authorizer,
@@ -274,7 +272,7 @@ public record TestServices(
       PolarisCatalogsApi catalogsApi =
           new PolarisCatalogsApi(
               new PolarisServiceImpl(
-                  realmEntityManagerFactory,
+                  resolutionManifestFactory,
                   metaStoreManagerFactory,
                   userSecretsManagerFactory,
                   authorizer,
@@ -290,7 +288,7 @@ public record TestServices(
           polarisDiagnostics,
           storageCredentialCache,
           resolverFactory,
-          realmEntityManagerFactory,
+          resolutionManifestFactory,
           metaStoreManagerFactory,
           realmContext,
           securityContext,
diff --git 
a/service/common/src/testFixtures/java/org/apache/polaris/service/catalog/PolarisPassthroughResolutionView.java
 
b/service/common/src/testFixtures/java/org/apache/polaris/service/catalog/PolarisPassthroughResolutionView.java
index 8919ef5f0..44b1c06fd 100644
--- 
a/service/common/src/testFixtures/java/org/apache/polaris/service/catalog/PolarisPassthroughResolutionView.java
+++ 
b/service/common/src/testFixtures/java/org/apache/polaris/service/catalog/PolarisPassthroughResolutionView.java
@@ -26,10 +26,10 @@ import 
org.apache.polaris.core.catalog.PolarisCatalogHelpers;
 import org.apache.polaris.core.context.CallContext;
 import org.apache.polaris.core.entity.PolarisEntitySubType;
 import org.apache.polaris.core.entity.PolarisEntityType;
-import org.apache.polaris.core.persistence.PolarisEntityManager;
 import org.apache.polaris.core.persistence.PolarisResolvedPathWrapper;
 import org.apache.polaris.core.persistence.resolver.PolarisResolutionManifest;
 import 
org.apache.polaris.core.persistence.resolver.PolarisResolutionManifestCatalogView;
+import org.apache.polaris.core.persistence.resolver.ResolutionManifestFactory;
 import org.apache.polaris.core.persistence.resolver.ResolverPath;
 import org.apache.polaris.service.types.PolicyIdentifier;
 
@@ -41,17 +41,17 @@ import org.apache.polaris.service.types.PolicyIdentifier;
  * set of resolved entities that need to be checked against authorizable 
operations.
  */
 public class PolarisPassthroughResolutionView implements 
PolarisResolutionManifestCatalogView {
-  private final PolarisEntityManager entityManager;
+  private final ResolutionManifestFactory resolutionManifestFactory;
   private final CallContext callContext;
   private final SecurityContext securityContext;
   private final String catalogName;
 
   public PolarisPassthroughResolutionView(
       CallContext callContext,
-      PolarisEntityManager entityManager,
+      ResolutionManifestFactory resolutionManifestFactory,
       SecurityContext securityContext,
       String catalogName) {
-    this.entityManager = entityManager;
+    this.resolutionManifestFactory = resolutionManifestFactory;
     this.callContext = callContext;
     this.securityContext = securityContext;
     this.catalogName = catalogName;
@@ -60,7 +60,8 @@ public class PolarisPassthroughResolutionView implements 
PolarisResolutionManife
   @Override
   public PolarisResolvedPathWrapper getResolvedReferenceCatalogEntity() {
     PolarisResolutionManifest manifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
     manifest.resolveAll();
     return manifest.getResolvedReferenceCatalogEntity();
   }
@@ -68,7 +69,8 @@ public class PolarisPassthroughResolutionView implements 
PolarisResolutionManife
   @Override
   public PolarisResolvedPathWrapper getResolvedPath(Object key) {
     PolarisResolutionManifest manifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
 
     if (key instanceof Namespace namespace) {
       manifest.addPath(
@@ -87,7 +89,8 @@ public class PolarisPassthroughResolutionView implements 
PolarisResolutionManife
   public PolarisResolvedPathWrapper getResolvedPath(
       Object key, PolarisEntityType entityType, PolarisEntitySubType subType) {
     PolarisResolutionManifest manifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
 
     if (key instanceof TableIdentifier identifier) {
       manifest.addPath(
@@ -115,7 +118,8 @@ public class PolarisPassthroughResolutionView implements 
PolarisResolutionManife
   @Override
   public PolarisResolvedPathWrapper getPassthroughResolvedPath(Object key) {
     PolarisResolutionManifest manifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
 
     if (key instanceof Namespace namespace) {
       manifest.addPassthroughPath(
@@ -133,7 +137,8 @@ public class PolarisPassthroughResolutionView implements 
PolarisResolutionManife
   public PolarisResolvedPathWrapper getPassthroughResolvedPath(
       Object key, PolarisEntityType entityType, PolarisEntitySubType subType) {
     PolarisResolutionManifest manifest =
-        entityManager.prepareResolutionManifest(callContext, securityContext, 
catalogName);
+        resolutionManifestFactory.createResolutionManifest(
+            callContext, securityContext, catalogName);
 
     if (key instanceof TableIdentifier identifier) {
       manifest.addPassthroughPath(


Reply via email to