Android-OrmLiteContentProvider icon indicating copy to clipboard operation
Android-OrmLiteContentProvider copied to clipboard

IllegalArgumentException: Proper ID is not defined for field. when id is in super object

Open blazsolar opened this issue 11 years ago • 19 comments

When creating TableInfo only fields of top level class are used. In my case I have id set in super class and i get error because ID field was not found.

Caused by: java.lang.IllegalArgumentException: Proper ID is not defined for field.
        at com.tojc.ormlite.android.framework.TableInfo.<init>(TableInfo.java:109)
        at com.tojc.ormlite.android.framework.MatcherController.addTableClass(MatcherController.java:212)
        at com.tojc.ormlite.android.framework.MatcherController.add(MatcherController.java:87)

It should also check for fields in all super classes.

blazsolar avatar Feb 21 '14 09:02 blazsolar

For me, this is caused by proguard.. and I don't know how to pass it

rodriamaro avatar Apr 08 '14 15:04 rodriamaro

Thank you for reporting! I plan to check it.

jakenjarvis avatar Apr 09 '14 05:04 jakenjarvis

Hi @blazsolar, Please give up this. ORMLite also do not support inheritance class apparently.

Please refer to this.

  • http://stackoverflow.com/questions/10188414/does-ormlite-support-inheritance
  • http://stackoverflow.com/questions/10290207/how-do-i-properly-annotate-inheritance-classes-using-ormlite
  • http://stackoverflow.com/questions/12743171/how-does-ormlite-manage-inheritance-between-java-classes

I was also confirmed source code of ORMLite, but there was no significant difference in the acquisition method.

  • ORMLite core https://github.com/j256/ormlite-core/blob/master/src/main/java/com/j256/ormlite/field/DatabaseFieldConfig.java#L512
  • OrmLiteContentProvider https://github.com/jakenjarvis/Android-OrmLiteContentProvider/blob/Ver1.0.3/ormlite-content-provider-library/src/com/tojc/ormlite/android/framework/TableInfo.java#L87

getAnnotation does not seem to work well...(Argument of the annotation can not be read.) I think Gray Watson gave up the implementation for this reason.

Experimental results of me: Branch 'Issue15' https://github.com/jakenjarvis/Android-OrmLiteContentProvider/tree/Issue15

jakenjarvis avatar May 04 '14 14:05 jakenjarvis

Hi @phantomis Perhaps, it is a different problem... If you do not set properly, the annotation will get deleted.

jakenjarvis avatar May 04 '14 14:05 jakenjarvis

