I have a base class that stores a field called updatedAt and a setter setUpdatedAt. There is a child class Child. I know that Firebase cannot find setter in the parent classes, so I just define the setter setUpdatedAt again in Child, but I am still getting "No setter/field for updatedAt found on class xxx.Child"
My database json has that "updatedAt" field.
Sample code:
public abstract class Model {
private String mId;
private long mUpdatedAt;
public String getId() {return mId;}
public void setId(String id) { mId = id;}
public long getUpdatedAt() {return mUpdatedAt;}
public void setUpdatedAt(long updatedAt) { mUpdatedAt = updatedAt;}
}
public abstract class Child extends Model {
private String mCreator;
public String getCreator() {
return mCreator;
}
public void setCreator(String creator) {
mCreator = creator;
}
// having the following or not does not change the outcome
public void setUpdatedAt(long updatedAt) {
super.setUpdatedAt(updatedAt);
}
}
// then somewhere else, do this
new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
model = dataSnapshot.getValue(Child.class);
}
And I got "No setter/field for updatedAt found on class xxx.Child" and "No setter/field for id found on class xxx.Child" when "model = dataSnapshot.getValue(Child.class);" is executed.
For actual code sample, see github MinFirebaseApp. In MainActivity, you can see the two methods "createEmployee" and "showEmployee", which shows how an employee is created in "createEmployee" and the same employee is fetched in "showEmployee". Using the code, you can reproduce it by (after you change the package id to yours):
Put the google-services.json file in the app folder
Start the app
Click on "login" to sign in anonymously
Click on "create employee", see that the employee is created
Go to console.firebase.google.com to check that the employee is
created with id, name and updatedAt
Click on "show employee" from the app, see the "updatedAt" and "id"
are not set.
Check the logcat to find something like "No setter/field for id found" and "No setter/field for updatedAt found"
You'll need to call through to all of your setters in the subclass. You may as well do the getters too. Right now you're just doing setUpdatedAt(), but there is setId() as well. This is a bug in the Android client library for Realtime Database, but the team is working on a fix that will be available in the future.
Related
My firestore document I'm trying to serialize contains a map of maps of strings like this:
Some example document in my collection:
id: "someId1" (String)
vouchers (Map)
voucher_with_some_random_id_1 (Map)
name: "name 1"
description: "description 1"
voucher_with_some_random_id_2 (Map)
name: "name 2"
description: "description 2"
The problem I have with creating a matching POJO class is that the field names of the inner maps are not constant since the amount of vouchers in my vouchers Map changes from time to time.
For documents with unknown custom IDs there is a solution (Annotation #DocumentId)
But I couldn't find an annotation that works for maps.
My latest failed attempt:
public class MyPOJO {
public MyPOJO() {
}
public String id;
public VouchersPOJO vouchers;
}
public class VouchersPOJO {
public VouchersPOJO() {
}
public List<ActualVoucherPOJO> vouchers;
}
public class ActualVoucherPOJO {
public ActualVoucherPOJO() {
}
public String name, description;
}
MyPOJO x = documentSnapshot.toObject(MyPOJO.class);
As you already say voucher is a Map, so that's what you should use in your Java class too:
public class MyPOJO {
public String id;
public Map<String,Voucher> vouchers;
}
public class Voucher {
public String name, description;
}
In this case, I don't think toObject() is going to work on the entire data structure. It's not meant for handling dynamic/variable data. Instead, you will have to manually:
Iterate the entries of the Map of Maps that come back from the snapshot
Convert each map to the individual objects
Assemble the final MyPOJO object using what you found in the maps
I have a RealmObject named Activity:
public class Activity extends RealmObject {
#PrimaryKey
public String token;
public RealmList<String> names;
public RealmList<String> units;
public RealmList<Float> points;
}
When querying, I want to return all Activity items which their names list contains some value.(not a exactly matches, much like a SQL like statement.)
I tried
val allActivities = realm.where(Activity::class.java).contains("names", str).findAllAsync()
But I got an exception:
java.lang.IllegalArgumentException: Invalid query: field 'names' in
class 'Activity' is of invalid type 'STRING_LIST'.
I have tried How do I query RealmObject that have RealmList that contains specified value, but the type in the mentioned RealmList is extending RealmObject, while String is not. Any thoughts?
I have a model class to store Firebase User information. Inside of the model class I have a HashMap to store all of the data inside. Once I have stored the data, the I push the Hashmap into the Firebase database. The values store fine, but I cannot access the values. Every time I try to access them, I get an error saying that I am attempting to invoke a virtual method on a null object reference.
mDatabase.child("users").child(mUserId).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot ChildSnapshot, String s) {
// These two lines of code give the error.
User author = ChildSnapshot.child("profile").getValue(User.class);
String author_username = author.getUsername();
These give me the error. I am attempting to grab data from the child of the snapshot. Why is this giving me an error? Is there a better way to do this?
JSON Firebase snapshot:
Model class:
//TODO model class for the user. This way I can set the values for each user. I will be adding more values in the future.
public class User {
public HashMap<String, String> hashMap = new HashMap<String,String>();
public User() {
}
public User(String username) {
hashMap.put("username",username);
}
public String getUsername(){
return hashMap.get("username");
}
}
In case somebody else was struggling with this issue, I wanted to give an answer. Inside of my ChildEventListener, the profile is the key in this situation so when I use ChildSnapshot.child("profile").getValue(User.class) it returns a null value. Also, (I'm not quite sure why this is) the value of the username was stored in a different class called User_message which was used to store the message. so my updated code looks something like this:
mDatabase.child("users").child(mUserId).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot ChildSnapshot, String s) {
User_message author = ChildSnapshot.getValue(User_message.class);
String author_username = author.getUsername();
I was facing the same problem and spent more than 5 hours. I added Default Constructor of the model and this solves my problem.
public class User {
public String email;
public String name;
public User() {
}
public User(String email, String name) {
this.email = email;
this.name = name;
}}
I hope this will help you. Thanks
I know how to parse a simple DataSnapshot object to any Java class using public T getValue (Class<T> valueType). But after the Firebase 3.0 I am not able to parse the following data to my Java Class, as it contains a custom type instance for which I'm receiving NULL.
NOTE: The same logic was working fine before Firebase 3.0. I suppose its because now Firebase is using GSON instead of JACKSON. Please correct me if I'm wrong
DATA:
{
"address" : "DHA karachi",
"addresstitle" : "DHA karachi",
"logoimage" : {
"bucketname" : "test2pwow",
"id" : "zubairgroup",
"mediaType" : "image/png",
"source" : 1,
"url" : "https://pwowgroupimg.s3.amazonaws.com/zubairgroup1173.png?random=727"
},
"title" : "zubairghori"
}
Group.java
public class Group {
public String address;
public String addresstitle;
public LogoImage logoimage;
public Group(){}
}
LogoImage.java
public class LogoImage {
public String bucketname;
public String id;
public LogoImage(){}
}
Code that read:
Group group = datasnapshot.getValue(Group.class);
It doesn't cast LogoImage part of the database into the logoimage object. We always retrieve null in the logoimage object.
public T getValue(Class valueType)
1.The class must have a default constructor that takes no arguments
2.The class must define public getters for the properties to be assigned. Properties without a public getter will be set to their default value when an instance is deserialized
Check it from:
this source It'll help you
detail
I'm not sure why that is causing problem for you. This code works fine for me with the data you provided:
DatabaseReference ref = database.getReference("37830692");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Group group = dataSnapshot.getValue(Group.class);
System.out.println(group);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I had the same problem. I solved it by providing not only getters for all the values, but setter too. Hope this helps.
I had the same problem and solved it by making sure that the arguments of the constructor are spelled the same than the elements saved at Firebase. My mistake was that I was setting the key of Firebase with Uppercase letters and object arguments with lowercase letters.
I am using the .Net backend for Azure Mobile Service. I can successfully run the following query, and it returns all items from the database however it only returns the items with their IDs and no other columns are returns, they are all set to null
TableName.execute(new TableQueryCallback<ClassName>() {
#Override
public void onCompleted(List<ClassName> result, int count,
Exception exception, ServiceFilterResponse response)
So do I need to supply a select filter or should I be using the TableOperationsCallback? There is no error, it just returns all the columns as null except for the id column
Thanks
Make sure that the casing of the fields match between the client and the server. By default the .NET backend will make all properties camel-case, so that if you have this class:
public class Person : EntityData
{
public string Name { get; set; }
public int Age { get; set; }
}
Then the JSON response in a GET operation will look something like this:
[
{ "id":"the-first-id", "name":"John Doe", "age":33 },
{ "id":"the-first-id", "name":"Jane Roe", "age":34 }
]
So you need to define in your Android application a type where the field is either named in lower case, or properly tagged with the #SerializeName annotation, like in the example below (you don't need to do that for the id property as it's special-cased by the SDK):
public class Person {
#SerializedName("id")
public String Id;
#SerializedName("name")
public String Name;
#SerializedName("age")
public String Age;
}