#Storing Custom Variable POJOs in Firebase

1 messages · Page 1 of 1 (latest)

hard vortex
#

Stacktrace when I try to save the POJO with a custom type:

org.bukkit.event.EventException: null
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:310) ~[spigot-api-1.19-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[spigot-api-1.19-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:588) ~[spigot-api-1.19-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:575) ~[spigot-api-1.19-R0.1-SNAPSHOT.jar:?]
        at net.minecraft.server.players.PlayerList.remove(PlayerList.java:501) ~[spigot-1.19-R0.1-SNAPSHOT.jar:3540-Spigot-56be6a8-0231a37]
        at net.minecraft.server.network.PlayerConnection.a(PlayerConnection.java:1725) ~[spigot-1.19-R0.1-SNAPSHOT.jar:3540-Spigot-56be6a8-0231a37]
        at net.minecraft.network.NetworkManager.m(NetworkManager.java:416) ~[spigot-1.19-R0.1-SNAPSHOT.jar:3540-Spigot-56be6a8-0231a37]
        at net.minecraft.server.network.ServerConnection.c(ServerConnection.java:193) ~[spigot-1.19-R0.1-SNAPSHOT.jar:3540-Spigot-56be6a8-0231a37]
        at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:1312) ~[spigot-1.19-R0.1-SNAPSHOT.jar:3540-Spigot-56be6a8-0231a37]
        at net.minecraft.server.dedicated.DedicatedServer.b(DedicatedServer.java:394) ~[spigot-1.19-R0.1-SNAPSHOT.jar:3540-Spigot-56be6a8-0231a37]
        at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:1197) ~[spigot-1.19-R0.1-SNAPSHOT.jar:3540-Spigot-56be6a8-0231a37]
        at net.minecraft.server.MinecraftServer.v(MinecraftServer.java:1010) ~[spigot-1.19-R0.1-SNAPSHOT.jar:3540-Spigot-56be6a8-0231a37]
        at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:291) ~[spigot-1.19-R0.1-SNAPSHOT.jar:3540-Spigot-56be6a8-0231a37]
        at java.lang.Thread.run(Thread.java:833) [?:?]
#
Caused by: com.google.firebase.database.DatabaseException: No properties to serialize found on class net.minecraft.resources.ResourceKey
        at com.google.firebase.database.utilities.encoding.CustomClassMapper$BeanMapper.<init>(CustomClassMapper.java:538) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.loadOrCreateBeanMapperForClass(CustomClassMapper.java:316) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.serialize(CustomClassMapper.java:171) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.access$300(CustomClassMapper.java:51) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper$BeanMapper.serialize(CustomClassMapper.java:797) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.serialize(CustomClassMapper.java:172) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.access$300(CustomClassMapper.java:51) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper$BeanMapper.serialize(CustomClassMapper.java:797) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.serialize(CustomClassMapper.java:172) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.access$300(CustomClassMapper.java:51) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper$BeanMapper.serialize(CustomClassMapper.java:797) ~[?:?]
#
at com.google.firebase.database.utilities.encoding.CustomClassMapper$BeanMapper.serialize(CustomClassMapper.java:797) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.serialize(CustomClassMapper.java:172) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.access$300(CustomClassMapper.java:51) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper$BeanMapper.serialize(CustomClassMapper.java:797) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.serialize(CustomClassMapper.java:172) ~[?:?]
        at com.google.firebase.database.utilities.encoding.CustomClassMapper.convertToPlainJavaTypes(CustomClassMapper.java:65) ~[?:?]
        at com.google.firebase.database.DatabaseReference.setValueInternal(DatabaseReference.java:297) ~[?:?]
        at com.google.firebase.database.DatabaseReference.setValueAsync(DatabaseReference.java:178) ~[?:?]
        at dev.danmizu.skylands.player.PlayerMap.savePlayerData(PlayerMap.java:147) ~[?:?]
        at dev.danmizu.skylands.player.PlayerMap.endPlayerData(PlayerMap.java:151) ~[?:?]
        at dev.danmizu.skylands.player.PlayerMap.unloadPlayer(PlayerMap.java:82) ~[?:?]
        at dev.danmizu.skylands.events.PlayerLeave.onLeave(PlayerLeave.java:20) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
#
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:306) ~[spigot-api-1.19-R0.1-SNAPSHOT.jar:?]
        ... 13 more
#

POJO Class:

package dev.danmizu.skylands.player;

// java imports
import java.util.HashMap;
import java.util.Map;

// gson imports
import com.google.gson.Gson;
import com.google.cloud.firestore.annotation.Exclude;
import com.google.cloud.firestore.annotation.PropertyName;
import com.google.common.reflect.TypeToken;

// bukkit imports
import org.bukkit.Location;

public class PlayerData {
    //player's display name
    private String displayName;

