You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ClassCastException when trying to store/retrieve Records in a ConcurrentSkipListSet using EclipseStore.
Error message:
java.lang.ClassCastException: class Record cannot be cast to class java.lang.Comparable
The issue is consistently reproducible.
To Reproduce
Create a Record class with a timestamp field
Create a TestData class with a Map<String, NavigableSet>
Use ConcurrentSkipListSet with a custom Comparator
Try to store and retrieve data using EclipseStore
Get ClassCastException during storage operation
Expected behavior
Records should be stored and retrieved successfully in the sorted set without any ClassCastException.
Additional context
The issue seems related to serialization/deserialization of the ConcurrentSkipListSet with a custom Comparator in EclipseStore. Implementing Comparable interface on Record class could be potential workarounds.
Code
package eclipse.store.test;
import ch.qos.logback.classic.Level;
import org.eclipse.store.storage.embedded.types.EmbeddedStorage;
import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;
class EclipseStoreTest {
private static final Logger logger = LoggerFactory.getLogger(EclipseStoreTest.class);
private static final String STORAGE_PATH = "target/test-storage";
static class Record /*implements Comparable<Record>*/ {
private final Long timestamp;
public Record(Long timestamp) {
this.timestamp = timestamp;
}
public Long getTimestamp() {
return timestamp;
}
// @Override
// public int compareTo(Record other) {
// return Long.compare(this.timestamp, other.timestamp);
// }
@Override
public String toString() {
return "Record{timestamp=" + timestamp + '}';
}
}
static class RecordComparator implements Comparator<Record> {
@Override
public int compare(Record record1, Record record2) {
int timestampComparison = Long.compare(record1.getTimestamp(), record2.getTimestamp());
return timestampComparison;
}
}
static class TestData {
private Map<String, NavigableSet<Record>> data;
public TestData() {
this.data = new HashMap<>();
}
public void addRecord(String connector, Record r) {
data.computeIfAbsent(connector, k -> new ConcurrentSkipListSet<>(new RecordComparator())).add(r);
}
public NavigableSet<Record> getRecords(String connector) {
return data.getOrDefault(connector, new ConcurrentSkipListSet<>(new RecordComparator()));
}
}
@Test
void storeInitialData() {
EmbeddedStorageManager storage = EmbeddedStorage.start(Paths.get(STORAGE_PATH));
try {
TestData testData = new TestData();
testData.addRecord("set1", createRecord(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()));
storage.setRoot(testData);
storage.storeRoot();
} finally {
storage.shutdown();
}
}
@Test
void readData() {
TestData updatedData = loadData();
logger.info("Records: {}", updatedData.getRecords("set1"));
}
private void persistData(TestData data) {
EmbeddedStorageManager storage = EmbeddedStorage.start(Paths.get(STORAGE_PATH));
try {
storage.setRoot(data);
storage.storeRoot();
} finally {
storage.shutdown();
}
}
private TestData loadData() {
EmbeddedStorageManager storage = EmbeddedStorage.start(Paths.get(STORAGE_PATH));
try {
TestData data = (TestData) storage.root();
if (data == null) {
logger.error("Data could not be loaded. Root is null.");
return new TestData();
}
return data;
} finally {
storage.shutdown();
}
}
private Record createRecord(long timestamp) {
return new Record(timestamp);
}
}
The text was updated successfully, but these errors were encountered:
I think it's likely that the serializer needs to be aware of this comparator on the Record class at compile time by defining it, as you've suggested, on the Record class itself. If you're passing a custom comparator via the constructor, that could vary at runtime(imagineRecordComparatorFoo extends RecordComparator), and I'm not sure that we would expect that the serializer would persist information about whether you passed a RecordComparatorFoo or RecordComparator to the ConcurrentSkipListSet<>.
Environment Details
Describe the bug
ClassCastException when trying to store/retrieve Records in a ConcurrentSkipListSet using EclipseStore.
Error message:
The issue is consistently reproducible.
To Reproduce
Expected behavior
Records should be stored and retrieved successfully in the sorted set without any ClassCastException.
Additional context
The issue seems related to serialization/deserialization of the ConcurrentSkipListSet with a custom Comparator in EclipseStore. Implementing Comparable interface on Record class could be potential workarounds.
Code
The text was updated successfully, but these errors were encountered: