OVH Cloud OVH Cloud

[JDOM] problème avec SAXBuilder

23 réponses
Avatar
sylsau
Bonjour,

Mon probl=E8me est une peu particulier dans la mesure o=F9 il concerne
plusieurs domaines mais =E9tant donn=E9 que le vrai probl=E8me semble
venir de la classe SAXBuilder de l'API JDOM je pense qu'il a sa place
dans ce forum.
J'ai donc fait un programme JAVA qui prend en entr=E9e un fichier XML et
qui va dans un premier temps parser ce fichier, puis faire des
traitements sur les donn=E9es pars=E9es avant de finalement cr=E9er un
nouveau fichier XML r=E9sultat de ce traitement.

Ce programme fonctionne tr=E8s bien dans la console. Pour l'application
que je d=E9veloppe j'ai besoin de passer par php sur un serveur Apache2
donc pour utiliser le programme JAVA.

J'ai donc dans mon programme PHP utilis=E9 la fonction system("java
monProgramme donnees.xml", $retval); qui ex=E9cute la commande pass=E9e
en param=E8tre dans un shell. J'ai bien v=E9rifi=E9 que l'utilisateur sur
lequel tourne le serveur Apache2 a les droits n=E9cessaires, et que le
CLASSPATH et le PATH soient bien configur=E9s. D'ailleurs lorsque
j'=E9x=E9cute mon programme JAVA en mode console en =E9tant loggu=E9 sous
cet utilisateur tout marche bien.

Et l=E0, bizarrement quand j'ex=E9cute le programme, il y a un probl=E8me.
Apr=E8s pas mal de temps de recherche je suis arriv=E9 =E0 isoler ce qui
emp=EAchait le programme de fonctionner et apparemment cela viendrait de
la ligne suivante dans le programme JAVA :

[CODE]
SAXBuilder sxb =3D new SAXBuilder();
[/CODE]

J'ai r=E9duit au maximum mon programme pour ne laisser plus que =E7a dans
la classe principale du programme :

[CODE]
public ParseurDOM()
{
SAXBuilder sxb =3D new SAXBuilder();
System.out.println("Test");
}
[/CODE]

En ex=E9cutant le programme JAVA depuis PHP avec =E7a dans la classe
principale, j'ai un retour d'ex=E9cution =E0 1 qui indique qu'il y a une
erreur (qui ne peut donc venir que du constructeur SAXBuilder) et
l'affichage de la ligne "Test" ne se fait pas.

En enlevant l'appel au constructeur SAXBuilder(), j'ai bien l'affichage
de la ligne "Test". Le probl=E8me se situe donc dans le constructeur
SAXBuilder().

J'ai donc =E9t=E9 voir dans les sources de JDOM dans la classe SAXBuilder
et je ne vois rien de sp=E9cial en fait. Lors de l'instanciation, il y a
juste une instanciation de la classe DefaultJDOMFactory dont le
constructeur ne fait rien !

Donc, je ne vois vraiment pas d'o=F9 =E7a peut venir =E0 ce niveau l=E0, je
pensais =E0 un probl=E8me de localisation du driver SAX utilis=E9 par
SAXBuilder mais m=EAme en changeant et en mettant dans le constructeur
SAXBuilder() un driver SAX valide : org.apache.xerces.parsers.SAXParser
par exemple (et en modifiant le classpath), le probl=E8me reste le
m=EAme.

J'ai m=EAme tent=E9 d'utiliser d'autres API du m=EAme genre comme DOM4J ou
autres mais =E7a bloque toujours au m=EAme niveau lorsque l'on cr=E9e une
instance de la classe cherchant les drivers SAX apparemment.


Quelqu'un aurait une id=E9e de ce que je peux faire ? Peut-=EAtre
modifier des options dans Apache2 (je ne vois pas trop ce que je peux
modifier de plus en fait)? Modifier un chemin d'acc=E8s ? Ou peut =EAtre
cela ne peut pas se faire et =E7a ne marchera pas ?

Merci d'avance de votre aide.

10 réponses

1 2 3
Avatar
sylsau
Déjà merci de m'aidé :) que là je commence à être à cours
d'idées.

J'ai donc suivi tes conseils et j'a modifié le programme JAVA :

import org.jdom.*;
import org.jdom.input.*;
import java.io.*;


public class JDOM3
{
static org.jdom.Document document;
static Element racine;

public static void main(String[] args)
{
try
{

PrintStream out = new PrintStream("./test.txt");
System.setOut(out);
System.setErr(out);

}catch(Exception e1){

e1.printStackTrace();

}

//On crée une instance de SAXBuilder
try{
SAXBuilder sxb = new SAXBuilder();
System.out.println("test");


}catch(Throwable e){

e.printStackTrace();
}

}
}


