Unable to find generated Parcelable class with Realm - java

I am trying to pass realm object with bundle and I used Parcel library
This is my realm model class.
Album.java
#Parcel
public class Album extends RealmObject implements Serializable {
#PrimaryKey
public String id;
public String upc;
public String albumName;
public String albumArtUrl;
public String artistName;
public String genre_id;
public String genreName;
public String price;
public String releaseYear;
public int explicit;
public RealmList<Song> songs = new RealmList<>();
}
And this is Song.java.
#Parcel
public class Song extends RealmObject implements Serializable {
#PrimaryKey
public String id;
public String isrc;
public String songName;
public String artistName;
public String album_id;
public String albumArtUrl;
public String genre_id;
public String genreName;
public String releaseYear;
public String price;
public String lyrics;
public String demo;
public int explicit;
}
When I try to pass album object in bundle like that,
b.putParcelable("album", Parcels.wrap(album));
I am having that error.
Unable to find generated Parcelable class for com.devhousemyanmar.juketrill.models.Album, verify that your class is configured properly and that the Parcelable class com.devhousemyanmar.juketrill.models.Album$$Parcelable is generated by Parceler.
please help me to solve this.

If you check the documentation, it has a section dedicated to using Parceler.
// All classes that extend RealmObject will have a matching RealmProxy class created
// by the annotation processor. Parceler must be made aware of this class. Note that
// the class is not available until the project has been compiled at least once.
#Parcel(implementations = { PersonRealmProxy.class },
value = Parcel.Serialization.BEAN, // <-- requires getters/setters if set
analyze = { Person.class })
public class Person extends RealmObject {
// ...
}
But what's worth noting is that you don't need to specify implementations = {PersonRealmProxy.class} if you use realm.copyFromRealm(song) before passing it to Parcels.wrap(). You'll need to do that anyways if you want to use field values instead of bean serialization strategy, anyways.
Also, you might need a RealmList parceler configuration.

Related

MongoDB spring repository - abstract class as field "Class is abstract"

I'm getting error when spring mongo template reading object from DB: "Class is abstract". This is because internal field in document is abstract type.
in my case classes looks like:
public abstract class Context {
private String name;
}
public class AContext {
private String aData;
}
public class BContext {
private String bData;
}
#Document
#TypeAlias("Task")
public class Task {
#Id
private String id;
private String name;
private List<Context> contexts;
}
How can I fix thiss issue ?

Java Gson ClassCastException

I am building a Java Servlets 3.0 REST API and using Gson to serialize some data to json.
I get this error, though:
java.lang.ClassCastException: za.co.a.models.tables.sybase.Family cannot be cast to java.util.Map
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:145)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.google.gson.Gson.toJson(Gson.java:704)
at com.google.gson.Gson.toJson(Gson.java:683)
at com.google.gson.Gson.toJson(Gson.java:638)
at com.google.gson.Gson.toJson(Gson.java:618)
at za.co.a.helpers.JsonHelper.toJson(JsonHelper.java:33)
at za.co.a.models.tables.sybase.ActiveProcesses.saveProcess(ActiveProcesses.java:57)
My code is as follows:
#Table(name = "E_FAMILY")
public class Family extends IGenericModel <Family>
{
#Id
public BigDecimal EMPLOYEE_ID;
#Id
public BigDecimal FAMILY_ID;
#Id
public BigDecimal COMPANY_ID;
public String FIRSTNAME;
public String SECONDNAME;
public String SURNAME;
public String RELATION;
public int RELATION_ID;
public String MED_DEPENDENT_YN;
public String TAX_DEPENDENT_YN;
public String GENDER;
public Date BIRTHDATE;
public String TEL_HOME;
public String TEL_WORK;
public String TEL_CELL;
public String E_MAIL;
...
}
The calling code:
public String toJson(Object obj)
{
return gson.toJson(obj);
}
Family, in this case is field in a larger class, however, I'm not having any problems with any other fields or any other classes that are similar. This is the first time, in the year I've been developing this, that this error comes up. Is there a limit to the size or complexity of class Gson can serialize? Or what can I check to see what's causing the error? Or is there a way change this specific mapping, (though I don't understand why Google is trying to map this class to Map)?
Thanks
Sethmo
Edit Including class hierachy
IGenericModel and IGenericReadOnlyModel only contain functions. IModel has 2 members, but I've added it as part of an ExclusionStrategy so that those members don't get serialized.
public class IGenericModel<T> extends IGenericReadOnlyModel
{
}
public class IGenericReadOnlyModel<T> extends IModel
{
}
public class IModel
{
protected String dbEngine;
protected IDatabase db;
}
Edit rest of the code
Ok, the class that holds Family is quite large and mostly full of Strings, Dates and Booleans and ints. Where Family comes in is here, the two objects are passed from the front-end and represent the old and new values (users can edit, add and delete family members in the UI, then submit those lists).
public abstract class IWebProcess extends IModel
{
protected Object _OldValue;
protected Object _NewValue;
}
Once submitted (as JSON from the UI), it's serialized:
Type familyType = new TypeToken<LinkedList<Family>>(){}.getType();
LinkedList<Family> oldFamily = gson.fromJson(oldFamilyJson, familyType);
LinkedList<Family> newFamily = gson.fromJson(newFamilyJson, familyType);
Then, the concrete class is then initialized:
IWebProcess family = WebProcess_FamilyRequisition(oldFamily,newFamily,...,...,...)
then, in the constructor of WebProcess_FamilyRequisition, I call super(oldFamily, newFamily) and then in the constructor of IWebProcess:
this._OldValue = oldFamily
this._NewValue = newFamily
I do all this casting because I save the new values to the DB first, before serializing the entire WebProcess to the DB. I've made _OldValue and _NewValue Objects because this is a base class for 8 other classes that work the same and they serialize just fine.

