Springboot + ReactJS + Firebase's Realtime Database - java

Back-end: Springboot
Front-end: ReactJS
CloudRepo: Firebase Realtime Database
I have a Springboot application that GETs data from the Firebase Realtime Database.
This data is then served via a GET request from reactJS.
I get the JSON object in reactJS as :
What I am trying to do is to map the firebase snapshot to a Java Collection. Here is What I have done so far:
DatabaseReference ref = FirebaseService.getFirebaseDatabase().getReference("/devices/device1");
ref.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot messageSnapshot: dataSnapshot.getChildren()) {
DeviceData message = messageSnapshot.getValue(DeviceData.class);
System.out.println(message);
}
Map<String, DeviceData> document = (Map<String, DeviceData>) dataSnapshot.getValue();
setUpdatedDocumentData(document);
}
public void onCancelled(DatabaseError error) {
System.out.print("-----Error-----:\n" + error.getMessage());
}
});
My POJO looks like this:
public class DeviceData {
String sensor_1;
String sensor_2;
public DeviceData() {}
public DeviceData(String sensor_1, String sensor_2) {
this.sensor_1 = sensor_1;
this.sensor_2 = sensor_2;
}
public String getSensor_1() {
return sensor_1;
}
public void setSensor_1(String sensor_1) {
this.sensor_1 = sensor_1;
}
public String getSensor_2() {
return sensor_2;
}
public void setSensor_2(String sensor_2) {
this.sensor_2 = sensor_2;
}
#Override
public String toString() {
return "DeviceData{" +
"sensor_1='" + sensor_1 + '\'' +
", sensor_2='" + sensor_2 + '\'' +
'}';
}
}
I am getting null in my sensor_1 and sensor_2 log. How can I map the above firebase structure to a collection?

Under each /devices/$device node, you have two nested levels:
For the date
For the time.
Your code only has once loop over the children of the device node, so your messageSnapshot variable is actually a snapshot with all data for all timestamps for a specific date.
To handle your structure correctly, you need two nested loops:
DatabaseReference ref = FirebaseService.getFirebaseDatabase().getReference("/devices/device1");
ref.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dateSnapshot: dataSnapshot.getChildren()) {
for (DataSnapshot timeSnapshot: dataSnapshot.getChildren()) {
DeviceData message = timeSnapshot.getValue(DeviceData.class);
System.out.println(message);
}
}
Map<String, DeviceData> document = (Map<String, DeviceData>) dataSnapshot.getValue();
setUpdatedDocumentData(document);
}
public void onCancelled(DatabaseError error) {
System.out.print("-----Error-----:\n" + error.getMessage());
}
});
If you only care about the latest timestamp on the latest date, you can reduce the amount of data you read from the database by only getting the latest date:
DatabaseReference ref = FirebaseService.getFirebaseDatabase().getReference("/devices/device1");
ref.orderByKey().limitToLast(1).addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dateSnapshot: dataSnapshot.getChildren()) {
for (DataSnapshot timeSnapshot: dataSnapshot.getChildren()) {
DeviceData message = timeSnapshot.getValue(DeviceData.class);
System.out.println(message);
}
}
Map<String, DeviceData> document = (Map<String, DeviceData>) dataSnapshot.getValue();
setUpdatedDocumentData(document);
}
public void onCancelled(DatabaseError error) {
System.out.print("-----Error-----:\n" + error.getMessage());
}
});
You'll still have to read all timestamps for that date, but at least you're now only reading data for the most recent day.

Related

Cannot get reference to my auto generated push IDs in android