J'exécute le même programme php que celui mis plus haut. Le code de
retour est toujours 1 mais ça ne crée pas de fichier test.txt ! C'est
vraiment bizarre là.

En revanche, lorsque je le fais en mode console ça marche et ça me
crée normalement le fichier test.txt avec à l'intérieur : "test"
Avatar
alexandre cartapanis
Déjà merci de m'aidé :) que là je commence à être à cours
d'idées.

J'ai donc suivi tes conseils et j'a modifié le programme JAVA :

import org.jdom.*;
import org.jdom.input.*;
import java.io.*;


public class JDOM3
{
static org.jdom.Document document;
static Element racine;

public static void main(String[] args)
{
try
{

PrintStream out = new PrintStream("./test.txt");
System.setOut(out);
System.setErr(out);

}catch(Exception e1){

e1.printStackTrace();

}

//On crée une instance de SAXBuilder
try{
SAXBuilder sxb = new SAXBuilder();
System.out.println("test");


}catch(Throwable e){

e.printStackTrace();
}

}
}


J'exécute le même programme php que celui mis plus haut. Le code de
retour est toujours 1 mais ça ne crée pas de fichier test.txt ! C'e st
vraiment bizarre là.

En revanche, lorsque je le fais en mode console ça marche et ça me
crée normalement le fichier test.txt avec à l'intérieur : "test"



Ben la...
Je sais pas, peut être que tu ne peux pas créer de fichier dans ton
répertoire, mais je suppose que tu as vérifié...

Sinon ben... je sais pas!

Bon je vais te donner des pistes en vrac (vraiment en vrac lol).
- est-ce tu n'aurais pas plusieurs VM installée?
- Je ne sais pas du tout comment PHP utilise Java, mais peut être que
y'a déjà des fonctions prévues pour récupérer la sortie...
- Ce qui est sur c'est que si ton programme marche dans la console et
pas dans PHP, ça viens quasi-certainement de PHP, donc ce n'est peut
être pas la peine de trop chercher autour de Java mais plutôt de PHP. ..
- Peut être que ton problème est un problème de mémoire... essaye de
rajouter un "-Xmx128m -Xms64m" au lancement de java...

--
Alexandre CARTAPANIS - Responsable Système et Réseau
Email
Gsm. 06 72 07 51 55

Macymed SARL - 9 bvd Kraëmer 13014 Marseille France
Tél. 04 91 48 31 58 - Fax. 04 91 02 36 47
Web http://www.macymed.fr - Email

Avatar
David JOURAND
J'exécute le même programme php que celui mis plus haut. Le code de
retour est toujours 1 mais ça ne crée pas de fichier test.txt ! C'est
vraiment bizarre là.


Tu ne dois pas avoir le droit en écriture dans le répertoire ou
s'exécute java... Mets un chemin absolu vers un répertoire dans lequel

PrintStream out = new PrintStream("/home/sylsau14/test.txt");

par exemple.

--
David Jourand

Avatar
sylsau
- Bon, il y a bien une seule JVM installé sur mon ordinateur
- Pour la récupération des sorties en PHP après exécution d'une
commande, je viens d'essayer la fonction passthru() qui fait à peu
près le même traitement que system() sauf qu'elle affiche le
résultat brut en sortie.

Et bien en utilisant cette fonction, il ne se passe rien comme
d'habitude (à croire qu'il y a une sorte de malédiction lol)

- J'ai testé avec les options -X mais ça ne change rien non plus

Enfin, je vais continuer à chercher mais j'y crois plus maintenant lol
. Merci de ton aide.
Avatar
sylsau
Je pense pas que ce soit un problème d'écriture pour 2 raisons :

- j'ai fait un chmod 777 -R * sur le dossier ou se trouve ces
programmes (au moins je suis sur que ça peut pas venir de là :) )

- et lorsque j'enlève l'appel au constructeur new SAXBuilder(); le
fichier test.txt s'écrit normalement.

C'est vraiment cette ligne qui bloque tout mais je comprends pas
pourquoi !
Avatar
sylsau
Bon, je viens d'essayer de changer d'API pour le parsing dans mon
programme JAVA.
J'ai tenté en utilisant le parseur fourni dans l'API xerces.

Et en fait, le bloquage se situe dans un endroit similaire encore lors
de l'instanciation de la classe qui initialise les drivers du parseur
utilisé.

Cette ligne bloque : parser = new DOMParser();