For me the reason of this exception is different. I have a model class @DatabaseTable() @DefaultContentUri(authority = "co.wecommunicate", path = "group") @DefaultContentMimeTypeVnd(name = "co.wecommunicate.provider", type = "group") public class Group { @DatabaseField(id = true, columnName=BaseColumns._ID) public long id;

My ID field is not generated locally and thus I don't use "generatedId=true". This is the reason why I get the same exception.

suntehnik avatar May 08 '14 11:05 suntehnik

@suntehnik oops, sorry. What you pointed out is another issue. Please refer to the #11 This thread is a topic of when using inheritance class.

jakenjarvis avatar May 08 '14 17:05 jakenjarvis

This is crap! OrmLite do supports @DatabaseField on superclasses, and properly detects them.

You only need to add 2 lines to support them into your TableInfo class:

diff --git a/src/com/tojc/ormlite/android/framework/TableInfo.java b/src/com/tojc/ormlite/android/framework/TableInfo.java
index 9a66f58..5064e75 100644
--- a/src/com/tojc/ormlite/android/framework/TableInfo.java
+++ b/src/com/tojc/ormlite/android/framework/TableInfo.java
@@ -74,6 +74,7 @@ public class TableInfo implements Validity {
         SortedMap<Integer, String> defaultSortOrderMap = new TreeMap<Integer, String>();

         this.idColumnInfo = null;
+        while(tableClassType != null) {
             for (Field classfield : tableClassType.getDeclaredFields()) {
                 if (classfield.isAnnotationPresent(DatabaseField.class)) {
                     classfield.setAccessible(true); // private field accessible
@@ -110,6 +111,8 @@ public class TableInfo implements Validity {

                 }
             }
+            tableClassType = tableClassType.getSuperclass();
+        }

         if (this.idColumnInfo == null) {
             // @DatabaseField(columnName = _ID, generatedId = true)

Or you can download my TableInfo here.

renaudcerrato avatar Feb 25 '15 01:02 renaudcerrato

@nono240 Oh, I didn't have that idea! thanks. I was trying to access from a subclass in the field of the superclass. I have not yet tried your code, but would I implement it in the next version(Ver1.0.5).

jakenjarvis avatar Feb 26 '15 10:02 jakenjarvis

@jakenjarvis : my code was only a proof of concept. You'll probably have to slightly improve your code to correctly handle fields visibility as ormlite do: you must ignore private fields from superclasses.

renaudcerrato avatar Feb 27 '15 03:02 renaudcerrato

@nono240 We should read all fields where a @DatabaseField annotation was specified. So I judged, there is no need to ignore a private field. I think your concept is not wrong. :)

jakenjarvis avatar Feb 28 '15 16:02 jakenjarvis

No, OrmLite ignore private fields on superclasses.

renaudcerrato avatar Feb 28 '15 18:02 renaudcerrato

He said:

private C cfield;

Will be ignored by ORMLite by default. The reason is there is no annotation given for the cfield. If you don't specify annotation @DatabaseField for an attribute, that will be ignored.

and

ORMLite by default investigates all base class fields and will find the fields that have annotations.

That's Access level modifiers does not matter.(Of course, the private fields are ignored by default. However, We should read all fields where a @DatabaseField annotation was specified.) I have judged properly @DatabaseField annotation.

https://github.com/jakenjarvis/Android-OrmLiteContentProvider/blob/b913d92afbe42e4cf82858fe8eae1c75a445fad1/ormlite-content-provider-library/src/com/tojc/ormlite/android/framework/TableInfo.java#L82

    while(targetTableClassType != null) {
        for (Field classfield : targetTableClassType.getDeclaredFields()) {
            if (classfield.isAnnotationPresent(DatabaseField.class)) {

jakenjarvis avatar Mar 01 '15 03:03 jakenjarvis

Ok, but it could be worth to give it a try.

Thanks for great library.

renaudcerrato avatar Mar 01 '15 07:03 renaudcerrato

Any update on this?

renaudcerrato avatar Mar 27 '15 12:03 renaudcerrato

@renaudcerrato Sorry and thanks for waiting. I for a while, was very busy. I during the holidays of several days, worked on this project.

Result of verifying the Superclass of ORMLite: OrmLite is not ignore private fields on superclasses. All of the fields that @DatabaseField Annotation has been added, ORMLite will treat it as a valid column.

The reason is because the test code of testDoORMLiteCanBeAccessToThePrivateMembersOfSuperclass() has been finish successfully.

Also, I was searching for Modifier.isPrivate from within the source code of ORMLite, I could not find it. Field is required Modifier.isPrivate is in order to determine whether it is private. For this reason, I was convinced that it is not aware of the access modifier in ORMLite.

Then, I have uploaded the 1.0.5-SNAPSHOT. If possible, please try using. :)

jakenjarvis avatar May 06 '15 15:05 jakenjarvis

1.0.5-SNAPSHOT sounds fine =) Any official release?

renaudcerrato avatar Oct 05 '15 09:10 renaudcerrato

Hey mate - any chance of a release?

thorinii avatar Nov 23 '15 02:11 thorinii

Waiting for official release of this. Thanks

psamim avatar Dec 06 '15 06:12 psamim

Might also be because you didn't use a column name containing _ID like this :

@DatabaseField(columnName = BaseColumns._ID, id = true)

alois-git avatar May 07 '16 21:05 alois-git