    //player's current health
    private double health;

    //player's location
    private Location location;

    // CONSTRUCTORS
    public PlayerData() {}
    public PlayerData(String displayName) {
        this.displayName = displayName;
    }
    public PlayerData(String displayName, double health) {
        this.displayName = displayName;
        this.health = health;
    }
    public PlayerData(String inputDisplayName, double inputHealth, Location inputLocation) {
        this.displayName = inputDisplayName;
        this.health = inputHealth;
        this.location = inputLocation;
    }

    // GETTERS/SETTERS
    @PropertyName("displayName")
    public String getDisplayName() {
        return displayName;
    }

    @PropertyName("health")
    public double getHealth() {
        return health;
    }
    @PropertyName("health")
    public void setHealth(double input) {
        health = input;
    }

    @PropertyName("location")
    public Location getLocation() {
        return this.location;
    }
    @PropertyName("location")
    public void setLocation(Location input) {
        this.location = input;
    }

    // UTILITY
    @Exclude
    public String toJSON() {
        //convert player entry to json
        return new Gson().toJson(this);
    }

    @Exclude
    public Map<String, Object> toMap() {
        //convert player entry to json then to map 
        return new Gson().fromJson(toJSON(), new TypeToken<HashMap<String, Object>>() {}.getType());
    }
}
fathom bane
#

it cannot serialize the location because its trying to serialize the world

#
record SerializableLocation
      (double x, double y, double z, double yaw, double pitch, UUID world) {
  
  public Location toLocation() {
    return new Location(Bukkit.getWorld(world), x, y, z, yaw, pitch);
  }

  public static SerializableLocation fromLocation(Location loc) {
    return new SerializableLocation(loc.getX(), loc.getY(), loc.getZ(),
                                    loc.getYaw(), loc.getPitch(),
                                    loc.getWorld().getUID());
  }  

}
``` use something like that
#

instead of org.bukkit.Location

#

put this in the PlayerData class

#

or even better, use the UUID

#

@hard vortex

hard vortex
#

@fathom bane trying to implement the record in the playerdata class

fathom bane
#

no it has to be lowercase record

fathom bane
#

why is your language level 1.7

#

set it to like 17

#

or 16

hard vortex
#

it is 17 pretty sure

fathom bane
#

for what versiion are you developing

fathom bane
#

1.7

#

in the error message

#

so dont think so

#

check it in either gradle or maven settings, or check it in Project Structure if youre not using a build system

hard vortex
#

ah yea in my pom

#

fixed that

fathom bane
#

does it work niwo

#

now

hard vortex
#

Location isnt accepting yaw and pitch

fathom bane
#

oh yeah

#

yaw and pitch should be float

fathom bane
#

new declaration line

hard vortex
#

awesome

#

once its all working how would I use it where I store and retrieve from firebase?

#

do i change my location type to that

fathom bane
#

yeah

#

when storing the data you would first convert the Location to a SerializableLocation using SerializableLocation.fromLocation(loc)

#

and then loading the data you can convert the serializable location to a Location using serializableLocation.toLocation()

#

and then cache that and use it

hard vortex
#

I changed my POJO to use SerializableLocation instead of Location as that variables type. I store the location to the instance within the PlayerMove event for now to test so I changed it to this:
PlayerMap.getPlayerData(player).setLocation(SerializableLocation.fromLocation(player.getLocation()));

#

setLocation is from the PlayerData class

#

now it uses SerializableLocation type

#

SerializableLocation is a seperate class I made to define the type

#

which has the function that "casts" it

#

going to test it now

fathom bane
#

seems fine

hard vortex
#

hm

#
Caused by: com.google.firebase.database.DatabaseException: No properties to serialize found on class dev.danmizu.skylands.type.SerializableLocation
#

same issue I think

#
package dev.danmizu.skylands.type;

// java imports
import java.util.UUID;

// bukkit imports
import org.bukkit.Bukkit;
import org.bukkit.Location;

public record SerializableLocation(double x, double y, double z, float yaw, float pitch, UUID world) {
    public Location toLocation() {
        return new Location(Bukkit.getWorld(world), x, y, z, yaw, pitch);
    }
    public static SerializableLocation fromLocation(Location loc) {
        return new SerializableLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), loc.getWorld().getUID());
    }  
}
#

SerializableLocation class

#

Stacktrace

fathom bane
#

huh

#

you may have to implement a method to allow for serialization

hard vortex
#

could it just have to do with firebase having specific accepted types?

hard vortex
fathom bane
#

oh

hard vortex
#

at the bottom it says POJOs are accepted but maybe the accepted types still apply

fathom bane
#

they have to be public

hard vortex
#

it says public getters but nothing about public variables

fathom bane
#

right click in the SerializableLocation class, and go to Generate and then Getters

#

and then choose the format get<Name>

#

idk what its called

#

also it may be a problem with it being a record

#

as its final

hard vortex
#

does it need to have getters and setters in the type? I thought it meant for the actual POJO

#

cuz I have a getter and setter in the pojo

fathom bane
#

so change it to

class SerializableLocation {

  public double x, y, z;
  public float  yaw, pitch;
  public UUID   world;

  // the functions

}
``` and then right click -> `Generate` -> `Getters and Setters`
hard vortex
#
package dev.danmizu.skylands.type;

