SQL Troubles

Discussion in 'Plugin Development' started by Caedus, Jan 27, 2016.

Thread Status:
Not open for further replies.
  1. Offline

    Caedus

    Hi, so i'm having troubles with a very basic sql plugin, where a user gets added to my DB if they haven't already got a DB entry for their UUID.

    When I manually add my username name to the DB, it doesn't throw an error and as far as I can tell, the code runs properly. I believe my error stems from the ELSE part of my PlayerLoginEvent.

    Code:
    Code:
    public class PlayerDB extends JavaPlugin implements Listener{
        
       
        private static Connection connection;
       
        @Override
        public void onEnable(){
    
            getLogger().info("PlayerDB Loaded.");
            getServer().getPluginManager().registerEvents(this, this);
    
    
        }
        @Override
        public void onDisable(){
            try {
                if(connection == null || connection.isClosed()){
                    connection.close();
                }
            } catch (SQLException e) {
               
                e.printStackTrace();
            }
        }
       
        public synchronized static void openConnection(){
           
            try{
                connection = DriverManager.getConnection("jdbc:mysql://herp/derp", "username", "pw");
            } catch(Exception e)
            {
                e.printStackTrace();
            }
        }
       
    public synchronized static void closeConnection(){
        try {
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
       
        public synchronized static boolean playerDataContainsPlayer(Player player){
            try{
                PreparedStatement sql = connection.prepareStatement("SELECT * FROM `Minecraft` WHERE name=?");
                sql.setString(1, player.getName());
               
                ResultSet res = sql.executeQuery();
               
                boolean containsPlayer = res.next();
               
                sql.close();
                res.close();
               
                return containsPlayer;
               
            } catch (Exception e){
                e.printStackTrace();
                return false;
               
            }
        }
       
       
        @EventHandler
        public void onPlayerJoin(PlayerLoginEvent e){
            openConnection();
           
            try {
               
                if(playerDataContainsPlayer(e.getPlayer())){
                    PreparedStatement sql = connection.prepareStatement("SELECT Name FROM `Minecraft` where UUID=?");
                    sql.setString(1, e.getPlayer().getUniqueId().toString());
                   
                    ResultSet res = sql.executeQuery();
                    res.next();
                   
                    sql.close();
                    res.close();
                   
                    Bukkit.broadcastMessage("Player "+e.getPlayer().getName()+" has logged in, already in DB");
                } else {
                   
                    String playerIP = e.getPlayer().getAddress().toString();
                   
                    PreparedStatement np = connection.prepareStatement("INSERT INTO `Minecraft` values(?,?,?);");
                    np.setString(1, e.getPlayer().getName());
                    np.setString(2, e.getPlayer().getUniqueId().toString());
                    np.setString(3, playerIP);
                   
                    np.execute();
                   
                    np.close();
                    Bukkit.broadcastMessage("ok");
                }
               
               
               
            } catch (Exception ee) {
                ee.printStackTrace();
            } finally {
                closeConnection();
            }
           
    
           
           
        }
       
    }
    The NPE Error I get is as follows:
    Code:
    [13:10:12] [Server thread/WARN]: java.lang.NullPointerException
    [13:10:12] [Server thread/WARN]:     at me.Caedus.PlayerDB.onPlayerJoin(PlayerDB.java:100)
    [13:10:12] [Server thread/WARN]:     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    [13:10:12] [Server thread/WARN]:     at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    [13:10:12] [Server thread/WARN]:     at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    [13:10:12] [Server thread/WARN]:     at java.lang.reflect.Method.invoke(Unknown Source)
    [13:10:12] [Server thread/WARN]:     at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:300)
    [13:10:12] [Server thread/WARN]:     at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
    [13:10:12] [Server thread/WARN]:     at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:501)
    [13:10:12] [Server thread/WARN]:     at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:486)
    [13:10:12] [Server thread/WARN]:     at net.minecraft.server.v1_8_R3.PlayerList.attemptLogin(PlayerList.java:439)
    [13:10:12] [Server thread/WARN]:     at net.minecraft.server.v1_8_R3.LoginListener.b(LoginListener.java:89)
    [13:10:12] [Server thread/WARN]:     at net.minecraft.server.v1_8_R3.LoginListener.c(LoginListener.java:53)
    [13:10:12] [Server thread/WARN]:     at net.minecraft.server.v1_8_R3.NetworkManager.a(NetworkManager.java:222)
    [13:10:12] [Server thread/WARN]:     at net.minecraft.server.v1_8_R3.ServerConnection.c(SourceFile:168)
    [13:10:12] [Server thread/WARN]:     at net.minecraft.server.v1_8_R3.MinecraftServer.B(MinecraftServer.java:745)
    [13:10:12] [Server thread/WARN]:     at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:335)
    [13:10:12] [Server thread/WARN]:     at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:629)
    [13:10:12] [Server thread/WARN]:     at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:537)
    [13:10:12] [Server thread/WARN]:     at java.lang.Thread.run(Unknown Source)
    Cheers
     
  2. Online

    timtower Moderator Moderator

    @Caedus And what is line 100?
    And database and network calls shouldn't happen on the main thread.
     
  3. Offline

    Caedus

    Code:
    String playerIP = e.getPlayer().getAddress().toString();
    I don't follow
     
  4. Online

    timtower Moderator Moderator

    @Caedus Try to find if getPlayer is returning null or getAddress?
    And network / database calls take time, loads of it compared to normal operations, then can freeze the main thread.
     
  5. Offline

    Caedus

    @timtower Yup, seems like it is, I commented out the line and it worked. Any idea how I can go about making it work?
     
  6. Online

    timtower Moderator Moderator

    @Caedus Which of the methods is throwing the error? getPlayer or getAddress?
     
  7. Offline

    Caedus

    @timtower I'm not sure how to check, but I would I assume it's getAddress() as the following code works no problem:

    Code:
    String playerIP = e.getPlayer().getName().toString();
                   
                    PreparedStatement np = connection.prepareStatement("INSERT INTO `Minecraft` values(?,?,?);");
                    np.setString(1, e.getPlayer().getName());
                    np.setString(2, e.getPlayer().getUniqueId().toString());
                    np.setString(3, playerIP);
     
  8. Online

    timtower Moderator Moderator

    @Caedus Well, try just printing the values that they return.
     
  9. Offline

    Caedus

    @timtower It prints null, not sure why

    EDIT: Found what was wrong, with the event PlayerLoginEvent, the server apparently does not know what your IP is yet and thus cannot get it, I use PlayerJoinEvent now and it works perfectly.

    If anyone can tell me a difference between the two events, that would be cool.
     
    Last edited: Jan 27, 2016
  10. Offline

    WolfMage1

    @Caedus
    1. Be specific when catching Exceptions, if it doesn't throw every one, don't catch every one
    2. Close your connections in a finally block, because if it throws an SQLException before you close it then they never get closed.
    3.
    Code:
    PreparedStatement sql = connection.prepareStatement("SELECT * FROM `Minecraft` WHERE name=?");
    
    No point in selecting everything to see if there's a player in your database. You're just retrieving and returning unneeded data. Just set your UUID field as primary key and then do SELECT `UUID` instead.
    4. As @timtower said, don't run MySQL queries on the main thread, and in this case use the AsyncPlayerPreLoginEvent, but if you're going to be using MySQL connections in commands and what not create a new thread and run it through that so it doesn't halt the server thread.
    5. Most important of them all, don't use TheBCBroz for Java tutorials, all he does is teach bad practice (like for example catching non specific exceptions, or using static when it's not needed) And we all know what happens when you use bad practice.
    [​IMG]
    @ShowbizLocket61 for the image.

    EDIT: As for your NPE, Likely due to the player not being fully initialized, the event has .getAdddress() built in, you should use that instead instead of attempting to get the player.
     
    Last edited: Jan 27, 2016
  11. Offline

    mythbusterma

    @Caedus

    Another note: I don't think the synchronized keyword does what you think it does. You should remove it since you're not using it.
     
Thread Status:
Not open for further replies.

Share This Page