10

I'm using Google's firebase-database SDK for Android, v9.0.1. I have my app hooked up to Firebase and can read and write data at various locations.

However, I cannot get a specific boolean field to bind using dataSnapshot.getValue(PingReport.class) and I keep getting an error in my logs that says No setter/field for isUp found on class com.myapp.PingReport when the field clearly exists in my model.

Here's the JSON in the Firebase database:

{
    "durationMs": 364,
    "isUp": true,
    "timestampMillis": 1464916019971
}

and here's the model class:

public class PingReport {

    private long durationMs;
    private boolean isUp;
    private long timestampMillis;

    public PingReport() {
        // required by Firebase
    }

    public PingReport(long durationMs, boolean isUp, long timestampMillis) {
        this.durationMs = durationMs;
        this.isUp = isUp;
        this.timestampMillis = timestampMillis;
    }

    public long getDurationMs() {
        return durationMs;
    }

    public boolean isUp() {
        return isUp;
    }

    public long getTimestampMillis() {
        return timestampMillis;
    }
}

If I call getDurationMs() or getTimestampMillis() the correct values are returned, but the value returned from isUp() is always false. I have tried different combinations of naming it up and isUp and mUp and adding setters setUp(boolean up) and setIsUp(boolean isUp), but nothing seems to work. The documentation for the Android SDK not very detailed. Is there some trick or detail I'm overlooking?

Jschools
  • 2,698
  • 1
  • 17
  • 18
  • 2
    From whatever code you posted, there should be no problem as such. I myself have used ``boolean` in similar POJO without any issue. Please check other parts of the code if the value is correctly passed. – Shadab Ansari Jun 03 '16 at 22:57

8 Answers8

46

If your boolean field is named isUp, then the getter must be named isIsUp() or getIsUp(). Alternatively, if you want a getter named isUp, the field name would be up.

Bob Snyder
  • 37,759
  • 6
  • 111
  • 158
  • 3
    The JavaDoc at https://firebase.google.com/docs/reference/android/com/google/firebase/database/DataSnapshot.html states: "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" Changing the getter from the conventional form, public boolean isUp(), to public boolean getIsUp() solved the issue. I don't like it, but that's the solution. – Jschools Jun 07 '16 at 18:19
  • Another option not described in the current documentation is to use public fields. No getter method is needed for a public field. See this [related question/answer](http://stackoverflow.com/questions/37512895/are-getter-methods-really-needed-for-class-stored-using-databasereference-setval). – Bob Snyder Jun 07 '16 at 19:02
  • 5
    This is cancerous. Just wasted 2.5 hours of my life on this that I won't get back :( – Parth Bhoiwala Oct 24 '18 at 04:48
  • 2
    That's weird behavior by Firebase :( but that solved my issue after hours wasted. Thanks man. Upvoted. – Perry Apr 20 '19 at 17:46
  • thank you very much you really helped me alot – Mosa Mar 07 '21 at 20:11
  • Thank you. I would have never be able to identify that XD – Fish Jun 27 '21 at 12:33
4

Alternatively, you can use the @PropertyName annotation from Firebase Database to handle this. Also, it's better to include setters as well.

Pass a custom Java object, if the class that defines it has a default constructor that takes no arguments and has public getters for the properties to be assigned.

public class PingReport {

private long durationMs;
private boolean isUp;
private long timestampMillis;

public PingReport() {
    // required by Firebase
}

public PingReport(long durationMs, boolean isUp, long timestampMillis) {
    this.durationMs = durationMs;
    this.isUp = isUp;
    this.timestampMillis = timestampMillis;
}

public long getDurationMs() {
    return durationMs;
}

@PropertyName("isUp")
public boolean isUp() {
    return isUp;
}

public long getTimestampMillis() {
    return timestampMillis;
}

}

Kamal Kishore
  • 399
  • 4
  • 6
3

I ran into this problem in Kotlin. I had several boolean values. All of them were set properly except for the one that started with is. To fix this, I made it a custom getter and that fixed the problem:

data class FirebaseEvent(
    val description: String? = null,
    val disableLogin: Boolean? = null,
    val isDVR: Boolean? = null
) {
    fun getIsDVR(): Boolean? {
        // this is needed to trick Kotlin into using this getter instead of generating its own which breaks firebase
        return isDVR
    }
}
Peter Graham
  • 2,467
  • 2
  • 24
  • 29
1

Don't use "is" with your variable name specifically with Firebase Realtime Database. I also had the same problem, I have to change my variable name from "isUserExist" to "userExist" ! Crippy Firebase!

Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
0

Your getter for isUp() is not following the normal convention. Have you tried public boolean getIsUp()?

John Shea
  • 26
  • 2
0

You should check the naming convention in java.

Try to use:

 private boolean up;
 public boolean isUp() {
        return up;
 }
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
0

if you are using Kotlin then use PropertyName on getter and setter of the variable so that you bypass kotlin generated getters/setters names. using this annotation on the variable itself doesn't help because it doesnt affect the generated setters and setters.

data class(
   @get:PropertyName("isRead")
   @set:PropertyName("isRead")
   var isRead: Boolean? = null
)

you can check this question for more info about java

Amr
  • 1,068
  • 12
  • 21
-1

Dont use the primitive "boolean" type but use "Boolean" class instead.