Skip to content
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

Primitives and nested class problem with Class column type #3551

Open
Ryszard-Trojnacki opened this issue Feb 1, 2025 · 0 comments
Open

Comments

@Ryszard-Trojnacki
Copy link
Contributor

I'm unable to read (deserialize) Class type for nested class and primitives. Storing values to database works, but there is an error while retrieving/loading.

(This is not a big problem for me, because I just found this only in unit testing scenario)

In Java we can have nested classes:

public class ConfigDATest {

    // Nested class
    public static class TestConfig {
        public String name;
        public Long def;
        public BigDecimal value;
        public float f;
   }
}

When I tried to pass this class to Class type column:

public class DbConfig {
    @Column(name = "key", length = 128) @Id @Index(unique = true)
    private String key;

    @Column(name = "type")
    private Class<?> type;
}

then it is OK, to store it:

+------------------------------------------------------+
|type                                                  |
+------------------------------------------------------+
|java.lang.Integer                                     |
|test.ConfigDATest.TestConfig                          |
+------------------------------------------------------+

But when Ebean is loading this then there is an error:

Caused by: jakarta.persistence.PersistenceException: Error readSet on test.tables.DbConfig.type
	at io.ebeaninternal.server.deploy.BeanProperty.readSet(BeanProperty.java:527)
	at io.ebeaninternal.server.deploy.BeanProperty.readSet(BeanProperty.java:536)
	at io.ebeaninternal.server.query.SqlBeanLoad.load(SqlBeanLoad.java:63)
	... 21 more
Caused by: jakarta.persistence.PersistenceException: Unable to find Class test.ConfigDATest.TestConfig
	at io.ebeaninternal.server.type.ScalarTypeClass.parse(ScalarTypeClass.java:42)
	at io.ebeaninternal.server.type.ScalarTypeClass.convertFromDbString(ScalarTypeClass.java:24)
	at io.ebeaninternal.server.type.ScalarTypeClass.convertFromDbString(ScalarTypeClass.java:10)
	at io.ebean.core.type.ScalarTypeBaseVarchar.read(ScalarTypeBaseVarchar.java:63)
	at io.ebeaninternal.server.deploy.BeanProperty.readSet(BeanProperty.java:521)
	... 23 more
Caused by: java.lang.ClassNotFoundException: test.ConfigDATest.TestConfig
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:421)
	at java.base/java.lang.Class.forName(Class.java:412)
	at io.ebeaninternal.server.type.ScalarTypeClass.parse(ScalarTypeClass.java:40)
	... 27 more

The problem is with io.ebeaninternal.server.type.ScalarTypeClass it uses to serialize: Class#getCanonicalName and to load Class#forName.
This construction for nested class will not work:

        Class.forName(TestConfig.class.getName());   // Works
        Class.forName(TestConfig.class.getCanonicalName());  // Error

This will also not work for primitive types:

        Class.forName(int.class.getName());  // Error
        Class.forName(int.class.getCanonicalName());  // Error

Example code:

        var q=new DbConfig();
        q.setType(int.class);
        q.setKey("int_test");
        db.insert(q);

        var x=db.find(DbConfig.class, "int_test");

Here is error:

Caused by: jakarta.persistence.PersistenceException: Unable to find Class int
	at io.ebeaninternal.server.type.ScalarTypeClass.parse(ScalarTypeClass.java:42)
	at io.ebeaninternal.server.type.ScalarTypeClass.convertFromDbString(ScalarTypeClass.java:24)
	at io.ebeaninternal.server.type.ScalarTypeClass.convertFromDbString(ScalarTypeClass.java:10)
	at io.ebean.core.type.ScalarTypeBaseVarchar.read(ScalarTypeBaseVarchar.java:63)
	at io.ebeaninternal.server.deploy.BeanProperty.readSet(BeanProperty.java:521)

I can make PR with fix for this.

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

1 participant