eclipse / jnosql

Eclipse JNoSQL is a framework which has the goal to help Java developers to create Jakarta EE applications with NoSQL.
Other
229 stars 72 forks source link

[BUG] Invalid deserialization of maps with generic values #535

Closed m4ttek closed 1 month ago

m4ttek commented 1 month ago

Which JNoSQL project the issue refers to?

JNoSQL (Core)

Bug description

Maps with nested objects are not properly treated while reading them from database. As I tried debugging it, it seems that Reflections class just sets ArrayList of DefaultElement while executing setValue method. It causes the map to have array index as a key instead of actual key, which is incorrectly written inside a subobject in a field "name".

image

Fortunately, whole entity is correctly saved to database, so it's only a problem with reading it then.

JNoSQL Version

1.1.1

Steps To Reproduce

  1. Create an Entity with a field type Map<String, Object>
  2. Save an instance of this entity to database, field should contain map with nested subobject, i.e.
    {
    "opinion": "test",
    "question": {
     "question_1": false,
     "question_2": false
    }
    }
  3. Try to read it using standard repositor

Expected Results

An object should be properly read from database, in the same form as it is saved.

Code example, screenshot, or link to a repository

No response

otaviojava commented 1 month ago

Hey @m4ttek what database are you using?

m4ttek commented 1 month ago

Hi @otaviojava , I'm using ArangoDB in my project.

otaviojava commented 1 month ago

Hey @m4ttek could you help me to reproduce it?

@Entity
public class Form {

    @Id
    private String id;

    @Column
    private Map<String, Object> questions;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Map<String, Object> getQuestions() {
        return questions;
    }

    public void setQuestions(Map<String, Object> questions) {
        this.questions = questions;
    }
}

The execution:

import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import org.eclipse.jnosql.mapping.document.DocumentTemplate;

import java.util.List;
import java.util.Map;

public class App5 {

    public static void main(String[] args) {

        try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
          Form form = new Form();
          form.setId("form");
          form.setQuestions(Map.of("question_1", "Duke", "question_2", false));
            var template = container.select(DocumentTemplate.class).get();
            template.insert(form);
            List<Form> heroes = template.select(Form.class).result();
            System.out.println(heroes);

        }
    }

    private App5() {
    }
}
m4ttek commented 1 month ago

@otaviojava try to add third entry to question map with nested map, i.e. "question_3", Map.of("advanced", "true", "visible": "true")

otaviojava commented 1 month ago

Thanks, @m4ttek. I created the solution. Could you test it, please?

m4ttek commented 1 month ago

I've tested it with 1.1.2-SNAPSHOT and unfortunately it still doesn't work properly: image

otaviojava commented 1 month ago

Hey @m4ttek could you give me the test that you are doing?

Because it looks like the serialization happen without using `Element ' or any fields from the implementation.

otaviojava commented 1 month ago

Using the previous sample that you mentioned, it shows this way:

Screenshot 2024-08-09 at 16 49 58

m4ttek commented 1 month ago

Do I use proper repositories for snapshots?

repositories {
    maven("https://jakarta.oss.sonatype.org/content/repositories/snapshots/")
    maven("https://oss.sonatype.org/content/repositories/snapshots")
}

The difference between your test and mine is that I'm using Repository instead of DocumentTemplate and that I have inheritance in my model class, so this generic map is in a subclass. I thought, that it's probably irrelevant in handling single field.

otaviojava commented 1 month ago

Yes, you are using a proper snapshot.

However, I did not deploy the snapshot version.

Could you try it now?

m4ttek commented 1 month ago

Yes, my test is now passing correctly

otaviojava commented 1 month ago

Thank you @m4ttek I am closing this issue.