Skip to content

PersistenceExceptionTypeHandlerConsistencyUnhandledTypeId #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
rpx99 opened this issue Feb 26, 2025 · 7 comments
Open

PersistenceExceptionTypeHandlerConsistencyUnhandledTypeId #176

rpx99 opened this issue Feb 26, 2025 · 7 comments

Comments

@rpx99
Copy link

rpx99 commented Feb 26, 2025

Wonder what I am doing wrongly...

byte[] data = kundeSerializer.serialize(kunde); // ok
kundeSerializer.deserialize(data); // error

Caused by: java.lang.RuntimeException: java.util.concurrent.ExecutionException: org.eclipse.serializer.persistence.exceptions.PersistenceExceptionTypeHandlerConsistencyUnhandledTypeId: No type handler found for type id "1000061".

Have this in my dictionary:

0000000000001000061 org.eclipse.serializer.persistence.types.PersistenceRoots$Default{
	[list] instances  (
		java.lang.Object instance,
	),
	[list] identifiers(
		[char] identifier,
	),
}

    public byte[] serialize(Kunde kunde) {
        // Serialisiere das Kunde-Objekt in ein Byte-Array
        Serializer<byte[]> serializer = Serializer.Bytes();
        byte[] data = serializer.serialize(kunde);
        return data;
    }

    public Kunde deserialize(byte[] data) {
        // Deserialisiere das Byte-Array zurück zum Kunde-Objekt
        Serializer<byte[]> serializer = Serializer.Bytes();
        Kunde kunde = serializer.deserialize(data);
        return kunde;
    }
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Kunde implements Basis, Serializable {

    private static final Faker faker = new Faker();

    private UUID id;
    private String kundennummer;
    private String vorname;
    private String nachname;
    //private LocalDate geburtsdatum;

    // Custom Constructor with default values
    public static Kunde createWithDefaults() {
        return Kunde.builder()
                .id(UUID.randomUUID())
                .kundennummer(String.valueOf(faker.number().randomNumber(10, true)))
                .vorname(faker.name().firstName())
                .nachname(faker.name().lastName())
                //.geburtsdatum(faker.date().birthday(18, 80).toInstant().atZone(ZoneId.systemDefault()).toLocalDate())
                .build();
    }

    @Override
    public UUID getId() {
        return id;
    }

    public String getFullName() {
        return vorname + " " + nachname + "  // ("+kundennummer+")";
    }

//    public String getFullName() {
//        String formattedGeburtsdatum = (geburtsdatum != null) ? geburtsdatum.format(DateTimeFormatter.ofPattern("dd.MM.yyyy")) : "n.a.";
//        return vorname + " " + nachname + " --- geb. am " + formattedGeburtsdatum;
//    }
}

Using serializer version 2.1.2

@rpx99
Copy link
Author

rpx99 commented Feb 26, 2025

Okay, I found this

Seems I need to register my class?

    public byte[] serialize(Kunde kunde) {
        final SerializerFoundation<?> foundation = SerializerFoundation.New()
                .registerEntityTypes(Kunde.class);
        final Serializer<byte[]> serializer = Serializer.Bytes(foundation);
        // Serialisiere das Kunde-Objekt in ein Byte-Array
        //Serializer<byte[]> serializer = Serializer.Bytes();
        byte[] data = serializer.serialize(kunde);
        return data;
    }

    public Kunde deserialize(byte[] data) {
        final SerializerFoundation<?> foundation = SerializerFoundation.New()
                .registerEntityTypes(Kunde.class);
        final Serializer<byte[]> serializer = Serializer.Bytes(foundation);
        // Deserialisiere das Byte-Array zurück zum Kunde-Objekt
        //Serializer<byte[]> serializer = Serializer.Bytes();
        Kunde kunde = serializer.deserialize(data);
        return kunde;
    }

@rpx99
Copy link
Author

rpx99 commented Feb 26, 2025

This works, too (without registering my Kunde class).


    private final Serializer<byte[]> serializer;

    @Inject
    public KundeSerializer() {
        // Initialisieren Sie SerializerFoundation und Serializer im Konstruktor
        //SerializerFoundation<?> foundation = SerializerFoundation.New().registerEntityTypes(Kunde.class);
        //this.serializer = Serializer.Bytes(foundation);
        this.serializer = Serializer.Bytes();
    }

    public byte[] serialize(Kunde kunde) {
        // Serialisiere das Kunde-Objekt in ein Byte-Array
        return serializer.serialize(kunde);
    }

    public Kunde deserialize(byte[] data) {
        // Deserialisiere das Byte-Array zurück zum Kunde-Objekt
        return serializer.deserialize(data);
    }

In my log I see:

Type dictionary is empty or not existing. Initializing type handler manager with a new default type dictionary

Wonder what's the problem in my original code...

@hg-ms
Copy link
Contributor

hg-ms commented Feb 26, 2025

The Exception is thrown because the serialized data does not contain type information by default.
The second serializer instance that does the deserialization does not know which type has been associated with the id "1000061" by the serializing instance.

To solve that you have several options how to sync type information between different serializer instances, please have a look at the docu for details.

The options are:

  1. Register types explicitly.
  2. Export and import the serializer type dictionary.
  3. Use the 'TypedSerializer' that includes type information in the serialized data.

@rpx99
Copy link
Author

rpx99 commented Mar 6, 2025

Maybe one suggestion for method 2 of the docu is to stress that it is really the content of the file and not the path of the file one needs to pass in:

        // Pfad zur Datei aus der System-Eigenschaft abrufen
        String storageDirectory = System.getProperty("org.eclipse.store.storage.directory");
        String typeDictionaryPath = Paths.get(storageDirectory, "PersistenceTypeDictionary.ptd").toString();
        log.info("Using type dictionary: " + typeDictionaryPath);
        // Inhalt der .ptd-Datei als String lesen
        String typeDictionaryContent = readTypeDictionaryContent(typeDictionaryPath);
        final SerializerFoundation<?> foundation = SerializerFoundation.New(typeDictionaryContent);
        log.info("Using serializer foundation: " + foundation);
        this.serializer = Serializer.Bytes(foundation);


    private String readTypeDictionaryContent(String path) {
        try {
            return new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new RuntimeException("Failed to read .ptd file: " + path, e);
        }
    }

@hg-ms
Copy link
Contributor

hg-ms commented Mar 7, 2025

Maybe one suggestion for method 2 of the docu is to stress that it is really the content of the file and not the path of the file one needs to pass in:

Using a storage-type-dictionary-file to initialize a serializer instance is only one of many option to configure the serializer.
The serializer does not require a storage-type-dictionary as the serializer is intended to work without a storage. Therefore, the serializer offers an API to export its current type-dictionary as a String and an API to instantiate a serializer with that exported type-dictionary (for deserialization).

@rpx99
Copy link
Author

rpx99 commented Mar 7, 2025

Understand. How to create the appropriate string from storageManager.typeDictionary() ?

This is wrong: storageManager.typeDictionary().view().toString();

@hg-ms
Copy link
Contributor

hg-ms commented Mar 7, 2025

You need to use the PersistenceTypeDictionaryAssembler:

 String typeDictionaryString = PersistenceTypeDictionaryAssembler.New().assemble(storageManager.typeDictionary());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants