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

NetBeans Java Discussion :

Problème de ClassLoader


Sujet :

NetBeans Java

  1. #1
    Membre expérimenté
    Avatar de yotta
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Septembre 2006
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 088
    Points : 1 540
    Points
    1 540
    Par défaut Problème de ClassLoader
    Bonjour à tous,

    Je rencontre actuellement un problème que je n'arrive pas à comprendre, c'est pourquoi je tente ma chance sur ce forum.
    Tout se déroule sous NetBeans 6.5 avec le jdk 1.6.
    Le contexte est simple. Il s'agit d'un jar exécutable qui contient en plus de ses classes de travail un dossier nommé HTMLFiles, qui comme son nom l'indique contient des fichiers HTML, dont un fichier qui se nomme index.html.
    Dans son travail, mon jar est amené à ouvrir un fichier contenu dans ce dossier HTMLFiles.
    Pour réaliser cette opération, j'avais dans un premier temps utilisé la méthode getRessource de mon ClassLoader pour récupérer sous la forme d'un File ma ressource index.html. Et là, surprise ! Le code fonctionne parfaitement lorsque je l'exécute sous NetBeans, mais si je le lance en dehors de NetBeans, je constate que la construction du fichier échoue car la ressource n'est plus trouvée ?!
    J'en ai alors conclu que le ClassLoader n'utilise pas le même path lorsqu'il évolue dans une JVM instanciée par NetBeans que celui utilisé par la JVM lorsque le code est lancé en dehors de NetBeans. Après avoir pisté la chose, je me suis éffectivement rendu compte que dans NetBeans, le fichier est cherché dans le code source, pas dans le dossier dist résultant de la compilation. Je me suis dit que cela venait du fait d'exploiter un objet File, qui par définition est en rapport avec le système de fichier, hors mon fichier se trouve à l'interieur de mon jar, donc pas sur le système de fichier.
    J'ai alors changé de technique et j'ai remplacé mon File par un InputStream via la méthode getRessourceAsStream de mon ClassLoader. InputStream étant plus généraliste que File, il n'est pas forcément associé au système de fichier. Effectivement, une fois la modification apportée, mon code fonctionne. Enfin presque....
    Je penses que vous avez devinez que je m'amusais à construire un serveur Web en quelque sorte. C'est éffectivement presque le cas.
    Pour clarifié la chose, mon code écoute le port 80 avec un serversocket. Je pars du principe que mon programme sera sollicité par le protocole HTTP. J'ai donc étudié ce dernier et j'ai compris qu'il y a avait en gros deux mode de transfert de fichier, pour simplifier. Un mode texte, et un mode binaire. J'ai aussi remarqué que les navigateurs Web lorsqu'ils interrogent un serveur Web via HTTP soumettent une requête HTTP généralement pour demander une page html. Et tout de suite après avoir récupéré la page, les navigateurs envoient une requête supplémentaire automatiquement pour récupérer l'icône du site visité. Cette requête demande l'envoie d'un fichier sensé se trouver à la raçine du site et se nommé favicon.ico.
    J'ai alors ajouté dans mon dossier HTMLFiles, un fichier favicon.ico à côté du fichier index.html.
    Comme mon programme répond correctement à la requête de la page HTML, trouve le fichier via mon ClassLoader (dans NetBeans ou Hors NetBeans), et comme il sait répondre à plusieurs requêtes successives, j'ai été fier de moi de remarquer que cela fonctionne à merveille. Du moins lorsque je lance le code depuis NetBeans.
    En effet, depuis NetBeans, lorsque j'interroge mon programme avec mon navigateur web, je récupère bien ma page index.html, et je vois l'icône correspondant au fichier favicon.ico que j'ai ajouté dans HTMLFiles apparaît devant l'URL dans la barre d'adresse et devant le nom de l'onglet de la page. Pour bien comprendre la suite, je précise que cette icône représente un bonhomme qui cours juste vêtu d'un short, les cheveux au vent.
    C'est maintenant que cela devient étrange car comme je viens de le dire, en lançant le code depuis NetBeans, tout fonctionne parfaitement bien. Mais dés que je le lance hors NetBeans, je n'ai aucunes erreurs, mais mon icône n'apparaît pas entière ???? on ne voit que les pieds de mon coureur ???
    Je récapitule :
    - Lancement depuis NetBeans, favicon.ico apparaît entier dans l'onglet et devant l'URL.
    - Lancement en dehors de NetBeans, favicon.ico apparaît partiellement ?!...

    Quelqu'un aurait-il une idée ?
    Si cela est nécessaire, je peux montrer mon code....
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  2. #2
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 083
    Points
    7 083
    Par défaut
    getResource renvoie une URL et non un File. Si tu récupères le File de l'URL normal que ça ne fonctionne pas

    Quand tu envoies le flux de l'icône essayes de le flusher en fin de traitement. Et de fermer le flux.

    Pourquoi ne pas embarder JeTTy, Coyote ou Tomcat dans ton application ? Ca sera plus simple.
    Java : Cours et tutoriels - FAQ - Java SE 8 API - Programmation concurrente
    Ceylon : Installation - Concepts de base - Typage - Appels et arguments

    ECM = Exemple(reproduit le problème) Complet (code compilable) Minimal (ne postez pas votre application !)
    Une solution vous convient ? N'oubliez pas le tag
    Signature par pitipoisson

  3. #3
    Membre expérimenté
    Avatar de yotta
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Septembre 2006
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 088
    Points : 1 540
    Points
    1 540
    Par défaut Bonjour Nemek
    Merci de votre réponse. Malheureusement, je penses que cela tient à un manque de précision, mais soi-dit en passant, un File peut être construit sur une URI qui peut être fournie par une URL. Je ne vois absolument pas en quoi il serait impossible de récupérer un objet File via le ClassLoader et la méthode getRessource.
    Ex. :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    File fichierTest = null;
    fichierTest = new File(getClass().getClassLoader().getRessource("chemindanslejar/fichier.test").toURI());
    Quand au flush, je le réalise évidement en fin de boucle. Pour être vraiement plus claire, je vais placer ci-dessous le code qu'il faut, précédé d'une description de l'arborescence du jar exécutable :

    Arborescence : EntreeHTTP.jar

    /
    |--> HTMLFiles (créé dans NetBeans en tant que Folder)
    |..........|
    |..........|--> Index.html
    |..........|--> favicon.ico
    |
    |--> ecouteur (créé dans NetBeans en tant que package)
    ...........|
    ...........|--> EcouteurHTTPDev.java (Seule et unique fenêtre du prog.)
    ...........|--> Lanceur.java (ne contient que la méthode main)
    ...........|--> ProcessDialogue (implémente Runnable)
    ...........|--> ProcessEcoute (sous-classe SwingWorker)
    ...........|--> utilitaires (classe static contenant divers méthodes utilitaires)


    La méthode main de Lanceur se contente d'instancier EcouteurHTTPDev. A l'issue de son initialisation, EcouteurHTTPDev s'affiche à l'écran par lui-même.
    Il n'y a aucuns rapports directe entre la construction de cette fenêtre et le dialogue réseau qui me pose problème. Inutile donc d'en préciser le code. Cependant, cette fenêtre contient deux boutons dont la légende est explicite : [On Line] et [Off Line].
    Le bouton On Line est associé à ma classe ProcessEcoute, tout comme Off Line. Lors de sa première utilisation, le bouton instancie alors ProcessEcoute si nécessaire en lui passant en paramètre le JTextField que ma fenêtre contient, puis l'execute. Ceci afin de permettre à ProcessEcoute de tracer sa gestion sur le JTextField de ma fenêtre. Le bouton Off Line se contente d'invoquer la méthode d'arrêt de ProcessEcoute, ce qui entraîne sa finalisation. Voilà pour l'aspect graphique. Passons maintenant à ce qui nous intéresse, à savoir ProcessEcoute, et ProcessDialogue.

    ProcessEcoute gère l'écoute du port 80 de la carte réseau de mon système. Il réalise cela à l'aide d'une instance de ServerSocket.
    Le seul rôle de ProcessEcoute est d'instancier un ProcessDialogue en lui fournissant en paramètre le socket de la connexion qui vient d'être établie. Une fois ProcessDialogue instancié et lancé, ProcessEcoute boucle et recommence à écouter le port 80, etc, etc...
    Je penses qu'il n'est pas nécessaire d'encombrer ces explications avec le code de ProcessEcoute. Il n'est pas à l'origine du problème non plus.

    Examinons maintenant ProcessDialogue.
    Seules deux méthodes de cette classe sont en rapport avec le dialogue réseau : run() issu de l'implémentation de Runable, et traitement(String valeur), méthode privée permettant de faciliter la construction des entêtes HTTP de la réponse et en charge de l'intégration du fichier réponse.

    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
     
    public void run() {
       byte[] recept = null;
       OutputStream fluxSortie = null;
       try {
           while (!dialogue.isClosed()) {
              fluxReception = dialogue.getInputStream();
              recept = new byte[fluxReception.available()];
              int NbrLect = fluxReception.read(recept);
              if (NbrLect > 0) {
                 String contenu = new String(recept);
                 Object[] reponseTest = traitement(contenu); // Etude des entetes http et récupération éventuelle des paramètres de la requete http.
                 String rep = "<HTML>ERROR !!!</HTML>", memo = new String();
                 if (reponseTest[0] != null) {
                    if (reponseTest[1].toString().equals("text/html")) {
                       BufferedReader lecteur = new BufferedReader(new InputStreamReader((InputStream)reponseTest[0]));
                       while (lecteur.ready()) memo += lecteur.readLine() + "\n";
                       rep = utilitaires.faconneReponse(reponseTest[1].toString(), memo.length());
                       rep += memo;
                       byte[] reponse = rep.getBytes();
                       fluxSortie = dialogue.getOutputStream();
                       fluxSortie.write(reponse, 0, reponse.length);
                       fluxSortie.flush();
                       fluxSortie.close();
                       }
                    else {
                       InputStream lecteur = (InputStream)reponseTest[0];
                       int lng;
                       byte[] reponse;
                       fluxSortie = dialogue.getOutputStream();
                       while ((lng = lecteur.available()) > 0) {
                          reponse = new byte[lng];
                          lecteur.read(reponse);
                          fluxSortie.write(reponse);
                          }
                       fluxSortie.flush();
                       fluxSortie.close();
                       }
                    }
                 }
              }
           }
        catch (IOException e) {
           e.printStackTrace();
           }
        }
    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
     
    private Object[] traitement(String recept) {
            Object[] reponseTraitement = null;
            String[] parsing = recept.split("\\n");
            String methode = null, url = null, version = null;
            methode = parsing[0].split(" ")[0];
            url = parsing[0].split(" ")[1];
            version = parsing[0].split(" ")[2];
            if (methode != null && url != null && version != null) {
                if (methode.equalsIgnoreCase("GET") || methode.equalsIgnoreCase("HEAD") || methode.equalsIgnoreCase("POST") || methode.equalsIgnoreCase("PUT") || methode.equalsIgnoreCase("DELETE")) {
                    if (methode.equalsIgnoreCase("GET")) {
                        Properties params = new Properties();
                        if (url.indexOf("?") > 0) {
                            String parametres = url.split("\\?")[1];
                            String[] paramsParsing = parametres.split("\\&");
                            for (int i = 0 ; i < paramsParsing.length ; i++) params.put(paramsParsing[i].split("\\=")[0], paramsParsing[i].split("\\=")[1]);
                            }
                        String adresseInterne = "HTMLFiles" + url;
                        String type = null;
                        InputStream fluxSortie = null;
                        if (!url.matches(".+\\.[a-zA-Z]{2,4}")) adresseInterne += "Index.html";
                        if (adresseInterne.matches("(.+\\.htm)|(.+\\.html)|(.+\\.txt)|(.+\\.rtf)")) type = "text/html";
                        else type = "application/octet-stream";
                        reponseTraitement = new Object[2];
                        try {
                            fluxSortie = getClass().getClassLoader().getResourceAsStream(adresseInterne);
                            }
                        catch (Exception ex) {
                            ex.printStackTrace();
                            }
                        reponseTraitement[0] = fluxSortie;
                        reponseTraitement[1] = type;
                        if (params.isEmpty()) {
                            // Pas de parametres, on traite simplement l'url...
     
                        }
                        else {
                            // Il y a des parametres, ces derniers sont contenus dans params...
     
                            }
                        }
                    }
                else {
                    // Il ne s'agit pas d'un trafic web type HTML mais d'autre chose...
     
                    }
                }
            return reponseTraitement;
            }
    Lorsque je lance mon programme, après avoir cliqué sur mon bouton [On Line], ProcessEcoute écoute le port 80 de ma machine. Je lance alors mon navigateur Web dans lequel je saisie l'adresse http://adresse.ip.de.mamachine. C'est à ce moment là qu'il y a deux résultats possibles. Si je lance mon code depuis NetBeans, tout fonctionne à merveille. Mon navigateur réceptionne bien le fichier index.html et l'affiche. Ce dernier contient une baslie <A href> et elle est fonctionnelle. De plus, l'icône que j'ai placé avec le fichier index.html dans mon dossier HTMLFiles est bien envoyée à mon navigateur puisqu'elle apparaît devant la barre d'adresse, et dans le titre de l'onglet qui affiche la page. En second test, je complète l'url dans mon navigateur ainsi : "http://adresse.ip.de.mamachine/favicon.ico".
    Si tu as compris mon code ci-dessus, tu comprendras que ce dernier renvoie alors en type application/octet-stream le fichier favicon.ico qu'il va chercher dans le dossier HTMLFiles.
    Par contre, si je lance le programme en dehors de NetBeans, tout fonctionne de la même manière, à la différence prèt que l'icône est systématiquement incomplète. Comme je le précise dans mon premier post, cette icône représente un courreur. Et bien lorsque je lance mon application en dehors de NetBeans, je ne récupère que le bout d'un talon ?..... Et si je lance l'application depuis NetBeans, le coureur est entier ??????????
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  4. #4
    Membre expérimenté
    Avatar de yotta
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Septembre 2006
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 088
    Points : 1 540
    Points
    1 540
    Par défaut
    Ca ne dit rien à personne ???
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  5. #5
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    C'est tout de même étrange cette histoire, surtout que NetBeans devrait peu ou prou ne rien modifier à cette affaire.

    Juste histoire d'avancer un peu, ce serait possible de rajouter un log qui affiche l'URL résultant d'un getResource sur le favicon ? Qu'on puisse valider que le fichier est bien trouvé au même endroit.

    Il faudrait aussi vérifier que le fichier est correct dans le jar utilisé en dehors de NetBeans, par exemple en ouvrant le jar avec Winzip ou équivalent, en décompressant le fichier de l’icône et en l'ouvrant avec un éditeur d'image compatible.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  6. #6
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 083
    Points
    7 083
    Par défaut
    Citation Envoyé par pursang Voir le message
    Merci de votre réponse. Malheureusement, je penses que cela tient à un manque de précision, mais soi-dit en passant, un File peut être construit sur une URI qui peut être fournie par une URL. Je ne vois absolument pas en quoi il serait impossible de récupérer un objet File via le ClassLoader et la méthode getRessource.
    Ex. :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    File fichierTest = null;
    fichierTest = new File(getClass().getClassLoader().getRessource("chemindanslejar/fichier.test").toURI());
    Le fait d'avoir un accès ne signifie pas que l'appel est valide ...
    Lis la doc de File(URI) : uri - An absolute, hierarchical URI with a scheme equal to "file", a non-empty path component, and undefined authority, query, and fragment components.

    Ce n'est pas le cas de ton URI quand tu passes par un JAR

    Citation Envoyé par pursang Voir le message
    Quand au flush, je le réalise évidement en fin de boucle.
    Tu fermes également le flux ?


    Je regarderai le reste plus tard.
    Java : Cours et tutoriels - FAQ - Java SE 8 API - Programmation concurrente
    Ceylon : Installation - Concepts de base - Typage - Appels et arguments

    ECM = Exemple(reproduit le problème) Complet (code compilable) Minimal (ne postez pas votre application !)
    Une solution vous convient ? N'oubliez pas le tag
    Signature par pitipoisson

  7. #7
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    Sauf que là ce n'est pas le problème car dans ce cas il ne verrait rien du tout, même pas le début d'un orteil vu que le fichier ne serait pas trouvé.

    Idem pour la fermeture du flux en fin ou pas .. cela n'expliquerait pas la différence de comportement entre NetBeans et standalone. Les bonnes pratiques c'est bien mais c'est bien aussi d'essayer de résoudre le problème au lieu de partir dans tous les sens

    La seule chose que je vois pour l'instant c'est que pour une raison que j'ignore le fichier inclus dans le jar pourrait être corrompu et l’exécution dans NetBeans en trouvant un autre ailleurs, n'a pas ce problème.

    Sorti de ça, le classloader n'a rien à voir avec le problème vu qu'exécuter une application dans NetBeans ne modifie en rien le classloader utilisé.

    Autre piste, bien tracer quelle méthode est appelée pour envoyer le favicon, juste histoire d'être sur qu'une tentative n'est pas faite pour lire le favicon comme un fichier texte, auquel cas le premier caractère incompatible avec un char va planter le transfert, ce qui abouti a une image incomplète aussi.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  8. #8
    Membre actif Avatar de DarkMolo
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    207
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Maroc

    Informations forums :
    Inscription : Juillet 2006
    Messages : 207
    Points : 277
    Points
    277
    Par défaut
    Salut,

    J'ai cru comprendre que pour récupérer une ressource contenu dans son jar, il fallait utiliser "Thread.currentThread().getContextClassLoader()" plutôt que "getClass().getClassLoader()", je ne me rappelle plus pourquoi :s , j'essaierais de trouver une référence, essaie avec.
    Certified SCJP 5.0 / SCWCD 5.0 / SCEA 5.0
    C'est une grande folie de vouloir être sage tout seul.
    Duc de La Rochefoucauld

  9. #9
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    Citation Envoyé par DarkMolo Voir le message
    Salut,

    J'ai cru comprendre que pour récupérer une ressource contenu dans son jar, il fallait utiliser "Thread.currentThread().getContextClassLoader()" plutôt que "getClass().getClassLoader()", je ne me rappelle plus pourquoi :s , j'essaierais de trouver une référence, essaie avec.
    Jamais utilisé ça et pourtant j'accède très souvent à des ressources stockées dans mes jars et jamais eu de problèmes de ce genre à noter.
    Par contre j'utilise getResourceAsStream et pas getResource, bien sur.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  10. #10
    Membre actif Avatar de DarkMolo
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    207
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Maroc

    Informations forums :
    Inscription : Juillet 2006
    Messages : 207
    Points : 277
    Points
    277
    Par défaut
    En effet bulbo , je me suis trompé, désolé pour la mauvaise piste .

    J'avais utilisé le "Thread.currentThread().getContextClassLoader()" pour charger une ressource contenu dans un war(ou un jar dans le WEB-INF d'un war), ce qui n'avait pas marché avec "getClass().getClassLoader()".
    Certified SCJP 5.0 / SCWCD 5.0 / SCEA 5.0
    C'est une grande folie de vouloir être sage tout seul.
    Duc de La Rochefoucauld

  11. #11
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Points : 7 083
    Points
    7 083
    Par défaut
    Citation Envoyé par pursang Voir le message
    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
    public void run() {
       byte[] recept = null;
       OutputStream fluxSortie = null;
       try {
           while (!dialogue.isClosed()) {
              fluxReception = dialogue.getInputStream();
              recept = new byte[fluxReception.available()];
              int NbrLect = fluxReception.read(recept);
              if (NbrLect > 0) {
                 String contenu = new String(recept);
                 Object[] reponseTest = traitement(contenu); // Etude des entetes http et récupération éventuelle des paramètres de la requete http.
                 String rep = "<HTML>ERROR !!!</HTML>", memo = new String();
                 if (reponseTest[0] != null) {
                    if (reponseTest[1].toString().equals("text/html")) {
                       BufferedReader lecteur = new BufferedReader(new InputStreamReader((InputStream)reponseTest[0]));
                       while (lecteur.ready()) memo += lecteur.readLine() + "\n";
                       rep = utilitaires.faconneReponse(reponseTest[1].toString(), memo.length());
                       rep += memo;
                       byte[] reponse = rep.getBytes();
                       fluxSortie = dialogue.getOutputStream();
                       fluxSortie.write(reponse, 0, reponse.length);
                       fluxSortie.flush();
                       fluxSortie.close();
                       }
                    else {
                       InputStream lecteur = (InputStream)reponseTest[0];
                       int lng;
                       byte[] reponse;
                       fluxSortie = dialogue.getOutputStream();
                       while ((lng = lecteur.available()) > 0) {
                          reponse = new byte[lng];
                          lecteur.read(reponse);
                          fluxSortie.write(reponse);
                          }
                       fluxSortie.flush();
                       fluxSortie.close();
                       }
                    }
                 }
              }
           }
        catch (IOException e) {
           e.printStackTrace();
           }
        }
    Je t'ai mis en gras le code qui pose problème.

    Citation Envoyé par bulbo Voir le message
    Sauf que là ce n'est pas le problème
    Je répondais à la première question :
    Citation Envoyé par pursang Voir le message
    Pour réaliser cette opération, j'avais dans un premier temps utilisé la méthode getRessource de mon ClassLoader pour récupérer sous la forme d'un File ma ressource index.html. Et là, surprise ! Le code fonctionne parfaitement lorsque je l'exécute sous NetBeans, mais si je le lance en dehors de NetBeans, je constate que la construction du fichier échoue car la ressource n'est plus trouvée ?!
    comme disait l'autre vaut mieux apprendre à l'homme à pêcher que lui donner le poisson ...
    Java : Cours et tutoriels - FAQ - Java SE 8 API - Programmation concurrente
    Ceylon : Installation - Concepts de base - Typage - Appels et arguments

    ECM = Exemple(reproduit le problème) Complet (code compilable) Minimal (ne postez pas votre application !)
    Une solution vous convient ? N'oubliez pas le tag
    Signature par pitipoisson

  12. #12
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    Heu je confirme que le code en gras est berk pour rester poli

    Essaye voir plutôt quelque chose comme ça:

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    byte[] reponse = new byte[1024]; // buffer de taille arbitraire
    int nbRead = -1;
    while ((nbRead = lecteur.read(reponse)) > -1) {
         fluxSortie.write(reponse, 0, nbRead);
    }

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  13. #13
    Membre expérimenté
    Avatar de yotta
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Septembre 2006
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 088
    Points : 1 540
    Points
    1 540
    Par défaut
    Merci bulbo. Vous dites que mon code est beurk, je veux bien. Mais en quoi le votre n'est pas beurk ? Il fait exactement la même chose écrit de manière un peu plus condensé. La seule différence est que vous définissez un buffer de taille arbitraire (d'ailleurs, vous partez du principe que la méthode read ne renverra jamais plus de 1024 octets, je ne vois pas ce qui permettrai d'affirmer cela). Moi je me donne la peine de lui donner la bonne taille, je ne vois aucune différences ? Pourriez-vous me préciser en quoi c'est si beurk

    Merci Nemek, apparemment, vous êtes le seul a avoir lu attentivement mes posts. Et vos réponses sont intéressantes. J'avais effectivement fait une énorme erreur d’appréciation en m'orientant vers l'utilisation d'un File. Mais mon problème reste entier. Je ne m'explique toujours pas pourquoi j'obtiens un fonctionnement correcte (même si mon code ne l'est pas) dans NetBeans, et un fonctionnement différent hors de NetBeans ? De plus, je ne vois pas en quoi le problème se situe dans la partie de code que vous avez mis en gras ? J'ai pourtant réfléchi, cherché, mais je ne comprends toujours pas. Pourriez-vous être plus clair pour un amateur comme moi ?

    Afin d'illustrer un peu plus le problème, je joint à ce post deux petits cliché de mon écran. Un représente le résultat obtenu dans FireFox lorsque je lance mon application depuis NetBeans, lautre celui que j'obtiens lorsque je lance mon application en dehors de NetBeans.
    Si vous voulez, je peux mettre à votre disposition une archive rar de mon projet netbeans complet. Cela vous permettrai avant d'y apporter quelle que modification que ce soit d'exécuter le code dans ces deux contextes, et constater par vous même la différence de résultat. Et puis vous pourriez mieux pister ce qui cloche...
    Pour ma part, afin de pouvoir continuer à avancer, j'ai sorti mon dossier HTMLFiles de mon jar pour le poser au même endroit que ce dernier. Et je travailles en attendant avec des File pour lesquels ma méthode Beurk fonctionne parfaitement.

    Lancé depuis NetBeans :


    Lancé en dehors de NetBeans :
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

  14. #14
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    On va y aller ligne par ligne .. après tu fais comme tu veux, comme tu n'as pas l'air d'apprécier mes coups de main, tu feras sans pour la suite..

    while ((lng = lecteur.available()) > 0) {
    De la doc de InputStream: Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.

    Donc possible que parfois available te retourne 0 alors qu'il y a encore à lire. Ce n'est pas une condition d'arrêt valable dans tous les cas. Alors que le retour d'un read si !


    reponse = new byte[lng]; tu alloues un nouveau buffer à chaque lecture alors que tu peux réutiliser le même, bonjour l'utilisation de la mémoire et du GC pour rien. L'allocation doit être fait en dehors de la boucle.

    lecteur.read(reponse); tu ne sais pas combien tu as lu, tu perds l'info là.

    fluxSortie.write(reponse);Tu écris tout ton buffer alors que tu as peut-être lu moins que sa taille au final.

    J'ai pris un buffer d'une taille arbitraire juste pour lire bloc par bloc le fichier, ce qui est plus efficace que byte par byte.. tout simplement après si tu as de gros fichiers tu peux adapter la taille du buffer de lecture/ecriture suivant les performances constatée.

    Bulbo

    PS : ah oui j'oubliais .. on demande un coup de main mais on est tellement sur que ceux qui répondent sont a coté de la plaque qu'on n'essaye même pas la/les solutions proposées.

    1 - Pas de File pour acceder à des fichiers dans un jar.. ça ne peut pas marcher peu importe l'URI fournit à la classe File, il faut récupérer le stream. Que ça te plaise ou pas, ça marche comme ça.

    2 - Probable que le available sur l'inputStream retourné par un getResourceAsStream quand la resource est dans un jar (une archive) ne marche pas comme celui d'un FileInputStream.. et que donc ta méthode de lecture beurk ne puisse pas lire correctement les données.
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  15. #15
    Membre expérimenté
    Avatar de yotta
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Septembre 2006
    Messages
    1 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 088
    Points : 1 540
    Points
    1 540
    Par défaut
    Très bien. Pour commencer, je vais te présenter mes excuses bulbo. Je ne voulais pas être désagréable et je l'ai été. J'ai parfois tendance à être exagérément susceptible, et à la lecture de ta remarque sur le côté "berk pour rester poli" de mon code m'a effectivement blessé. En effet, j'ai bien remarqué que je faisait mal quelque chose, et c'est d'explications dont j'avais besoin. En te lisant, tu m'as rappelé un prof un peu nul (pas incompétent, juste nul) qui quant ses élèves ne comprenaient pas quelque chose se fâchait. Tes explications supplémentaires par contre sont elles utiles. Pour être claire, si tu m'avais tout de suite répondu cela sans faire de commentaire sur ton opinion personnelle concernant la qualité de mon code, j'aurai compris tout seul qu'il était effectivement berk. Maintenant, on va peut-être pas en faire une montagne non plus. Je vais faire un effort côté susceptibilité, et si tu me le permets, faits en un côté pédagogique.
    En attendant, ta dernière intervention m'a permis de comprendre et de corriger mon erreur, donc un grand MERCI.
    Une technologie n'est récalcitrante que par ce qu'on ne la connait et/ou comprend pas, rarement par ce qu'elle est mal faite.
    Et pour cesser de subir une technologie récalcitrante, n'hésitez surtout pas à visiter les Guides/Faq du site !

    Voici une liste non exhaustive des tutoriels qui me sont le plus familiers :
    Tout sur Java, du débutant au pro : https://java.developpez.com/cours/
    Tout sur les réseaux : https://reseau.developpez.com/cours/
    Tout sur les systèmes d'exploitation : https://systeme.developpez.com/cours/
    Tout sur le matériel : https://hardware.developpez.com/cours/

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec classLoader et classe interne
    Par croquette06 dans le forum Langage
    Réponses: 2
    Dernier message: 30/12/2012, 00h01
  2. Problème de classloading (?)
    Par Deaf dans le forum Général Java
    Réponses: 7
    Dernier message: 25/05/2012, 16h51
  3. Problème de ClassLoader dans l'utilisation d'un plugin Eclipse
    Par hanial dans le forum Eclipse Platform
    Réponses: 0
    Dernier message: 08/07/2011, 10h47
  4. Problème avec ClassLoader.getResource()
    Par julien_lesbegueries dans le forum Général Java
    Réponses: 3
    Dernier message: 05/03/2010, 17h02
  5. Problème de classLoader dans l'utilisation d'un plugin Eclipse
    Par Cluster37 dans le forum Eclipse Platform
    Réponses: 11
    Dernier message: 12/05/2008, 17h40

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