-
Notifications
You must be signed in to change notification settings - Fork 35
BinaryPersistenceException: Inconsistent state for java.math.BigDecimal used as a storage root #521
Description
This happens only when BigDecimal / BigInteger is used as the root object. In practice, using such a numeric value as the storage root is unrealistic and makes no practical sense.
When storing and reloading BigDecimal an inconsistency is thrown if the same numeric value is represented with different scales (for example "1.23" vs "1.2300").
Exception :
org.eclipse.serializer.persistence.binary.exceptions.BinaryPersistenceException: Inconsistent state for instance java.math.BigDecimal@72443081: "1.23" not equal to "1.2300"
Full stack trace:
org.eclipse.serializer.persistence.binary.exceptions.BinaryPersistenceException: Inconsistent state for instance java.math.BigDecimal@72443081: "1.23" not equal to "1.2300"
at org.eclipse.serializer.persistence.binary.types.ValidatingBinaryHandler.throwInconsistentStateException(ValidatingBinaryHandler.java:57)
at org.eclipse.serializer.persistence.binary.types.ValidatingBinaryHandler.validateStates(ValidatingBinaryHandler.java:47)
at org.eclipse.serializer.persistence.binary.types.ValidatingBinaryHandler.validateState(ValidatingBinaryHandler.java:25)
at org.eclipse.serializer.persistence.binary.types.AbstractBinaryHandlerCustomValue.updateState(AbstractBinaryHandlerCustomValue.java:69)
at org.eclipse.serializer.persistence.binary.types.AbstractBinaryHandlerCustomValue.updateState(AbstractBinaryHandlerCustomValue.java:23)
at org.eclipse.serializer.persistence.binary.types.BinaryLoader$Default.buildInstances(BinaryLoader.java:463)
at org.eclipse.serializer.persistence.binary.types.BinaryLoader$Default.build(BinaryLoader.java:397)
at org.eclipse.serializer.persistence.binary.types.BinaryLoader$Default.get(BinaryLoader.java:834)
at org.eclipse.serializer.persistence.binary.types.BinaryLoader$Default.loadRoots(BinaryLoader.java:894)
at org.eclipse.store.storage.embedded.types.EmbeddedStorageManager$Default.loadExistingRoots(EmbeddedStorageManager.java:355)
at org.eclipse.store.storage.embedded.types.EmbeddedStorageManager$Default.initialize(EmbeddedStorageManager.java:378)
at org.eclipse.store.storage.embedded.types.EmbeddedStorageManager$Default.start(EmbeddedStorageManager.java:258)
at org.eclipse.store.storage.embedded.types.EmbeddedStorageManager$Default.start(EmbeddedStorageManager.java:99)
at org.eclipse.store.storage.embedded.types.EmbeddedStorage.createAndStartStorageManager(EmbeddedStorage.java:609)
at org.eclipse.store.storage.embedded.types.EmbeddedStorage.start(EmbeddedStorage.java:466)
at test.microstream.various.jdk.BigDecimalTest.bigDecimalDifferentScalesBehavior(BigDecimalTest.java:43)
Steps to reproduce (summary):
- Persist a BigDecimal value with scale X (e.g. new BigDecimal("1.2300").setScale(4, RoundingMode.UNNECESSARY) as root or inside an object.
- Persist a BigDecimal numeric-equal value with a different scale (e.g. new BigDecimal("1.23")) in a subsequent run or update.
- Reload / compare — exception is thrown during binary persistence validation.
Expected behavior:
Value in loaded instance should be updated with value stored in the storage.
Actual behavior:
Persistence throws BinaryPersistenceException reporting the two BigDecimal string representations as unequal ("1.23" vs "1.2300").
Test:
@Test
void bigDecimalDifferentScalesBehavior()
{
BigDecimal bd = new BigDecimal("1.2300").setScale(4, RoundingMode.UNNECESSARY);
try (EmbeddedStorageManager storageManager = EmbeddedStorage.start(bd, tempDir)) {
}
BigDecimal bd2 = new BigDecimal("1.23");
try (EmbeddedStorageManager storageManager = EmbeddedStorage.start(bd2, tempDir)) {
// numeric equality ignoring scale
assertEquals(bd.stripTrailingZeros(), bd2.stripTrailingZeros(), "BigDecimal numeric value should match when stripped");
}
}This issue also affects the BigInteger type.
@Test
void bigIntegerVariants()
{
BigInteger first = new BigInteger("12");
try (EmbeddedStorageManager storageManager = EmbeddedStorage.start(first, tempDir)) {
}
BigInteger loaded = new BigInteger("123");
try (EmbeddedStorageManager storageManager = EmbeddedStorage.start(loaded, tempDir)) {
assertEquals(first, loaded, "should be equal after storing and reloading");
}
}