-
Notifications
You must be signed in to change notification settings - Fork 166
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
Improve EOAttribute's value factory method to accept numeric arguments #962
Improve EOAttribute's value factory method to accept numeric arguments #962
Conversation
When creating custom prototypes, one can configure a factory method to convert the attribute's value from/to a string or byte array. It's not possible to use an integer or a float value as an argument/return type, though, even if you set a value type of integer ("i") or float ("f"). Trying to fetch/save an entity containing an attribute using this prototype will throw the following exception: ``` Error encountered converting value of class MyEnum to type specified in attribute 'myEnumAttribute' of entity 'MyEntity'. Conversion exception is : EOAttribute adaptorValueByConvertingAttributeValue(Object): Unable to convert value of class java.lang.Integer for attribute 'enumAttribute' in entity 'MyEntity' to adaptor type EOAttribute.AdaptorBytesType. Check the signature of the conversion method MyEnum.toInteger(). ``` This pull request adds the ability to configure a factory method that receives numeric values as an argument and a conversion method that returns numeric values. For instance, it allows the creation of enum prototypes that translate from/to a number in the database. I'm testing this change using an Oracle database, and everything has been working fine so far. I'll try to test it on other databases as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all looks fine, though I am having trouble testing it. I have an entity with a custom Type
enum attribute, which I've changed over to use int4
as the external type (PostgreSQL) from the javaEnum
prototype. I've added factory and conversion methods on Type
:
public static Type fromInt(int i) {
for (Type t : values()) {
if (t.ordinal() == i) {
return t;
}
}
return null;
}
public int toInt() {
return ordinal();
}
Shouldn't that be enough to get me there? I can successfully save a Type
value to the database, but I can't read it back. Instead, I'm getting a ClassCastExcecption
from the template method:
java.lang.ClassCastException: java.lang.Integer cannot be cast to net.logicsquad.juno.model.person.Employer$Type
at net.logicsquad.juno.model.person._Employer.type(_Employer.java:187)
Factory method doesn't seem to get called. Any thoughts?
@paulhoadley It's broken. I'm already working on a fix. Thanks for taking the time to test it. |
…tabase Complements the previous commit by converting numeric values from the database to custom types using an attribute's `valueFactoryClass` and `valueFactoryMethod` properties. The parameter type passed to the `valueFactoryMethod` adheres to the `valueType` configured in the EOModel. It must be a reference type (java.lang.Integer, java.lang.Long, etc.), not a primitive type. The `DateJDBCColumn` class was deprecated in favor of `ERXEnhancedJDBCColumn` to accommodate this change. I'm not sure about the impact of this change on Wonder users, but it doesn't seem too risky. Please, let me know if I'm overlooking something.
@paulhoadley I added the missing parts to this pull request. I tested the previous solution without ever calling the attribute getter method—shame on me. 🤦♂️ I'll do another round of tests this week to ensure I'm not missing something. Thanks again for taking the time to review my work. 😀 I'm still not happy with one tiny detail, though. Suppose the value factory method has a primitive type parameter (instead of a reference type). In that case, one gets an exception like the following:
This misleading error message may take lots of time for the inattentive to figure out the solution. Maybe we should log a warning before throwing the |
I'm running into that right now. None of |
This is not the final solution. It would be great to fix it in the `NSSelector` class instead. 🤔
@paulhoadley According to the screenshot you shared above, the value type of your property is
I reran the tests with a nested enum type (as your example) and had no problems either. I added a new commit to this pull request to improve the error message temporarily. Could you please try again and let me know if it works? |
Thanks @hprange—works perfectly. Perhaps I had botched something myself when testing yesterday. I think this is ready to go. |
When creating custom prototypes, one can configure a factory method to convert the attribute's value from/to a string or byte array. It's not possible to use an integer or a float value as an argument/return type, though, even if you set a value type of integer ("i") or float ("f"). Trying to fetch/save an entity containing an attribute using this prototype will throw the following exception:
This pull request adds the ability to configure a factory method that receives numeric values as an argument and a conversion method that returns numeric values. For instance, it allows the creation of enum prototypes that translate from/to a number in the database.
I'm testing this change using an Oracle database, and everything has been working fine so far. I'll try to test it on other databases as well.