IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Tomcat et TomEE Java Discussion :

The provided connection is not established. quand je recrée un nouveau LDAPConnectionPool


Sujet :

Tomcat et TomEE Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut The provided connection is not established. quand je recrée un nouveau LDAPConnectionPool
    Bonjour ce post fait suite au post https://www.developpez.net/forums/d2...d-client-java/"> (problème de fuite de mémoire d'une application Java sous tomcat interrogee à partir d'un client Java)



    J'avais trouvé un hack pour résoudre une problème de fuite de mémoire en utilisant un wrapper

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class CustomLDAPConnectionPool {
     
        public LDAPConnection lDAPConnection;
        public int numConnection;
     
        public LDAPConnectionPool connection;
     
        public CustomLDAPConnectionPool(LDAPConnection connection, int numConnection) throws LDAPException {
            this.lDAPConnection = connection;
            this.numConnection = numConnection;
            this.connection = new LDAPConnectionPool(connection, numConnection);
        }
     
        public SearchResult search(SearchRequest request) throws LDAPException {
            SearchResult result = this.connection.search(request);
            this.connection.close();
            this.connection = new LDAPConnectionPool(this.lDAPConnection, this.numConnection);  // l'erreur apparait à cette ligne 
            return result;
        }
     
        public SearchResultEntry searchForEntry(@NotNull SearchRequest searchRequest) throws LDAPException {
            SearchResultEntry result = this.searchForEntry(searchRequest);
            this.connection.close();
            this.connection = new LDAPConnectionPool(this.lDAPConnection, this.numConnection);
            return result;
        }
    }
    Ca a marché 2 jours et puis je ne sais pas ce qui s'est passé, ça ne marche plus

    J'ai l'erreur suivante

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    com.unboundid.ldap.sdk.LDAPException: The provided connection is not established.
    	at com.unboundid.ldap.sdk.LDAPConnectionPool.<init>(LDAPConnectionPool.java:661) ~[unboundid-ldapsdk-5.1.1.jar:5.1.1]
    	at com.unboundid.ldap.sdk.LDAPConnectionPool.<init>(LDAPConnectionPool.java:567) ~[unboundid-ldapsdk-5.1.1.jar:5.1.1]
    	at com.unboundid.ldap.sdk.LDAPConnectionPool.<init>(LDAPConnectionPool.java:502) ~[unboundid-ldapsdk-5.1.1.jar:5.1.1]
    	at com.unboundid.ldap.sdk.LDAPConnectionPool.<init>(LDAPConnectionPool.java:443) ~[unboundid-ldapsdk-5.1.1.jar:5.1.1]
    	at com.unboundid.ldap.sdk.LDAPConnectionPool.<init>(LDAPConnectionPool.java:354) ~[unboundid-ldapsdk-5.1.1.jar:5.1.1]
    	at eu.europa.europarl.staffaccess.ldap.CustomLDAPConnectionPool.search(CustomLDAPConnectionPool.java:23) ~[classes/:na]
    Pouvez vous m'aider . Pour la suggestion de PhilippeGibault d'utiliser un LDAP Template, merci encore, mais j'aimerais trouver la solution avec ma méthode

  2. #2
    Membre très actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    486
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 486
    Billets dans le blog
    5
    Par défaut
    Le message semble simple: Il n'arrive pas à se connecter au LDAP...

    De plus, la classe est trop mal conçu!

    Déjà, un principe de base, quand on gère un AutoClosable ( https://docs.oracle.com/javase/8/doc...Closeable.html ), pour éviter de se faire vraiment chier, on utilise un try-with-ressource (depuis Java 7):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    try(MonAutoClosable monAutoClosable){
      //Mon traitement
    }
    LDAPConnection est un AutoClosable:

    https://docs.ldap.com/ldap-sdk/docs/...onnection.html

    De plus, lorsque l'on fait un traitement, on n'ouvre le flux qu'une seule fois, on fait le traitement, on ferme le flux.

    Soit en pratique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    try(MonFlux = ...){
      //tout le traitement
    }
    Ici, on ouvre à chaque fois le flux, on fait un truc machin chose (search) et on ferme, on en crée un nouveau, puis on recommence.

    Tu m'étonnes qu'il râle après!

    Le code de search devrai être:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public SearchResult search(SearchRequest request) throws LDAPException {
        try(LDAPConnection lDAPConnection = ...){
            return this.connection.search(request);
        }
    }
    Pour une BDD, on a un code équivalent (ici, lire des fichier SQL) comme:
    https://bitbucket.org/philippegibaul...chiersSQL.java
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
     
    package com.calculateur.warhammer.create.database.sql;
     
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.TreeMap;
    import java.util.logging.Level;
    import java.util.logging.Logger;
     
    import com.calculateur.warhammer.base.bdd.IExecuteSQL;
    import com.calculateur.warhammer.base.exception.DAOException;
    import com.calculateur.warhammer.base.server.IDatabaseConfiguration;
     
    public class ExecuteFichiersSQL implements IExecuteSQL {
     
    	private static final Logger LOGGER = Logger.getLogger(ExecuteFichiersSQL.class.getName());
     
    	private static final String SEPARATOR_SQL_FILE = "_";
     
    	private static final String SQL_COMMENTAIRE = "--";
     
    	private static final int INDEX_NUMERO = 0;
     
    	private final File folderSQL;
     
    	private final IDatabaseConfiguration configuration;
     
    	private final Map<Integer, File> mapExecution;
     
    	public ExecuteFichiersSQL(File folderSQL, IDatabaseConfiguration configuration) {
    		this.folderSQL = folderSQL;
    		this.configuration = configuration;
    		mapExecution = new TreeMap<>();
    	}
     
    	@Override
    	public void executeSQL() throws DAOException {
    		try {
    			determinerOrdreExecution();
    			executeSQLFiles();
    		} catch (Exception e) {
    			throw new DAOException(e);
    		}
    	}
     
    	private void determinerOrdreExecution() {
    		String fileName;
    		String[] tab;
    		Integer order;
    		for (File sqlFile : folderSQL.listFiles()) {
    			fileName = sqlFile.getName();
    			tab = fileName.split(SEPARATOR_SQL_FILE);
    			order = Integer.parseInt(tab[INDEX_NUMERO]);
    			mapExecution.put(order, sqlFile);
    		}
    	}
     
    	private void executeSQLFiles() throws ClassNotFoundException, SQLException, IOException {
    		Class.forName(configuration.getClassDriver());
    		try (Connection connection = DriverManager.getConnection(configuration.getJDBCUrl(), configuration.getUser(),
    				configuration.getPassword())) {
    			for (Entry<Integer, File> entry : mapExecution.entrySet()) {
    				LOGGER.info("Execution ficnier n°" + entry.getKey() + " " + entry.getValue().getAbsolutePath());
    				executeSQLFile(connection, entry.getValue());
    				LOGGER.info("Le ficnier n°" + entry.getKey() + " " + entry.getValue().getAbsolutePath()+" a été executé entièrement");
    			}
    		}
    	}
     
    	private void executeSQLFile(Connection connection, File file) throws IOException, SQLException {
    		try (BufferedReader br = new BufferedReader(new FileReader(file))) {
    			String sql;
    			while ((sql = br.readLine()) != null) {
    				if(!sql.isEmpty() && !sql.startsWith(SQL_COMMENTAIRE)) {
    					executeUpdate(connection, sql);
    				}
    			}
    		}
    	}
     
    	private void executeUpdate(Connection connection,String sql)throws SQLException{
    		try(PreparedStatement ps =connection.prepareStatement(sql)){
    			LOGGER.log(Level.INFO,"Execute SQL : {0}",sql);
    			ps.executeUpdate();
    		}
    	}
    }
    Ici, je n'ouvre une connexion en BDD qu'une seule fois. Et les données de la BDD sont passés en paramètres (IDatabaseConfiguration configuration).

    L'équivalent LDAP serait de passer les données du LDAP (url, mdp...) dans une interface dédiée.

    Enfin, le rôle du LDAP Template est justement de gérer le flux avec LDAP, et donc de ne pas se préoccuper de cette gestion de flux et d'interroger le LDAP en ne se concentrant que sur l'aspect métier, et non plus sur les problèmes bas-niveaux.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut
    Bonjour Philippe merci beaucoup pour ta réponse,

    au départ je faisait appel au LDAP en faisant appel (comme ce que tu me dit) une seule fois à la création de LDAPConnection :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            try (LDAPConnection connection = new LDAPConnection(this.host, this.port, username, pass)) {
                return new AllConnection(new LDAPConnectionPool(connection, 64), this.env);
            } catch (LDAPException e) {
                logger.error("LDAPException occurred. Could not connect to AD.", e);
            }

    Le problème est que je faisait appel en boucle aux méthodes du LDAP
    et cela est gourmand en mémoire (la mémoire augmentait jusqu'à ce que TOMCAT explose).


    Un bon moyen de libérer la mémoire utilisé est de faire un LDAPConnectionPool.close()

    c'est pourquoi j'utilisais mon wrapper CustomLDAPConnectionPool que je décris dans le post initial.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    123456
            try (LDAPConnection connection = new LDAPConnection(this.host, this.port, username, pass)) {
                return new AllConnection(new CustomLDAPConnectionPool(connection, 64), this.env);
            } catch (LDAPException e) {
                logger.error("LDAPException occurred. Could not connect to AD.", e);
            }
    et j'ai vue en partie d'où provient l'erreur que je t'ai signalé

    quand je fais appel à la méthode

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    
    new CustomLDAPConnectionPool(connection, 64)  // je vois que l'objet connection est bien connecté au LDAP
    et que j'inspecte le constructeur de CustomLDAPConnectionPool,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        public CustomLDAPConnectionPool(LDAPConnection connection /* l'objet connection n'est plus connecté au LDAP, POURQUOI ? */, int numConnection) throws LDAPException {
            this.lDAPConnection = connection;
            this.numConnection = numConnection;
    }
    l'objet connection en entré de mon constructeur n'est plus connecté au LDAP, POURQUOI ?

    Peux tu m'aider à résoudre ce probléme ou/et mon problème de départ de fuite de mémoire ?

  4. #4
    Membre très actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    486
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 486
    Billets dans le blog
    5
    Par défaut
    C'est quoi le AllConnection?????????????

    Il apparait à l'insu de mon plein gré.

    Ensuite, le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    try (LDAPConnection connection = new LDAPConnection(this.host, this.port, username, pass)) {
                return new AllConnection(new LDAPConnectionPool(connection, 64), this.env);
            } catch (LDAPException e) {
                logger.error("LDAPException occurred. Could not connect to AD.", e);
            }
    Fonctionne normalement. Dès que les lignes dans le try (qui est un try-with ressources) sont exécutés, la ressource (ici LDAPConnection) est automatiquement fermé.
    Je ne vois pas l'intérêt du AllConnection. Si j'interroge un LDAP, c'est pour lister des users, en ajouter ...
    Si j'ouvre une connexion au LDAP, c'est pour interagir avec celui-ci.

    Une fois que j'ai fini, je ferme la connexion.

    Donc en résumé:
    1. J'ouvre mon LDAP (ou autre flux comme la BDD)
    2. Je fais mon traitement (demande d'utilisateur, modification ...)
    3. Une fois fini, je ferme le flux pour libérer les ressources.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut
    re,
    le AllConnection, c'est du code qui a été programmé par une ancienne stagiaire que j'ai repris et je ne peux pas changer. c'est trop long et difficile à expliquer

    Mes vrais questions sont dans le dernier message que j'ai fait. Mon probléme initial: fuite de mémoire quand je fait des nouvelles recherches (la mémoire utilisé augmente de plus en plus suite à des appels au LDAP en boucle)


    Si tu pouvais me donner des explications, ça serait super, si possible sans utiliser le LDAPTemplate et en utilisant les méthodes que j'ai décrite.

  6. #6
    Membre très actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    486
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 486
    Billets dans le blog
    5
    Par défaut
    On peut peut-être faire évoluer le AllConnection de la façon suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    public class AllConnection implements AutoClosable{
     
       private final LDAPConnection ldapConnection;
     
       public AllConnection(LDAPConnection ldapConnection){
           this.ldapConnection = ldapConnection;
       }
     
       @Override
       public void close() throws Exception{
           if(ldapConnection != null){
               ldapConnection.close();
          }
       }
    }
    De fait, on utiliserai:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    try( AllConnection allConnection = new AllConnection(...)){
     
    }
    ce qui fermerait le tout.

    Mais bon, c'est une stagiaire qui a fait ça, avec un nommage étrange, je pense que un refactoring serait plus adapté.
    Enfin, si il y a des tests....

  7. #7
    Membre très actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    486
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 486
    Billets dans le blog
    5
    Par défaut
    Ou déprécier l'objet, et passer par quelque chose de plus saint.

Discussions similaires

  1. Réponses: 3
    Dernier message: 16/04/2019, 16h29
  2. Réponses: 11
    Dernier message: 21/12/2016, 17h51
  3. The provider BC may not be signed by a trusted party
    Par Jonathan.Harvey dans le forum PL/SQL
    Réponses: 0
    Dernier message: 08/04/2011, 15h44
  4. Réponses: 0
    Dernier message: 27/03/2009, 11h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo