Problème Connexion base de données [NullPointerException]

Kenda

Architecte en herbe
16 Juillet 2016
292
1
2
125
32
www.youtube.com
Bonjour,

Je suis en train de faire un plugin d'authentification avec une base de données, sauf que j'ai une erreur assez étrange depuis hier soir.

J'ai le plugin qui fonctionne sous bungeecord et paper (en 1.9), mais depuis hier soir, juste le plugin du bungeecord se connecte à la BDD, et le paper me renvoie un NullPointerException alors que les deux plugins on exactement la même configuration.

Voici les logs d'erreurs du paper :

Code:
[09:18:32] [Server thread/INFO]: [HexaAuth] Enabling HexaAuth v1.0
[09:18:36] [Server thread/WARN]: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
[09:18:36] [Server thread/WARN]:     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[09:18:36] [Server thread/WARN]:     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
[09:18:36] [Server thread/WARN]:     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[09:18:36] [Server thread/WARN]:     at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.Util.getInstance(Util.java:387)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:919)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:898)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:887)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:862)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2164)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2089)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:795)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:44)
[09:18:36] [Server thread/WARN]:     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[09:18:36] [Server thread/WARN]:     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
[09:18:36] [Server thread/WARN]:     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[09:18:36] [Server thread/WARN]:     at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:400)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:327)
[09:18:36] [Server thread/WARN]:     at java.sql.DriverManager.getConnection(DriverManager.java:664)
[09:18:36] [Server thread/WARN]:     at java.sql.DriverManager.getConnection(DriverManager.java:247)
[09:18:36] [Server thread/WARN]:     at fr.kenda.hexaauth.spigot.sql.MySQL.connect(MySQL.java:14)
[09:18:36] [Server thread/WARN]:     at fr.kenda.hexaauth.spigot.Main.onEnable(Main.java:25)
[09:18:36] [Server thread/WARN]:     at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:292)
[09:18:36] [Server thread/WARN]:     at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:319)
[09:18:36] [Server thread/WARN]:     at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:407)
[09:18:36] [Server thread/WARN]:     at org.bukkit.craftbukkit.v1_9_R2.CraftServer.loadPlugin(CraftServer.java:358)
[09:18:36] [Server thread/WARN]:     at org.bukkit.craftbukkit.v1_9_R2.CraftServer.enablePlugins(CraftServer.java:318)
[09:18:36] [Server thread/WARN]:     at net.minecraft.server.v1_9_R2.MinecraftServer.t(MinecraftServer.java:414)
[09:18:36] [Server thread/WARN]:     at net.minecraft.server.v1_9_R2.MinecraftServer.l(MinecraftServer.java:379)
[09:18:36] [Server thread/WARN]:     at net.minecraft.server.v1_9_R2.MinecraftServer.a(MinecraftServer.java:333)
[09:18:36] [Server thread/WARN]:     at net.minecraft.server.v1_9_R2.DedicatedServer.init(DedicatedServer.java:272)
[09:18:36] [Server thread/WARN]:     at net.minecraft.server.v1_9_R2.MinecraftServer.run(MinecraftServer.java:573)
[09:18:36] [Server thread/WARN]:     at java.lang.Thread.run(Thread.java:748)
[09:18:36] [Server thread/WARN]: Caused by: java.lang.NullPointerException
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.ConnectionImpl.getServerCharset(ConnectionImpl.java:3004)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.MysqlIO.sendConnectionAttributes(MysqlIO.java:1908)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1837)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1207)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2254)
[09:18:36] [Server thread/WARN]:     at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2105)
[09:18:36] [Server thread/WARN]:     ... 25 more


Ensuite voici ma class Main du bungee :

Java:
package fr.kenda.hexaauth.bungee;

import fr.kenda.hexaauth.bungee.listeners.EventMessaging;
import fr.kenda.hexaauth.bungee.sql.MySQL;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;

public class MainBungee extends Plugin {

    private static final MySQL mysql = new MySQL();
    public static MainBungee instance;

    @Override
    public void onEnable(){
        instance = this;
        PluginManager pm = ProxyServer.getInstance().getPluginManager();
        mysql.connect("192.168.0.225", 3306, "minecraft", "kenda", "{password}");
        pm.registerListener(this, new EventMessaging());
    }

    @Override
    public void onDisable(){

    }
    public static MainBungee getInstance() {
        return instance;
    }
}

Et voici ma class Main du paper

Java:
package fr.kenda.hexaauth.spigot;

import fr.kenda.hexaauth.spigot.sql.MySQL;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;

import java.sql.Connection;

public final class Main extends JavaPlugin {

    private static Main instance;
    private static final MySQL mysql = new MySQL();
    public String prefix = "§f[§6Hexa§9Auth§f] §7§l» ";

    @Override
    public void onEnable() {
        instance = this;
        mysql.connect("192.168.0.225", 3306, "minecraft", "kenda", "{password}");
        Bukkit.getConsoleSender().sendMessage(prefix + "§aPlugin lancé avec succès.");
        this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");

        registerCommands();
        registerEvents();

    }
...

Ainsi que ma class MySql :
Java:
package fr.kenda.hexaauth.spigot.sql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class MySQL {
  private Connection connection;

  public void connect(String host, int port, String database, String user, String password) {
    if (!isConnected()) {
      try {
        connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database +"?autoReconnect=true", user, password);
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
 
  public void disconnect() {
    if (isConnected())
      try {
        connection.close();
      } catch (SQLException e) {
        e.printStackTrace();
      } 
  }
 
  public boolean isConnected() {
    try {
      return connection != null && !connection.isClosed() && !connection.isValid(5);
    } catch (SQLException e) {
      e.printStackTrace();
      return false;
    }
  }

  public void update(String query) {
    Connection connection = getConnection();

    try(PreparedStatement statement = connection.prepareStatement(query)) {
      statement.executeUpdate();
    }
    catch(SQLException e) {
      // TODO: handle exception
      // Il faut que ton plugin réagisse s'il ne peut pas créer la table
      e.printStackTrace();
    }
  }

  public Connection getConnection() {
    return connection;
  }

}

Je trouve sa étrange, et c'est uniquement les papers qui bug, j'ai essayer avec un plugin et serveur vierge et même problème.
Je suis sur que c'est un truc tout con en plus, mais impossible de trouver :(

Merci de l'aide :)
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 087
157
455
247
21
Mìlhüsa
Bonjour,

Java ne permet pas directement de te connecter avec une base de données MySQL, il faut que tu rajoutes un pilote en dépendance, et tu sembles utiliser un pilote obsolète fourni par un autre plugin ou que sais-je, rajoute-le manuellement et met-le dans un de tes packages pour éviter les collisions avec les autres plugins :
XML:
<build>
   <plugins>
      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-shade-plugin</artifactId>
         <version>3.2.4</version>
        
         <executions>
            <execution>
               <phase>package</phase>
               <goals>
                  <goal>shade</goal>
               </goals>
               <configuration>
                  <relocations>
                     <relocation>
                        <pattern>com.mysql</pattern>
                        <shadedPattern>fr.kenda.hexaauth.shaded.com.mysql</shadedPattern>
                     </relocation>
                    
                     <relocation>
                        <pattern>com.google</pattern>
                        <shadedPattern>fr.kenda.hexaauth.shaded.com.google</shadedPattern>
                     </relocation>
                  </relocations>
                 
                  <!-- Warning suppresion: overlapping resources -->
                  <filters>
                     <filter>
                        <artifact>mysql:mysql-connector-java</artifact>
                        <excludes>
                           <exclude>META-INF/MANIFEST.MF</exclude>
                        </excludes>
                     </filter>
                    
                     <filter>
                        <artifact>com.google.protobuf:protobuf-java</artifact>
                        <excludes>
                           <exclude>META-INF/MANIFEST.MF</exclude>
                        </excludes>
                     </filter>
                  </filters>
               </configuration>
            </execution>
         </executions>
      </plugin>
   </plugins>
</build>

<dependencies>
   <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.28</version>
     
      <exclusions>
         <exclusion>
            <!-- CVE-2021-22569 -->
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
         </exclusion>
      </exclusions>
   </dependency>
  
   <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>3.19.3</version>
   </dependency>
</dependencies>

Et après tu dois manuellement initier la connexion avec ledit pilote (tu ne peux pas utiliser DriverManager parce qu'il ne sait pas où est ton pilote), tu peux t'aider de ce repository :
https://github.com/RainbowDashLabs/BasicSQLPlugin

Plus particulièrement :
https://github.com/RainbowDashLabs/...lecoins/data/util/DataSourceProvider.java#L14 — pour créer une DataSource à partir de laquelle tu pourras établir une ou plusieurs connexions (l'équivalent de ta précédente URL).
Tu peux activer la reconnexion automatique avec MysqlDataSource#setAutoReconnect(boolean).
La classe Database en paramètre est simplement une classe d'exemple qui contient l'équivalent de tes paramètres dans ta fonction MySQL#connect(...).

Pense aussi à te protéger contre les injections SQL, concrètement n'utilise jamais la concaténation.

Cordialement,
ShE3py
 
Dernière édition:

Kenda

Architecte en herbe
16 Juillet 2016
292
1
2
125
32
www.youtube.com
Bonjour,


Merci de la réponse plus approfondi sur ce sujet.
Chose que je ne comprend pas, depuis tout ce temps j'ai toujours pu faire l'accès de cette manière, et depuis hier soir seulement j'ai ce problème sans rien touché.

Ensuite chose que je n'ai pas préciser, j'utilise gradle et je suis en version 1.9 de paper (je ne sais pas si il y a un rapport avec ce problème).
Et pourquoi donc mon bungeecord uniqurement fonctionne avec le plugin ?


Merci.
 

ShE3py

Enbogueuse
Support
26 Septembre 2015
4 087
157
455
247
21
Mìlhüsa
Et pourquoi donc mon bungeecord uniqurement fonctionne avec le plugin ?
Aucune idée, tu as une erreur interne lorsque le pilote tente de récupérer l'encodage de la BDD, et donc le plus simple est de mettre à jour le pilote.
Puisque tu le n'a jamais installé dans ton plugin il prend la version qu'il trouve, où ça aucune idée, cependant ce n'est probablement pas la dernière en date et ce ne serait pas étonnant que deux serveurs aient une version différente si tu n'en choisit toi aucun.

Ensuite chose que je n'ai pas préciser, j'utilise gradle et je suis en version 1.9 de paper (je ne sais pas si il y a un rapport avec ce problème).
La gestion des dépendances se fait différemment ;
Code:
plugins {
    id 'java'
    id 'com.github.johnrengelman.shadow' version '7.1.2'
}

group 'org.example'
version '0.1.0'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'mysql:mysql-connector-java:8.0.28'
   
    // CVE-2021-22569
    implementation('com.google.protobuf:protobuf-java') {
        version {
            strictly '3.19.3'
        }
    }
}

shadowJar {
    relocate 'com.mysql', 'fr.kenda.hexaauth.shaded.com.mysql'
    relocate 'com.google', 'fr.kenda.hexaauth.shaded.com.google'
}

assemble.dependsOn shadowJar

Puis tu crées le jar final avec la tâche « assemble ».


La dépendance enregistre aussi le service, dans le jar final « /META-INF/services/java.sql.Driver » :
Code:
com.mysql.cj.jdbc.Driver

Ce qui permet d'indiquer à Java un pilote SQL additionnel (ici, MySQL) à charger, or la tâche shadowJar permet de le déplacer dans notre package (ce qui évite qu'un autre plugin arrive avec son propre com.mysql et écrase notre dépendance avec une autre version), si tu veux être propre il faudrait aussi modifier ce fichier :
Code:
fr.kenda.hexaauth.shaded.com.mysql.cj.jdbc.Driver

Ou plus simplement supprimer ce fichier, parce que de toute façon il faut passer directement par MysqlDataSource et non par DriverManager, afin d'être sûr d'obtenir la version de notre pilote que l'on a embarqué avec le plugin et pas un truc au pif.