// java imports
import java.util.UUID;

// bukkit imports
import org.bukkit.Bukkit;
import org.bukkit.Location;

class SerializableLocation {

    public double getX() {
        return this.x;
    }

    public void setX(double x) {
        this.x = x;
    }

    public double getY() {
        return this.y;
    }

    public void setY(double y) {
        this.y = y;
    }

    public double getZ() {
        return this.z;
    }

    public void setZ(double z) {
        this.z = z;
    }

    public float getYaw() {
        return this.yaw;
    }

    public void setYaw(float yaw) {
        this.yaw = yaw;
    }

    public float getPitch() {
        return this.pitch;
    }

    public void setPitch(float pitch) {
        this.pitch = pitch;
    }

    public UUID getWorld() {
        return this.world;
    }

    public void setWorld(UUID world) {
        this.world = world;
    }
    public double x, y, z;
    public float yaw, pitch;
    public UUID world;

    public SerializableLocation(double x2, double y2, double z2, float yaw2, float pitch2, UUID uid) {
    }
    
    public Location toLocation() {
        return new Location(Bukkit.getWorld(world), x, y, z, yaw, pitch);
    }
    public static SerializableLocation fromLocation(Location loc) {
        return new SerializableLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), loc.getWorld().getUID());
    }
}
#

this look right?

fathom bane
#

yeah

hard vortex
#

it asked me to have a constructor too

#

the class should be public right

#

cuz i get errors saying the class isnt accessible otherwise

fathom bane
#

oh yeah

#

@hard vortex put two constructors;

public SerializableLocation(double x, double y, double z,
                            float yaw, float pitch, UUID world) {
  this.x = x;
  this.y = y;
  this.z = z;
  this.yaw = yaw;
  this.pitch = pitch;
  this.world = world;
}

public SerializableLocation() {

}
#

second one is needed for firebase to work i think

fathom bane
hard vortex
#

okay so it somewhat works!

#

on the first time I join and leave its able to store it

#

second time I get an error but I think it has to do with retrieving the data on join

fathom bane
#

?paste

#

send error

hard vortex
#

so for some reason its not able to take the data and create a new POJO with it

fathom bane
#

bruh

#

sussy baka

hard vortex
fathom bane
#

ok nvm

#

aight

hard vortex
#

yea the error is on every move event

fathom bane
#

yeah the player data is null

#

so it hasnt been loaded yet

hard vortex
#

I have to use SerializableLocation again to parse it back when I retrieve the data right

#

or do I have to change the PlayerData pojo so it can do that?

#
public static void retrievePlayerData(Player player, @Nonnull final onPlayerDataRetrievalCallback callback) {
        //set player data reference
        DatabaseReference refPlayers = Firebase.getInstance().getReference("players").child(player.getUniqueId().toString());

        //DEBUG
        TextUtil.sendConsoleLog("Player Data Retrieving");

        //retrieve player data from database
        refPlayers.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot snapshot) {
                //DEBUG
                TextUtil.sendConsoleLog("Player Data Retrieved");
                callback.onPlayerDataRetrieval(snapshot.getValue(PlayerData.class));
            }

            @Override
            public void onCancelled(DatabaseError error) {
            }
        });
    }
#

you can see at callback.onPlayerDataRetrieval(snapshot.getValue(PlayerData.class));

fathom bane
#

no idea how firebase works

hard vortex
#

when it gets the data (snapshot) its using the POJO

fathom bane
#

so idk what im looking at

hard vortex
#

most of it is not important just that line really

fathom bane
#

ah

hard vortex
#

thats all because it needs to get the data asynchronously so that means 50x more code to get it to work in java

fathom bane
#

yeah lmao

hard vortex
#

so is there something I have to do with the getter/setter in PlayerData to make it parse the data back from the database as the SerializableLocation type?

fathom bane
#

it would be much cleaner if they did it like

ref
  .whenSuccess(value -> ...)
  .whenError(error -> ...)
  .releaseWhenDone();
hard vortex
#

yea well google hates us I guess

fathom bane
#

idk what the issue is man

#

about thsi new issue

hard vortex
#

yea ill try to see if i can solve it on my own

#

thanks for all the help!

#

I wouldnt have been able to get this far

#

already spent a few days searching online for the answer