Ca voudrait peut être dire que c'est un problème de CLASSPATH mais
ça voudrait également dire que le CLASSPATH de www-data en mode
console n'est pas le même que celui de www-data lorsque Apache tourne
puisqu'en mode console ça marche.

Enfin, je reste sur l'affaire je continue à chercher lol
Avatar
David JOURAND
Ca voudrait peut être dire que c'est un problème de CLASSPATH mais
ça voudrait également dire que le CLASSPATH de www-data en mode
console n'est pas le même que celui de www-data lorsque Apache tourne
puisqu'en mode console ça marche.


Trouves le moyen d'afficher les messages de sortie... Quand tu auras le
logs tu auras l'exception, donc tu auras la cause de l'erreur, donc tu
auras la solution ! Si c'est un problème de classpath, tu doit avoir Une
ClassNotFoundException ou un truc dans ce genre là !

--
David Jourand

Avatar
sylsau
Ouais mais je n'arrive pas à mettre la main sur l'exception qui cause
cette erreur.
Etant donné que ça vient d'une autre classe et que cette classe ne
renvoie elle même aucune exception, il faudrait peut être que je
recompile toute l'API JDOM en mettant des messages de test dans
SAXBuilder.java notamment et que je refasse le jar ensuite.

Peut être ça me permettrait de mettre la main dessus.
Avatar
David JOURAND
Ouais mais je n'arrive pas à mettre la main sur l'exception qui cause
cette erreur.


Il y a toujours un moyen... Oui je sais ça énerve de lire ça ;-)


Etant donné que ça vient d'une autre classe et que cette classe ne
renvoie elle même aucune exception, il faudrait peut être que je
recompile toute l'API JDOM en mettant des messages de test dans
SAXBuilder.java notamment et que je refasse le jar ensuite.


Non !

Voila ce que je vous propose :
1 - faire une classe de test simple que vous appellerez depuis le
programme PHP :

public class Test {
public static void main (String[] args) {
PrintStream ps = new PrintStream("/var/tmp/test.txt");
System.setOut(out);
System.setErr(out);
System.out.println("test");
}
}

Après exécution vous devriez obtenir le fichier test.txt avec "test"
dedans.

2 - faire une autre classe TestSAX qui instancie le SAXBuilder avec le
catch, etc... Modifier la classe Test :

public class Test {
public static void main (String[] args) {
PrintStream ps = new PrintStream("/var/tmp/test.txt");
System.setOut(out);
System.setErr(out);
try {
System.out.println("Step 1");
TestSAX ts = new TestSAX();
System.out.println("Step 2");
ts.instanciateThatFuckingSAXBuilder();
System.out.println("Step 3");
} catch (Throwable t) {
System.out.println("FAILED");
t.printStackTrace();
}
}
}

3 - Bingo ? Or Not ?

--
David Jourand

Avatar
sylsau
Yes, Bingo !

J'ai fait ça pour le programme java :

import java.io.*;
import org.jdom.*;
import org.jdom.input.*;


class TestSAX{

TestSAX()
{

}

void instanciateSAXBuilder()
{
//On crée une instance de SAXBuilder
try{
org.jdom.input.SAXBuilder sxb = new org.jdom.input.SAXBuilder();

System.out.println("Constructeur de SAX");


}catch(Throwable e){

e.printStackTrace();
}
}

}

public class Test {
public static void main (String[] args) {

PrintStream ps = null;

try{

ps = new PrintStream("./test.txt");

}catch(Exception e){

e.printStackTrace();

}

System.setOut(ps);
System.setErr(ps);
System.out.println("test");

try {
System.out.println("Step 1");
TestSAX ts = new TestSAX();
System.out.println("Step 2");
ts.instanciateSAXBuilder();
System.out.println("Step 3");
} catch (Throwable t) {
System.out.println("FAILED");
t.printStackTrace();
}


}

}



Et Enfin, un message d'erreur (bravo pour avoir pensé à créer les 2
classes comme ça pour récupérer l'erreur dans la seconde :), j'y
aurais pas pensé !) . Voici le contenu du fichier test.txt après
l'exécution du programme :

test
Step 1
FAILED
java.lang.NoClassDefFoundError: org/jdom/input/SAXBuilder
at Test.main(Test.java:51)

Donc effectivement c'était bien un problème de classe non trouvée.
Il y a donc bien une différence entre le CLASSPATH pour l'user
www-data à la compilation puisque ça compile bien et le CLASSPATH
disponible lors de l'exécution via la fonction PHP apparemment.
Ou peut être c'est un problème de droit. www-data n'a pas le droit
d'accéder au répertoire /usr/share/java/jdom.jar lors de l'exécution
depuis php.
1 2 3