diff --git a/polaris-core/src/main/java/org/apache/polaris/core/entity/PolarisBaseEntity.java b/polaris-core/src/main/java/org/apache/polaris/core/entity/PolarisBaseEntity.java index c50c16fcff..80b0a96405 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/entity/PolarisBaseEntity.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/entity/PolarisBaseEntity.java @@ -19,12 +19,9 @@ package org.apache.polaris.core.entity; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.HashMap; import java.util.Map; import java.util.Objects; +import org.apache.polaris.core.persistence.PolarisObjectMapperUtil; /** * Base polaris entity representing all attributes of a Polaris Entity. This is used to exchange @@ -34,9 +31,6 @@ public class PolarisBaseEntity extends PolarisEntityCore { public static final String EMPTY_MAP_STRING = "{}"; - // to serialize/deserialize properties - private static final ObjectMapper MAPPER = new ObjectMapper(); - // the type of the entity when it was resolved protected final int subTypeCode; @@ -106,25 +100,15 @@ public PolarisBaseEntity withGrantRecordsVersion(int grantRecordsVersion) { @JsonIgnore public Map getPropertiesAsMap() { - if (properties == null) { - return new HashMap<>(); - } - try { - return MAPPER.readValue(properties, new TypeReference<>() {}); - } catch (JsonProcessingException ex) { - throw new IllegalStateException( - String.format("Failed to deserialize json. properties %s", properties), ex); - } + return PolarisObjectMapperUtil.deserializeProperties(getProperties()); } @JsonIgnore - public static String convertPropertiesToJson(Map properties) { - try { - return properties == null ? null : MAPPER.writeValueAsString(properties); - } catch (JsonProcessingException ex) { - throw new IllegalStateException( - String.format("Failed to serialize json. properties %s", properties), ex); + protected static String convertPropertiesToJson(Map properties) { + if (properties == null || properties.isEmpty()) { + return EMPTY_MAP_STRING; } + return PolarisObjectMapperUtil.serializeProperties(properties); } public String getInternalProperties() { @@ -133,17 +117,7 @@ public String getInternalProperties() { @JsonIgnore public Map getInternalPropertiesAsMap() { - if (this.internalProperties == null) { - return new HashMap<>(); - } - try { - return MAPPER.readValue(this.internalProperties, new TypeReference<>() {}); - } catch (JsonProcessingException ex) { - throw new IllegalStateException( - String.format( - "Failed to deserialize json. internalProperties %s", this.internalProperties), - ex); - } + return PolarisObjectMapperUtil.deserializeProperties(getInternalProperties()); } public int getGrantRecordsVersion() { diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/AtomicOperationMetaStoreManager.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/AtomicOperationMetaStoreManager.java index 5e598f9b47..c52e9273f1 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/AtomicOperationMetaStoreManager.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/AtomicOperationMetaStoreManager.java @@ -858,9 +858,7 @@ private void revokeGrantRecord( } PolarisBaseEntity principal = loadEntityResult.getEntity(); - Map internalProps = - PolarisObjectMapperUtil.deserializeProperties( - principal.getInternalProperties() == null ? "{}" : principal.getInternalProperties()); + Map internalProps = principal.getInternalPropertiesAsMap(); boolean doReset = reset @@ -877,15 +875,13 @@ private void revokeGrantRecord( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) { internalProps.put( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE, "true"); - principalBuilder.internalProperties( - PolarisObjectMapperUtil.serializeProperties(internalProps)); + principalBuilder.internalPropertiesAsMap(internalProps); principalBuilder.entityVersion(principal.getEntityVersion() + 1); ms.writeEntity(callCtx, principalBuilder.build(), true, principal); } else if (internalProps.containsKey( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) { internalProps.remove(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE); - principalBuilder.internalProperties( - PolarisObjectMapperUtil.serializeProperties(internalProps)); + principalBuilder.internalPropertiesAsMap(internalProps); principalBuilder.entityVersion(principal.getEntityVersion() + 1); ms.writeEntity(callCtx, principalBuilder.build(), true, principal); } @@ -1230,7 +1226,7 @@ private void revokeGrantRecord( PolarisTaskConstants.TASK_DATA, PolarisObjectMapperUtil.serialize(refreshEntityToDrop)); PolarisBaseEntity.Builder taskEntityBuilder = new PolarisBaseEntity.Builder() - .properties(PolarisObjectMapperUtil.serializeProperties(properties)) + .propertiesAsMap(properties) .id(ms.generateNewId(callCtx)) .catalogId(0L) .name("entityCleanup_" + entityToDrop.getId()) @@ -1238,8 +1234,7 @@ private void revokeGrantRecord( .subTypeCode(PolarisEntitySubType.NULL_SUBTYPE.getCode()) .createTimestamp(clock.millis()); if (cleanupProperties != null) { - taskEntityBuilder.internalProperties( - PolarisObjectMapperUtil.serializeProperties(cleanupProperties)); + taskEntityBuilder.internalPropertiesAsMap(cleanupProperties); } // TODO: Add a way to create the task entities atomically with dropping the entity; // in the meantime, if the server fails partway through a dropEntity, it's possible that @@ -1523,8 +1518,7 @@ private void revokeGrantRecord( task -> { PolarisBaseEntity.Builder updatedTaskBuilder = new PolarisBaseEntity.Builder(task); - Map properties = - PolarisObjectMapperUtil.deserializeProperties(task.getProperties()); + Map properties = task.getPropertiesAsMap(); properties.put(PolarisTaskConstants.LAST_ATTEMPT_EXECUTOR_ID, executorId); properties.put( PolarisTaskConstants.LAST_ATTEMPT_START_TIME, String.valueOf(clock.millis())); @@ -1534,8 +1528,7 @@ private void revokeGrantRecord( Integer.parseInt( properties.getOrDefault(PolarisTaskConstants.ATTEMPT_COUNT, "0")) + 1)); - updatedTaskBuilder.properties( - PolarisObjectMapperUtil.serializeProperties(properties)); + updatedTaskBuilder.propertiesAsMap(properties); EntityResult result = updateEntityPropertiesIfNotChanged(callCtx, null, updatedTaskBuilder.build()); if (result.getReturnStatus() == BaseResult.ReturnStatus.SUCCESS) { diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/BaseMetaStoreManager.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/BaseMetaStoreManager.java index 9820d8950c..a56eeda3dc 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/BaseMetaStoreManager.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/BaseMetaStoreManager.java @@ -39,8 +39,7 @@ public abstract class BaseMetaStoreManager implements PolarisMetaStoreManager { public static PolarisStorageConfigurationInfo extractStorageConfiguration( @Nonnull PolarisDiagnostics diagnostics, PolarisBaseEntity reloadedEntity) { - Map propMap = - PolarisObjectMapperUtil.deserializeProperties(reloadedEntity.getInternalProperties()); + Map propMap = reloadedEntity.getInternalPropertiesAsMap(); String storageConfigInfoStr = propMap.get(PolarisEntityConstants.getStorageConfigInfoPropertyName()); diff --git a/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TransactionalMetaStoreManagerImpl.java b/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TransactionalMetaStoreManagerImpl.java index 50ebc52a78..18484a5516 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TransactionalMetaStoreManagerImpl.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/persistence/transactional/TransactionalMetaStoreManagerImpl.java @@ -893,9 +893,7 @@ private void bootstrapPolarisService( PolarisBaseEntity principal = loadEntityResult.getEntity(); PolarisBaseEntity.Builder principalBuilder = new PolarisBaseEntity.Builder(principal); - Map internalProps = - PolarisObjectMapperUtil.deserializeProperties( - principal.getInternalProperties() == null ? "{}" : principal.getInternalProperties()); + Map internalProps = principal.getInternalPropertiesAsMap(); boolean doReset = reset @@ -911,15 +909,13 @@ private void bootstrapPolarisService( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) { internalProps.put( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE, "true"); - principalBuilder.internalProperties( - PolarisObjectMapperUtil.serializeProperties(internalProps)); + principalBuilder.internalPropertiesAsMap(internalProps); principalBuilder.entityVersion(principal.getEntityVersion() + 1); ms.writeEntityInCurrentTxn(callCtx, principalBuilder.build(), true, principal); } else if (internalProps.containsKey( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) { internalProps.remove(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE); - principalBuilder.internalProperties( - PolarisObjectMapperUtil.serializeProperties(internalProps)); + principalBuilder.internalPropertiesAsMap(internalProps); principalBuilder.entityVersion(principal.getEntityVersion() + 1); ms.writeEntityInCurrentTxn(callCtx, principalBuilder.build(), true, principal); } @@ -1438,10 +1434,9 @@ private void bootstrapPolarisService( .typeCode(PolarisEntityType.TASK.getCode()) .subTypeCode(PolarisEntitySubType.NULL_SUBTYPE.getCode()) .createTimestamp(clock.millis()) - .properties(PolarisObjectMapperUtil.serializeProperties(properties)); + .propertiesAsMap(properties); if (cleanupProperties != null) { - taskEntityBuilder.internalProperties( - PolarisObjectMapperUtil.serializeProperties(cleanupProperties)); + taskEntityBuilder.internalPropertiesAsMap(cleanupProperties); } PolarisBaseEntity taskEntity = taskEntityBuilder.build(); createEntityIfNotExists(callCtx, ms, null, taskEntity); @@ -1975,8 +1970,7 @@ private PolarisEntityResolver resolveSecurableToRoleGrant( .map( task -> { PolarisBaseEntity.Builder updatedTask = new PolarisBaseEntity.Builder(task); - Map properties = - PolarisObjectMapperUtil.deserializeProperties(task.getProperties()); + Map properties = task.getPropertiesAsMap(); properties.put(PolarisTaskConstants.LAST_ATTEMPT_EXECUTOR_ID, executorId); properties.put( PolarisTaskConstants.LAST_ATTEMPT_START_TIME, String.valueOf(clock.millis())); @@ -1986,7 +1980,7 @@ private PolarisEntityResolver resolveSecurableToRoleGrant( Integer.parseInt( properties.getOrDefault(PolarisTaskConstants.ATTEMPT_COUNT, "0")) + 1)); - updatedTask.properties(PolarisObjectMapperUtil.serializeProperties(properties)); + updatedTask.propertiesAsMap(properties); EntityResult result = updateEntityPropertiesIfNotChanged(callCtx, ms, null, updatedTask.build()); if (result.getReturnStatus() == BaseResult.ReturnStatus.SUCCESS) { diff --git a/polaris-core/src/test/java/org/apache/polaris/core/storage/cache/StorageCredentialCacheTest.java b/polaris-core/src/test/java/org/apache/polaris/core/storage/cache/StorageCredentialCacheTest.java index 5364fa8433..07b233228b 100644 --- a/polaris-core/src/test/java/org/apache/polaris/core/storage/cache/StorageCredentialCacheTest.java +++ b/polaris-core/src/test/java/org/apache/polaris/core/storage/cache/StorageCredentialCacheTest.java @@ -36,7 +36,6 @@ import org.apache.polaris.core.entity.PolarisEntitySubType; import org.apache.polaris.core.entity.PolarisEntityType; import org.apache.polaris.core.persistence.PolarisMetaStoreManager; -import org.apache.polaris.core.persistence.PolarisObjectMapperUtil; import org.apache.polaris.core.persistence.dao.entity.BaseResult; import org.apache.polaris.core.persistence.dao.entity.ScopedCredentialsResult; import org.apache.polaris.core.persistence.transactional.TransactionalPersistence; @@ -246,9 +245,7 @@ public void testCacheGenerateNewEntries() { internalMap.put( PolarisEntityConstants.getStorageConfigInfoPropertyName(), "newStorageConfig"); PolarisBaseEntity updateEntity = - new PolarisBaseEntity.Builder(entity) - .internalProperties(PolarisObjectMapperUtil.serializeProperties(internalMap)) - .build(); + new PolarisBaseEntity.Builder(entity).internalPropertiesAsMap(internalMap).build(); storageCredentialCache.getOrGenerateSubScopeCreds( metaStoreManager, callCtx, @@ -286,9 +283,7 @@ public void testCacheGenerateNewEntries() { internalMap.put( PolarisEntityConstants.getStorageConfigInfoPropertyName(), "newStorageConfig"); PolarisBaseEntity updateEntity = - new PolarisBaseEntity.Builder(entity) - .internalProperties(PolarisObjectMapperUtil.serializeProperties(internalMap)) - .build(); + new PolarisBaseEntity.Builder(entity).internalPropertiesAsMap(internalMap).build(); storageCredentialCache.getOrGenerateSubScopeCreds( metaStoreManager, callCtx, diff --git a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BasePolarisMetaStoreManagerTest.java b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BasePolarisMetaStoreManagerTest.java index 12096be46a..6adb042acd 100644 --- a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BasePolarisMetaStoreManagerTest.java +++ b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/BasePolarisMetaStoreManagerTest.java @@ -292,8 +292,8 @@ protected void testLoadTasks() { entry -> Assertions.assertThat(entry) .extracting( - e -> PolarisObjectMapperUtil.deserializeProperties(e.getProperties())) - .asInstanceOf(InstanceOfAssertFactories.map(String.class, String.class)) + PolarisBaseEntity::getPropertiesAsMap, + InstanceOfAssertFactories.map(String.class, String.class)) .containsEntry(PolarisTaskConstants.LAST_ATTEMPT_EXECUTOR_ID, executorId) .containsEntry(PolarisTaskConstants.ATTEMPT_COUNT, "1")); Set firstTasks = diff --git a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/PolarisTestMetaStoreManager.java b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/PolarisTestMetaStoreManager.java index f4aa7aa46c..646aeee51d 100644 --- a/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/PolarisTestMetaStoreManager.java +++ b/polaris-core/src/testFixtures/java/org/apache/polaris/core/persistence/PolarisTestMetaStoreManager.java @@ -18,8 +18,6 @@ */ package org.apache.polaris.core.persistence; -import static org.apache.polaris.core.entity.PolarisBaseEntity.convertPropertiesToJson; - import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -419,11 +417,8 @@ PolarisBaseEntity createPrincipal(String name) { .subTypeCode(PolarisEntitySubType.NULL_SUBTYPE.getCode()) .parentId(PolarisEntityConstants.getRootEntityId()) .name(name) - .internalProperties( - PolarisObjectMapperUtil.serializeProperties( - Map.of( - PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE, - "true"))) + .internalPropertiesAsMap( + Map.of(PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE, "true")) .build(); CreatePrincipalResult createPrincipalResult = @@ -466,8 +461,7 @@ PolarisBaseEntity createPrincipal(String name) { .isEqualTo(secrets.getSecondarySecretHash()); Map internalProperties = - PolarisObjectMapperUtil.deserializeProperties( - createPrincipalResult.getPrincipal().getInternalProperties()); + createPrincipalResult.getPrincipal().getInternalPropertiesAsMap(); Assertions.assertThat( internalProperties.get( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) @@ -510,8 +504,7 @@ PolarisBaseEntity createPrincipal(String name) { createPrincipalResult.getPrincipal().getId(), createPrincipalResult.getPrincipal().getType()) .getEntity(); - internalProperties = - PolarisObjectMapperUtil.deserializeProperties(reloadPrincipal.getInternalProperties()); + internalProperties = reloadPrincipal.getInternalPropertiesAsMap(); Assertions.assertThat( internalProperties.get( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) @@ -567,8 +560,7 @@ PolarisBaseEntity createPrincipal(String name) { .loadEntity( this.polarisCallContext, 0L, principalEntity.getId(), principalEntity.getType()) .getEntity(); - internalProperties = - PolarisObjectMapperUtil.deserializeProperties(newPrincipal.getInternalProperties()); + internalProperties = newPrincipal.getInternalPropertiesAsMap(); Assertions.assertThat( internalProperties.get( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) @@ -601,8 +593,7 @@ PolarisBaseEntity createPrincipal(String name) { .loadEntity( this.polarisCallContext, 0L, principalEntity.getId(), principalEntity.getType()) .getEntity(); - internalProperties = - PolarisObjectMapperUtil.deserializeProperties(finalPrincipal.getInternalProperties()); + internalProperties = finalPrincipal.getInternalPropertiesAsMap(); Assertions.assertThat( internalProperties.get( PolarisEntityConstants.PRINCIPAL_CREDENTIAL_ROTATION_REQUIRED_STATE)) @@ -669,7 +660,7 @@ PolarisBaseEntity createEntity( .subTypeCode(entitySubType.getCode()) .parentId(parentId) .name(name) - .properties(convertPropertiesToJson(properties)) + .propertiesAsMap(properties) .build(); PolarisBaseEntity entity = polarisMetaStoreManager @@ -870,11 +861,9 @@ void dropEntity(List catalogPath, PolarisBaseEntity entityToD Assertions.assertThat(cleanupTask).isNotNull(); Assertions.assertThat(cleanupTask.getType()).isEqualTo(PolarisEntityType.TASK); Assertions.assertThat(cleanupTask.getInternalProperties()).isNotNull(); - Map internalProperties = - PolarisObjectMapperUtil.deserializeProperties(cleanupTask.getInternalProperties()); + Map internalProperties = cleanupTask.getInternalPropertiesAsMap(); Assertions.assertThat(internalProperties).isEqualTo(cleanupProperties); - Map properties = - PolarisObjectMapperUtil.deserializeProperties(cleanupTask.getProperties()); + Map properties = cleanupTask.getPropertiesAsMap(); Assertions.assertThat(properties).isNotNull(); Assertions.assertThat(properties.get(PolarisTaskConstants.TASK_DATA)).isNotNull(); PolarisBaseEntity droppedEntity =