I am making an android app through android studio in java language. I have linked it to firebase Realtime database. There are auto generated push IDs as the last child. I want to retrieve my database values back in an activity. I am facing problem in giving reference to the push IDs.
This is what I have tried.
myRef = myfire.getReference().child("Data").child(strUID).child("Traffic").child("Wedding");
final String uid =myRef.getKey();
myRef.child(uid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
Toast.makeText(getApplicationContext(),"Data Not Available",Toast.LENGTH_LONG).show();
} else {
String stData1 = (Objects.requireNonNull(dataSnapshot.child("stData1").getValue())).toString();
String stData2 = (Objects.requireNonNull(dataSnapshot.child("stData2").getValue())).toString();
String stData3 = (Objects.requireNonNull(dataSnapshot.child("stData3").getValue())).toString();
String stData4 = (Objects.requireNonNull(dataSnapshot.child("stData4").getValue())).toString();
category basic = new category(stData1,stData2,stData3,stData4);
tvBalance.setText(stData4);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
Please provide a practical example.
Edit
This is my database structure:------------
Data>>
user id>>>>
Traffic>>>>
Wedding>>>>
Auto ID>>>
>stData1
>stData2
>stData3
>stData4 //I want to get this last value//
my json file
{
"Data" : {
"UyhzVqsz1BVFKoePa2NEmlPFu382" : {
"Traffic" : {
"Wedding" : {
"-MYKeSN8GZ8WbI-8TfVB" : {
"stData1" : "15 Apr 2021,06:43:00:pm",
"stData2" : "Wedding",
"stData3" : "kkk",
"stData4" : "100"
}
}
}
}
}
}
The only ways to get a node is by either knowing its full path, or by knowing the path to the parent node, and then some unique value under the node. Neither seems to be the case for the stData4 in your JSON, so you'll have to load the entire Wedding node and then loop over the results to get the part you want.
This isn't too bad though:
myRef = myfire.getReference("Data").child(strUID).child("Traffic/Wedding");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (!dataSnapshot.exists()) {
Toast.makeText(getApplicationContext(),"Data Not Available",Toast.LENGTH_LONG).show();
} else {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String stData1 = childSnapshot.child("stData1").getValue(String.class);
String stData2 = childSnapshot.child("stData2").getValue(String.class);
String stData3 = childSnapshot.child("stData3").getValue(String.class);
String stData4 = childSnapshot.child("stData4").getValue(String.class);
}
category basic = new category(stData1,stData2,stData3,stData4);
tvBalance.setText(stData4);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
The code above assumes that:
strUID has the value UyhzVqsz1BVFKoePa2NEmlPFu382

How do I query Firestore Array Value?

How can I Query the Array dates with the month value?
String monthString = "12";
Query queryZero = db.collection("Users").document(mCurrentUser).collection("Dates").whereArrayContainsAny("dates", ???);
What do I have to put where the '???' to retrieve dates with the dd/MM/yyyy <- /MM/ value is equal to the monthString?
Firestore at the moment does not support this kind of query. But, a possible workaround is to store additional array of months in your document and perform:
db.collection("Users").document(mCurrentUser).collection("Dates").whereArrayContains("months", "12");
Another solution is similar to #Ruyut's answer. But this would retrieve all the documents in the collection and you would have to perform the filtering in the client-side which could possibly degrade performance if you have thousands of documents.
FirebaseFirestore.getInstance().collection("Users")
.get()
.addOnSuccessListener(
new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
for (DocumentSnapshot ds : documentSnapshots.getDocuments()) {
// same code as #Ruyut's answer
}
}
}
);
public static void getData(){
DatabaseReference database = FirebaseDatabase.getInstance().getReference("Users").child(mCurrentUser).child("Dates");
database_course.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String key = ds.getKey(); //7UE......
HashMap<String, ArrayList<String>> datesHashMap = ds.get(key);
for(int i =0;i<datesHashMap.get("dates").size();i++){
String date = datesHashMap.get("dates").get(i);//08/12/2019
if (date.substring(3,5).equals("12")){
//put your code
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}

Why does my firebase database child return null?

I am working with firebase database and i was trying to get the value of a child using this code below and may System.out.println(MyCredit.toString()); is always returns null: Please see my firebase database
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users");
ref.addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Get map of users in datasnapshot
CollectCredits((Map<String,Object>) dataSnapshot.getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {
//handle databaseError
}
});
private void CollectCredits(Map<String,Object> users) {
MyCredit = new ArrayList<>();
//iterate through each user, ignoring their UID
for (Map.Entry<String, Object> entry : users.entrySet()){
//Get user map
Map singleUser = (Map) entry.getValue();
//Get Credit field and append to list
MyCredit.add((Long) singleUser.get("Credit"));
Toast.makeText(MainActivityCustonlistViewnew.this, "Credit : " +String.valueOf(MyCredit), Toast.LENGTH_SHORT).show();
}
System.out.println(MyCredit.toString());
}
Try this:
private void CollectCredits(DataSnapshot dataSnapshot) {
MyCredit = new ArrayList<>();
//iterate through each dataSnapshot
for (DataSnapshot d1 : dataSnapshot.getChildren()){
MyCredit.add(d1.getValue());
}
}
Let me give you some suggestions, Try to check your firebase database path both the root and child path because some time you did everything correctly but the path you specified to your Database reference which is not referring to the correct path. So it can produce the same result what are getting right now.

how to load data from firebase into arraylist in java

I have this piece of code in swift which loads up data from Firebase into dictionary a dictionary object.
i need to do same in java but its not dont know how. pl
// This is swift version
var yourArray = NSMutableArray()
func GetData() {
ref = Database.database().reference()
ref.child(bookTitle).observe(.value, with: { (snapshot) in
let children = snapshot.children
let allObj = children.allObjects
for i in 0 ..< allObj.count {
self.yourArray.add(allObj[i])
}
}) { (error) in
print(error)
}
Try This One
List<MyPojoClass> myList = new ArrayList<>();
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
myList.clear();
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
MyPojoClass pojo= postSnapshot.getValue(MyPojoClass.class);
myList.add(pojo);
// here you can access others property of pojo class.
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});