To define an object in a constructor in Serializable class

I have a JSON response like below image, and I have made a serializable class named as Project
In the image, I have two objects (emergency_contact, and secondary_owner) inside my an array of one object. I'm trying to figure out whether what to do in order to define the object, since I want that details to be present inside my constructor.
I have done this so far:
public class Project implements Serializable {
public int id;
public String name;
public String additional_information;
//Now what to do Emergency contact
public Project(int id, String name, String additional_information){
}
}
I have thought of doing this, public EmergencyContact emergency = new EmergencyContact(param1, param2).
And make a new class named as EmergencyContact, and do a getter and setter for the params. But after doing this, I'm still confused, how would I define it my constructor?
I know I'm close, but I need some help on that.
Sure. You need to have a:
public class EmergencyContact implements Serializable {
public String name;
public String number;
public EmergencyContact(String name, String number){
// assign fields
}
}
and one for the owner:
public class EmergencyOwner implements Serializable {
public String name;
public String number;
public EmergencyOwner(String name, String number){
// assign the fields
}
}
then in your Project class you can add fields of these classes:
public class Project implements Serializable {
public int id;
public String name;
public String additional_information;
public EmergencyContact emergency_contact;
public EmergencyOwner emergency_owner;
public Project(int id, String name, String additional_information, EmergencyContact emergency_contact, EmergencyOwner emergency_owner){
// assign the fields here as well
}
}
that's it. If that's an answer to the question consider to delete this question as it is a duplicated on a 100% :)
As a note, to be correctly from the point of clean code parameters, the fields should be private in a class, and use setters / getters to set/retrieve values from/to those fields.
public class Project implements Serializable {
private int id;
private String name;
private String additional_information;
private EmergencyContact emergency_contact;
private SecondaryOwner secondary_owner;
public Project(int id, String name, String additional_information, EmergencyContact emergencyContact, SecondaryOwner secondaryOwner){
this.id = id;
this.name = name;
this.additional_information = additional_information;
this.emergency_contact = emergencyContact;
this.secondary_owner = secondaryOwner;
}
}
You will define the other two classes the same way. Now, you are probably confused about the constructor of EmergencyContact & SecondaryOwner classes.. You can device both default constructors (without parameters) and a custom one(with parameters to it, just as the one above). If you use the default constructor, make sure to set values to the fields in the object, as following :
EmergencyContact emergencyContact = new EmergencyContact();
emergencyContact.setName("the name");
emergencyContact.setNumber("a number");
then you can use this object in the constructor of Project class
I hope it was clear enough, for any other clarifications feel free to ask.
Happy coding <3

How to deserialize JSON Array contained an abstract class without modifying a parent class?

I'm trying to deserialize JSON Array, which is persisted into my MongoDB, to a Java object by using Jackson. I found many tutorials mentioned to handle this polymorphism by adding:
#JsonTypeInfo(use=Id.CLASS,property="_class")
to a Super-class. However, in my case, I can't be able to modify the Super-class. So, are there some solutions to solve it without modifying the Super-class? Here is my code:
public class User {
#JsonProperty("_id")
private String id;
private List<Identity> identities; // <-- My List contains objects of an abstract class; Identity
public User(){
identities = new ArrayList<Identity>();
}
public static Iterable<User> findAllUsers(){
return users().find().as(User.class); // Always give me the errors
}
/*More code*/
}
It always give me the error - Can not construct instance of securesocial.core.Identity, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information.
You can use #JsonDeserilize annotation to bind a concrete implementation class to an abstract class. If you cannot modify your abstract class you can use the Jackson Mix-in annotations to tell Jackson how to find the implementation class.
Here is an example:
public class JacksonAbstract {
public static class User {
private final String id;
private final List<Identity> identities;
#JsonCreator
public User(#JsonProperty("_id") String id, #JsonProperty("identities") List<Identity> identities) {
this.id = id;
this.identities = identities;
}
#JsonProperty("_id")
public String getId() {
return id;
}
public List<Identity> getIdentities() {
return identities;
}
}
public static abstract class Identity {
public abstract String getField();
}
#JsonDeserialize(as = IdentityImpl.class)
public static abstract class IdentityMixIn {
}
public static class IdentityImpl extends Identity {
private final String field;
public IdentityImpl(#JsonProperty("field") String field) {
this.field = field;
}
#Override
public String getField() {
return field;
}
}
public static void main(String[] args) throws IOException {
User u = new User("myId", Collections.<Identity>singletonList(new IdentityImpl("myField")));
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Identity.class, IdentityMixIn.class);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(u);
System.out.println(json);
System.out.println(mapper.readValue(json, User.class));
}
}

Jackson mapper with polymorphimsm

I have classes in following structure :
class Member {
public long id;
public String name;
public String type;
public Pet pet;
};
public abstract class Pet {
}
public CatPet extends Pet {
public int age;
public String color;
}
public DogPet extends Pet {
public int age;
public String breed;
}
I have to serialize the objects of class Member into JSON string and vice-versa. Can I somehow make the serialization such that serialization of object Pet in class Member will be dependent on member 'type'. If type = "cat" it should serialize/deserialize using class CatPet.
Yes, you typically use annotation #JsonTypeInfo on base class, to indicate how polymorphic type information is to be used. And with that, things will "just work".

Categories