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
@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.
@timtower Yup, seems like it is, I commented out the line and it worked. Any idea how I can go about making it work?
@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);
@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.
@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. @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.
@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.