How to query firebase database to return a value's key's parent's parent?

I am developing a team chat application . I am storing chat data in firebase.
This is my Data structure
The chats are stored under a node named chats.
each immediate child of chats is the name of a team(like whatsapp.. chat groups).
the team node have all chat messages. the chat messages are stored
with a parent node in the format timestamp_chat
My Problem
Now I have to create a firebase query to fetch this team nodes by from key.
That is
if a from: field contains the a given search value (say, "ragesh"), then the parent node "team_name" have to be returned(say,"teamrova") as a datasnapshot.
Simply speaking , I want datasnapshot of teams that have a particular username in the from field.
My Work
I tried the follwing code :
reference1 = FirebaseDatabase.getInstance().getReference().child("chats");
Query chatQuery = reference1.orderByChild("from").equalTo("ragesh");
System.out.println("Chat list :: starting");
chatQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
System.out.println("Chat list :: onChildAdded");
for (DataSnapshot chat : dataSnapshot.getChildren()) {
HashMap<String, Object> hashMap = (HashMap<String, Object>) dataSnapshot.getValue();
System.out.println("Chat list :: The chat group is =>" + dataSnapshot.getKey());
System.out.println("Chat list :: The key & Value => " + chat.getKey() +" :: "+chat.getValue().toString());
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ChatListActivity.this, "Connection Error "+databaseError.getDetails(), Toast.LENGTH_SHORT).show();
System.out.println("Chat list :: databaseError "+databaseError.toString());
}
});
Sadly , above code don't return any value. even the
System.out.println("Chat list :: onChildAdded"); not called. And it
doesn't calls onCancelled also.(so,no error).
I get sturcked by this. please help me.
To get the username:
mRootRef.child("chats").child("teamrova").orderByChild("from").equalTo("ragesh").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
String name=datas.child("from").getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Since you are using addChildeventListener then you do not need the for loop to be able to get those values for (DataSnapshot chat : dataSnapshot.getChildren()) {
You also need to change this:
reference1 = FirebaseDatabase.getInstance().getReference().child("chats");
to this:
reference1 = FirebaseDatabase.getInstance().getReference().child("chats").child("teamrova");
The above code is an alternative with addValueEventListener

Categories