SimpleFramework and ORMLite - Foreign Collections - cannot instantiate - android

We are using ORMLite 4.41 in our Android app and facing this issue:
Having defined one column in class A:
#Element(required = false)
#ForeignCollectionField(eager=true, orderColumnName="Name",
columnName="TestItems")
public ForeignCollection<TestItem> Test
In class B we have defined foreign column:
#DatabaseField(foreign=true, foreignAutoRefresh=true,
columnName="TestItems")
public TestSummary TestItemId;
When we run it and it receives the input XML, Serializer.read method is called where the output should be classes filled with foreign keys being initialized.
Unfortunately, it always stops with the exception:
org.simpleframework.xml.core.InstantiationException: Cannot instantiate interface
com.j256.ormlite.dao.ForeignCollection for field 'Test' public
com.j256.ormlite.dao.ForeignCollection xxxxxxxx.TestModel$TestSummary.Test
Is there any way how to use ForeignCollection together with SimpleFramework?

Try using Collection instead, and I think you should be using ElementList instead of Element.
#ForeignCollectionField(eager=true, orderColumnName="Name",
columnName="TestItems")
#ElementList(required = false)
public Collection<TestItem> Test

Related

android Room with kotlin value class?

I'm trying to use a room entity with a value class:
#JvmInline
value class UserToken(val token: String)
and the entity:
#Entity(tableName = TABLE_AUTH_TOKEN)
data class TokenEntity(
#PrimaryKey val id: Int = 0,
val token: UserToken
)
I get the following error:
error: Entities and POJOs must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).
public final class TokenEntity {
^
is it even possible to use room with value class? I couldn't find anything about this. thanks
See the comment from #CommonsWare. Android does not yet support value classes for Room.
The same holds true for the value classes introduced in kotlin 1.5. The type is not supported.
— Support Inline class in Room entity
Here is a possible explanation according to Kotlin Inline Classes in an Android World.
Looking to solve this you could try and add a TypeConverter for your Inline class, but since your Inline class is just the value it wraps when it’s compiled, this doesn’t make much sense and it doesn’t work as you’d expect even if you tried...
I’m just guessing it’s because this is a TypeConverter converting UserId to Int which is basically the same as Int to Int 😭. Someone will probably solve this problem, but if you have to create a TypeConverter for your Inline class then you are still plus one class for the count (multidex). 👎
I think yes if you can provide a type converter for it to change it to some sort of primitive data type (int , string, long ...etc) when it needs to be stored, and to change it back to its class type when it's fetched from database.
You can read about Type Converters from here
Referencing complex data using Room
other than that, your other class should be an entity and bind both your entities together using a Relation.
at least that's what I know about how to use Room.
UserToken always will have only one attribute? In this case, you don't need two classes, just use token: String directly on your entity class;
If you really need keep this class, you have two options:
TypeConverter, where you basically will convert the object into a json, and save as string in the database;
Relation, where you will transform the UserToken in a entity, and on TokenEntity save the tokenId.

Polymorphism in Android Room when extending a non-Entity class

My server is sending me a list of object type Parent, as List<Parent> parents. I need to save this list in Room and to do so I need a PrimaryKey. So what I try to do in room is create something like
#Entity
class Child(mApple:String,mOrange:String):Parent(mApple,mOrange){
#PrimaryKeyy(autoGenerate=true)
var id:Int=0
}
And here is what parent looks like:
//it's a java class and so to be complete I will recreate it in Java
class Parent{
private final String mApple;
private final String mOrange;
private final String mDerivative;
public Parent(String apple, String orange){
mApple=apple;
mOrange=orange;
mDerivation = someMagic(apple,orange)
}
//then a bunch of methods for dealing with the state variables
}
The reason I want to extend Child from Parent is because it makes working with both Child and Parent together easy. But room is not compiling and I suspect it has to do with this. Unfortunately, Kotlin is not pointing me to where the error is occuring.
Is the error really due to the fact that Parent is not an Entity and that derivative does not provide a setter?
How do I get Android Studio to show me more details about this bug, such as line number? (linked to related questions)
The only errors I am able to get from the build tab:
error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
error: Cannot find getter for field.
error: Cannot find setter for field.
error: Cannot figure out how to read this field from a cursor.
error: Cannot find getter for field.
error: Cannot find setter for field.

Android Room Database Nested Object Reference for array of objects

I have a class structure with
Class x {
int a;
int b;
Y[] yList;
}
Class Y {
int m;
int n;
}
I am using data binding, Room and Dagger. I am getting compilation error as 'cannot find class DatabindingComponent', possibly because Room doesn't allow persistent of Nested objects. To enable I used #Embedded annotation but still getting same error. But if I use #Ignore annotation indicating Room that do not process this field; compilation is happening successfully.
How to reference nested array of objects for Room Database without foreign key?
Please refer to
https://developer.android.com/topic/libraries/architecture/room.html#no-object-references
https://developer.android.com/reference/android/arch/persistence/room/Ignore.html
https://developer.android.com/reference/android/arch/persistence/room/Embedded.html.
How to reference nested array of objects for Room Database without foreign key?
If you do not want Y to be an #Entity with its own table, the only option that I know of is to use #TypeConverters:
Define two static methods with #TypeConverter that convert Y[] to and from some basic type (e.g., String, by using JSON)
Register the class holding those methods using #TypeConverters somewhere (e.g., on your RoomDatabase subclass)
This works using collection classes (e.g., List, Set). I would guess that it works with Java arrays (Y[]), though I have not tried it.

Mock model object without setters

I'm implementing tests on my Android app and I want to do unit tests on a model. The problem is that I do not have setters as the model is created with Realm or by parsing a CSV file (witch univocity csv parser).
So, how could I create a mocked object with valid values? I have something like that:
public class Content {
private String title;
private String description;
...
}
How could I generate a mocked Content object with a title and description data?
Thanks in advance
Use code below in your test class:
Field field = Content.class.getDeclaredField("str");
field.setAccessible(true);
field.set(yourObject, "some value");
yourObject is a instance of Content that you use in your test class.
But you shouldn't fill mock object - you should just define method result for mock object.
A word of warning: reflection has a lot of disadvantages; for example a simple name change for your fields will go unnoticed; and not lead to compiler errors but to failing unit tests later on.
This I suggest a different solution - providing a package-private or protected constructor that you can use to initialize your fields. Then you do not to use reflection; and at the same time, your "public" interface of that class doesn't change either, like:
public class Content {
// unit testing only
Content(String title, ... ) { ...
But of course, you have to do balancing - either you add that constructor that isn't required for production; or you go with not so robust reflection code!

Android ORMLite 4.38 allowGeneratedIdInsert causing IllegalStateException

I'm targeting Android 2.2 and newer. This error was generated on a device running 4.x. I am using ORMLite 4.38 libraries.
I need to guarantee every record instance is unique for any number of devices. I was happy to see that ORMLite supports UUIDs as IDs. I've created a UUID - id abstract base class for my database record definitions. allowGeneratedIdInsert is the perfect solution. But this feature seems to cause an 'IllegalStateException: could not create data element in dao'. I tested by removing this annotation, and no issue. Put it back in...same issue. Put the base class stuff in one record definition...same issue.
LogCat also reports:
Caused by: java.sql.SQLException: Unable to run insert stmt on object - objectid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx
public abstract class UUIDDaoEnabled<T> extends BaseDaoEnabled<T, UUID> {
//allowGeneratedIdInsert allows us to set UUID when this device db didn't create it
#DatabaseField(generatedId = true, allowGeneratedIdInsert=true)
private UUID id;
...
public void setUUIDFromSerializedSource(SerializedModelBinaryInputStream stream, Dao<T, UUID> dao) throws SQLException { //only place we can set UUIDs
if(id == null)
dao.refresh((T)this);
if(id != null)
throw new SQLException("Trying to set UUID on existing object");
id = stream.getCurrentUUID();
}
}
I'll specialize like so:
#DatabaseTable()
public class Type extends UUIDDaoEnabled<Type> { ... }
I can't explain this from the documentation for allowGeneratedIdInsert and generatedId. In fact the documentation for alloeGeneratedIdInsert says it overrides the default behavior of generatedId. It also says
This only works if the database supports this behavior
Yet, I have read in other posts that ORMLite 4.25 (?) and newer supports this behavior on Android devices. So, either that's not entirely true. Or I'm doing something stupid...anyone???
UPDATE: after thinking about it for a minute, I realized that neither allowGeneratedIdInsert support, nor inheritance can be the root cause, because I instantiate other objects based on the same abstract class. What I can't figure out is why one particular class is causing the issue. The only unique thing about the offending record type (compared to other types that create) is it is a many in a one to many, and it contains several to manies. Could these properties, combined with allowGenereatedIdInsert, be the root issue? Rather, I should ask, has anyone seen this issue in this circumstance?
UPDATE: nevermind the question. I can use updateId(...) instead of allowGeneratedIdInsert.
So I'm not sure about this but it looks to me that you are trying to insert an element twice into a table with the same UUID id. The exception is saying there is a constraints failure:
IllegalStateException: Could not create data element in dao
at BaseForeignCollection.add(BaseForeignCollection.java:57)
...
Caused by: SQLiteConstraintException: error code 19: constraint failed
If you call foreignCollection.add(...); it does the same thing as dao.create(...); -- and you can't do both of these with the same object. If you have an existing object that has already been created by the DAO and you want to associate it with another object, you should do something like:
// associate this object with another
existingObject.setForeignField(...);
// now update it in the db
existingObjectDao.update(existingObject);
You can't add it to the foreignField's foreign collection.
I had a similar problem. But it was caused by using create instead createOrUpdate to save the object.
It is also important to uninstall the application before changing this to ensure that the database has been removed and will not keep the old behavior.
Edit: createOrUpdate is very time expensive. It's better use just create with great amounts of data.
Edit 2:It is also bether to use a TransactionManager.callInTransaction.

Categories

Resources