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

Services Web Java Discussion :

Supression fichiers temporaires


Sujet :

Services Web Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 17
    Par défaut Supression fichiers temporaires
    Bonjour à tous !

    J'ai récemment créer des web services qui ont pour mission de retourner des fichiers générés au niveau du serveur (fichier générés par l'appel au web service).

    Ces Web services sont déployés sur un serveur TOMCAT 5.5 avec AXIS 1.3

    mes web services sont du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public DataHandler generateFile(){
    MyConfig myConf = new MyConfig(); //classe perso créant un dossier temporaire sur le serveur ou les fichiers temporaires sont générés
    ...
    DataHandler ret = new DataHandlern(new FileDataSource(myConf.monfichier));
    return ret; // retourne les fichiers générés
    }
    le problème est que je voudrais que les fichiers générés au niveau du serveur soient supprimés après l'appel du Web service, c'est à dire après l'envoi du fichier.

    J'ai alors tenté d'utiliser un bloc: try ... finally a la fin de la méthode du Web service, comme ce qui suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    try{
    return ret;
    }finally{
    myConf.cleanUpFolders(); // méthode détruisant le dossier temporaire avec tout les fichiers qu'il contient
    }
    Mais ça ne fonctionne pas (FileNotFoundException) au niveau du serveur -> il semble que le fichier devant être envoyé a été supprimé (j'imagine un certain problème de synchro, ou alors c ptet que je n'ai pas tout compris au try ... finally)

    Donc deuxième solution, j'ai rajouté un destructeur dans ma classe MyConfig:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public void finalize(){
    cleanUpFolders();
    }
    Le problème ici est que l'appel au destructeur ne se fait QUE lorsque je redémarre le serveur (et un serveur n'est pas fait pour être redémarrer toutes les heures )

    Connaitriez vous une solution pour que mes web services envoient les fichiers (ce qu'ils font actuellement) ET détruisent les fichiers temporaires ?

    Merci pour votre aide !

  2. #2
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Bonjour,

    Il y a plusieurs choses qui ne sont très claires dans ton explication : Quel est le type des fichiers générés ? Normalement, le webservice retourne un flux, toi tu retournes autre chose ? De quelle façon les clients récupèrent-ils les fichiers ?

    Je ne sais pas vraiment à quoi sert ton webservice, mais je normalement tu te connecte à une url, et tu obtiens un flux SOAP par exemple, que tu captures et traites, donc aucun fichier n'est accédé par le client directement, tu as la gestion de tes fichiers cotés serveurs.. Peut-être que tu fais un autre type de traitement ?

    A+

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 17
    Par défaut
    le type de fichiers générés varie selon les services: certains renvoies un fichier zip d'autre un fichier txt.

    Le client récupère le fichier dans un DataHandler :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ...
    ret = (DataHandler) call.invoke(new Object[] { monparam});
    FileOutputStream archive = new FileOutputStream(savePath);// savepath étant un chemin local coté client, exemple : c:\\test.zip
    ret.writeTo(archive);
    archive.close();
    Mon service retourne donc bien un fichier qui est dans un DataHandler.

    Mon web service génére des fichiers de données bioinformatiques qui sont compressés dans une archive zip temporaire au niveau du serveur. Le serveur renvoie ce fichier au client via le webservice dans le datahandler. Une fois que le client a reçu le fichier je souhaite que le serveur supprime le fichier temporaire qu'il a créé (le client ayant récupéré le fichier, inutile de laisser le fichier temporaire sur le serveur).

    Je débute dans les Webs Services, peut etre que ce n'est pas la meilleure solution, mais tout fonctionne très bien tant que je ne tente pas de supprimer les fichiers temporaires au niveau du serveur.

  4. #4
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Ok,

    Pour envoyer des fichiers binaires via un flux SOAP, il faut utiliser l'encodage base64.
    Ainsi, ton fichier binaire est directement inclus dans le flux SOAP, et les personnes utilisant ton webservices y ont accès directement.

    Il existe la technologie XOP, mais uniquement disponible à partir de Axis version 2..

    Les clients de ton webservice sont ils connus, qu'utilisent-ils comme techno pour accéder et exploiter ton webservice ?

    A+

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 17
    Par défaut
    les clients sont connus, il passent parune interface client JAVA que j'ai mis au point.
    Par contre je ne vois pas la différence qu'il y a a utiliser un DataHandler et un encodage Base 64. Car actuellement mes web services tournent parfaitement bien (ils génerent les fichiers et les envoient aux clients) le seul problème est comment supprimer les fichiers après leur envoi.

    C'est pour ça que je ne pense pas qu'il s'agisse d'un problème d'encodage, a moins que tu as plus de détails à m'apporter.
    Ci dessous voici un exemple complet de l'appel de l'un des webservice:

    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
     
    public boolean sendForGraphicalResultsExpression(String fileName1, String fileName2, String dirName, String savePath, int goLevel, Double threshold) throws FileNotFoundException, IOException, RemoteException {
    		// send a VSM and a Concept extraction file in order to retrieve a ZIP file containing an interactive similarity network
    			DataHandler ret = new DataHandler(new FileDataSource(localpath+"myres.txt"));
     
    			DataHandler dhVSM = new DataHandler(new FileDataSource(fileName1));
    			DataHandler dhCLUST = new DataHandler(new FileDataSource(fileName2));
    			DataHandler[] dhClustFiles = getDirAttachments(dirName);
     
    			File clustDir = new File(dirName);
     
    			String[] filenames = clustDir.list();
     
     
    			call.removeAllParameters();
    			call.setTargetEndpointAddress(endpointURL);
    			call.setOperationName(new QName(webService, "Build_GO_Graphical_Results_Expression"));
     
    			QName qnameAttachment = new QName(webService, "DataHandler");
     
    			call.registerTypeMapping(
    				dhVSM.getClass(),
    				qnameAttachment,
    				JAFDataHandlerSerializerFactory.class,
    				JAFDataHandlerDeserializerFactory.class);
     
    			call.addParameter("golevel", XMLType.XSD_INT, ParameterMode.IN);
    			call.addParameter("dhVSM", qnameAttachment, ParameterMode.IN);
    			call.addParameter("dhCLUST", qnameAttachment, ParameterMode.IN);
    			call.addParameter("dhClustFiles", XMLType.SOAP_ARRAY, ParameterMode.IN);
    			call.addParameter("filenames", XMLType.SOAP_ARRAY, ParameterMode.IN);
    			call.addParameter("threshold", XMLType.XSD_DOUBLE, ParameterMode.IN);
     
    			call.setReturnType(qnameAttachment);
     
    			ret = (DataHandler) call.invoke(new Object[] { goLevel, dhVSM, dhCLUST, dhClustFiles,filenames, threshold });
    			FileOutputStream archive = new FileOutputStream(savePath);
    			ret.writeTo(archive);
    			archive.close();
     
    			return true;
    		}
    Le client envoie des fichiers a traiter au web service , ceux ci sont dans des DataHandler (dhVSm et dhCLUST) en retour le client récupère le fichier envoyé par le web service dans le DataHandler ret.

    Et ça tourne parfaitement.

    Mais je ne sais pas comment faire pour que le serveur supprime les fichiers qu'il a reçu et générés une fois que tout le traitement a été effectué.

    merci encore

  6. #6
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Je vois une solution "barbare" peut-être y-a-t-il mieux ?! Mais vu que tu as accès au client, je pense que c'est faisable...

    - Lors de la création de tes fichiers, générer un String deleteOrder (qui pourrait être un hash du fichier ret par exemple), et le passer dans le flux du webservice au client. Stocker la correspondance entre ton fichier à effacer et ce hash deleteOrder en mémoire, afin de pouvoir le retrouver plus tard.
    - Lorsque le client a bien tout récupéré, il fait une nouvelle requête au webservice, avec le paramètre deleteOrder reçu dans le flux passé en paramètre
    - Lorsque le serveur reçoit cette requête avec ce paramètre, il n'envoit aucun fichier et il ne fait qu'effacer les fichiers correspondants au deleteOrder reçu.

    Prévoir une moulinette d'effacement quotidien, pour effacer les fichiers qui n'auraient pas été effacés.

    Qu'en penses-tu ?

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 17
    Par défaut
    Merci pour ta réponse.

    J'ai bien pensé à cette solution, mais c'était en cas d'ultime recours :-(
    Je souhaitais (et souhaite toujours) que mon client n'effectue qu'une seule communication avec le service.

    Car l'objectif final de ces services est de mettre en place des méthodes d'enchainements automatiques, il me faut donc limiter les requetes intempestives.

    N'étant pas expert en java, je me demandais s'il n'existerait pas un moyen, au niveau du serveur et plus particulièrement au niveau du service d'indiquer dans le block 'finally' que le fichier a fini d'être envoyé. Je pourrais alors faire appel à la methode cleanUpFolders.
    Ce qui donnerais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    try {
        return ret;
    } finally {
      Tant que envoi pas fini
         attendre fin envoi
      fin tant que
      supprimer dossiers temporaires
    }
    Mais je ne suis pas sur que finally soit vraiement destiné à ce type d'opération.

    Ou alors, y'a t'il un moyen pour forcer AXIS a lancer le garbage collector après chaque utilisation de web service (du coup le destructeur de MyConfig ferait tout le boulot)

  8. #8
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Le finally sert à executer du code qui aurait autrement été inaccessible lorsqu'une exception est générée ( par exemple la fermeture des connections/flux ). Donc dans ton cas, je ne pense pas que ce soit applicable.

    Appeller le garbage collector ralentirait ton application, car non seulement ça concernerait ces objets, mais tous ceux de ton application..

    Je pense que le meilleur moyen est soit donc de laisser le garbage collector se déclencher quand il est necessaire, soit faire un script automatique ( lancé toutes les 10 minutes par exemple ) qui tenterait d'effacer les fichiers inutilisés, en ignorant les exceptions du type "FileNotFound" etc..

    Je ne vois rien d'autre, peut-être quelqu'un d'autre a une idée ?

  9. #9
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    J'ai quand même une question.

    Je n'ai jamais utilisé les DataHandler. Lorsque tu génères celui-ci, il se base sur un fichier sur disque non ? Ne peux-tu pas t'arranger pour que ce fichier sur disque soit mit en mémoire, ainsi une fois la mise en mémoire effectuée, tu pourrais tranquillement effectuer ton effacement ?

    Ca prendrait de la mémoire, mais normalement une telle mémoire serait rapidement purgée... Enfin il faudrait tester :o

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 17
    Par défaut
    Le DataHandler, apparemment se base sur un fichier sur disque.

    Pour le problème de mémoire, ce n'est pas envisageable, les webs services vont traiter des données de puces à ADN pangénomiques (donc énormément de données) -> je risque vite de surcharger la méoire. (meme si le futur serveur aura 6Go de mémoire, mes 512 risquent de ne pas suffir)

    Par contre je crois avoir trouver une solution:
    j'ai mis un destructeur dans ma classe principale (celle qui contient les webs services), ce destructeur fait appel à la méthode cleanUpFolders() dont j'ai parlé précédemment.

    Mon idée était que AXIS (ou TOMCAT, je ne sais pas qui fait le boulot) finirait bien à un moment ou un autre par se débarasser des anciennes instances de services (une fois leur exécution terminée)

    et => CELA FONCTIONNE !!!! <=

    j'ai lancé 5 appels au web service à suivre et au 6eme les anciens dossiers temporaires ont été supprimés !!!

    Merci Beaucoup pour ton aide et toutes les infos !
    (au bout de 8 heures de recherche de solution, ça fait du bien de trouver :-D)

  11. #11
    Membre Expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 868
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 868
    Par défaut
    Génial, félicitations, et merci de partager ta solution
    A+ et bonne continuation pour ton projet !

  12. #12
    kij
    kij est déconnecté
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 362
    Par défaut
    Bonjour,

    Juste pour compléter le thread, un DataHandler ne se base pas forcément sur un fichier système.

    Tu peux très bien mettre en mémoire ton fichier dans un stream d'octet / tableau d'octet, puis mettre ce tableau dans le handler et l'envoyer.

    Au client de savoir quel type de donnée se trouve dans le handler par la suite, pour l'extraire correctement. Cette information, tu la fournie normalement dans ta documentation pour le coup, ou dans un programme client de test.

    J'ajouterai qu'il est préférable lorsque ton web service retourne un dataHandler, de le joindre à la requète SOAP de retour, et non le déclarer comme tu l'as fait en tant que retour de ton web service.

    Pourquoi donc ? Simplement parce que tu peux très bien vouloir (ce qui n'est pas ton cas pour le coup) gérer une réponse "basique" de type "message d'information" au format XML.
    Dans les cas d'erreur, ta réponse XML sera un message d'erreur, sans DataHandler joint à ta réponse SOAP. Dans les cas où tout se passe bien, tu auras une réponse XML d'information de type "tout s'est bien déroulé", avec ton DataHandler joint au flux.

    Ainsi il t'es permis de répondre plusieurs informations à ton client. Et si tu souhaite ajouter des informations sur le fichier retourné (autre que le contenu donc), il t'es facilement possible de mettre à jour le squelette XML de ta réponse pour y incorporer ces informations, que le client se fera une joie d'interpréter ^^

    Ceci dans un soucis d'avoir un web service plus souple à maintenir, et plus "fonctionnel".

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

Discussions similaires

  1. Les fichiers temporaires
    Par mzt.insat dans le forum Administration système
    Réponses: 4
    Dernier message: 08/08/2005, 14h48
  2. [Applet] Créer un fichier temporaire
    Par leminipouce dans le forum Applets
    Réponses: 21
    Dernier message: 28/07/2005, 16h16
  3. [Tomcat]Tomcat Fichier temporaire
    Par kitiara999 dans le forum Tomcat et TomEE
    Réponses: 5
    Dernier message: 19/07/2005, 23h13
  4. Y as il des fichiers temporaires sous builder
    Par Moutonstar dans le forum C++Builder
    Réponses: 2
    Dernier message: 12/12/2004, 14h24
  5. Comment changer le répertoire des fichiers temporaires ?
    Par devdev dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 01/09/2004, 14h18

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