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

JSF Java Discussion :

[RichFaces] Upload de fichier tout en postant les params du formulaire


Sujet :

JSF Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 143
    Par défaut [RichFaces] Upload de fichier tout en postant les params du formulaire
    Bonjour

    Je rencontre des difficultés avec le composant fileUpload de RichFaces. Le composant est placé au sein d'un formulaire comportant d'autres inputs. Je configure le fileUploadListener de façon à ce qu'une méthode d'un backing bean soit executée lorsqu'un fichier est uploadé. Le problème c'est que dans cette méthode, les autres input du formulaire sont null. Il semblerait que le composant fileUpload ne submite que le file mais pas les autres input du formulaire. Or j'ai aussi besoin de ces inputs.

    Voici le code de ma page :

    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
     
    <h:form>
    ...
    <tr>
    	<td colspan="4" align="center">
    		<rich:fileUpload
    		addControlLabel="Add the desired file ..."
    		fileUploadListener="#{monManagedBean.onUploadCompleted}"
    		maxFilesQuantity="1" acceptedTypes="csv"
    		/>
            </td>
     
    	<td align="right">
    		<h:outputLabel id="autreInputLabel" value="Autre input" />
    	</td>
    	<td align="left">
    		<h:inputText id="autreInput" value="#{monManagedBean.monAutreParam}" />
    	</td>
    </tr>
    ...
    </h:form>
    Le code du backing bean :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    private String monAutreParam;
    // getters et setters ...
     
    public void onUploadCompleted(final UploadEvent uploadEvent) {
    	final UploadItem uploadItem = uploadEvent.getUploadItem();
    	final File file = uploadItem.getFile();
            // ...  code où j'ai besoin de monAutreParam, mais à ce niveau il est toujours null
    }
    Voilà !

    Donc comment faire pour récupérer côté serveur, dans une méthode de mon backing bean, à la fois le file uploadé et tous les autres params du formulaire ?

    Merci d'avance pour votre aide

  2. #2
    Rédacteur

    Profil pro
    Inscrit en
    Juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 184
    Par défaut
    essaye avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <a4j:support event="onuploadcomplete" action="#{bean.action}" reRender="composant"  />

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 143
    Par défaut
    Merci pour ta réponse Sniper37.

    Le problème c'est que dans la méthode du bean spécifiée par l'attribut [action] du composant [a4j:support], je n'ai plus accès au fichier uploadé. En effet, une méthode d'action sur le managed bean ne prend pas de paramètre et je n'ai donc plus le UploadEvent qui me permettait d'avoir le fichier uploadé avec la méthode spécifiée par le [fileUploadListener].
    Donc, plutôt que d'utiliser le [fileUploadListener], j'utilise [uploadData] qui me permet de stocker dans mon managed bean la liste des fichiers uploadés. Mais là, même soucis. Dans la méthode du backing bean, ma liste de UploadItem est null. Et si je l'initialise dans mon constructeur pour éviter un NullPointerException, elle est vide. Bref j'ai perdu mon fichier uploadé.
    Cela semble logique étant donné que le fichier est uploadé dans un premier temps via une requête ajax et que l'appel à ma méthode se fait dans un second temps (sur l'évènement onuploadcomplete) par une autre requête. Le bean a dès lors perdu le fichier uploadé dans sa liste de UploadItem (le scope du managed bean est [request]).

    Ci-dessous mon code :

    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
     
    <h:form>
    ...
    <tr>
    	<td colspan="4" align="center">
    		<rich:fileUpload
    		addControlLabel="Add the desired file ..."
                    uploadData="#{monManagedBean.uploadedFiles}"
    		maxFilesQuantity="1" acceptedTypes="csv">
    		    <a4j:support event="onuploadcomplete" action="#{monManagedBean.process}" />
    		</rich:fileUpload>
            </td>
     
    	<td align="right">
    		<h:outputLabel id="autreInputLabel" value="Autre input" />
    	</td>
    	<td align="left">
    		<h:inputText id="autreInput" value="#{monManagedBean.monAutreParam}" />
    	</td>
    </tr>
    ...
    </h:form>
    et celui du managed bean

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    private List<UploadItem> uploadedFiles;
     
    private String monAutreParam;
    // getters et setters ...
     
     
    public String process(){
        LOGGER.debug("monAutreParam = " + this.monAutreParam);
        LOGGER.debug("file uploaded size = " + this.uploadedFiles.size());
        // ici this.uploadedFiles == null si je ne l'ai pas initialisée dans mon constrcteur
        // Ou this.uploadedFiles.size() == 0, si je l'ai initialisée
        return null;
    }
    Je pourrais remettre le fileUploadListener (qui lui reçoit bien le fichier) et enregistrer temporairement mon fichier uploadé à un endroit connu pour pouvoir le rattraper lors de la seconde requête qui soumet le reste du formulaire. Mais tout ceci serait bien lourd.

    Cela est assez énervant car avec une bonne vieille Servlet à l'ancienne et un <input type="file" ... > il n'y avait aucun problème. Certes on avait pas un composant qui fait de l'ajax et qui a un joli look avec progress bar et tout ça ; mais au moins c'était fonctionnel. Pour ma part, il est vraisemblable que je n'utilise peut-être pas ce composant comme il faut. Mais la doc est pauvre. J'ai lu en long en large et en travers la doc de RichFaces sur ce composant, les issues JIRA de RichFaces (j'ai même essayé les fonctions javascript beforeSubmit et submitForm) et rien n'y fait. C'est quand même décevant qu'un nouveau framework n'apporte pas de façon aisée ce qui est possible de faire facilement avec les technos sous-jacentes (Servlet).

    Bref. Comment faire pour que lors de la première requête ajax (lancée lorsque j'appuie sur le bouton [Upload] du composant RichFaces fileUpload) le fichier mais également les autres request paramaters de mon form soient transmis ?

    Merci

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 143
    Par défaut
    Ce qui est dingue en plus c'est que si je fais appel à cette petite méthode dans le code de onUploadCompleted (cf. premier message de cette discussion) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    	public static void printRequestParameters() {
    		final Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
    		for (final String paramName : params.keySet()) {
    			LOGGER.info(paramName + " => " + params.get(paramName));
    		}
    	}

    et bien je constate que les params de mon form sont bien postés.
    Pourquoi diable ne sont-ils donc pas settés dans les attributs de mon managed bean ?!

    Je vais les attraper à la main sinon comme je l'aurais fait dans une Servlet avec les HttpRequestParameters. Mais ce serait quand même dommage. Si j'utilise JSF c'est pour éviter de faire ça !

  5. #5
    Rédacteur

    Profil pro
    Inscrit en
    Juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 184
    Par défaut
    ton bean est en request ou session??

    Ce n'est pas normal que al liste des uploadItem soit null à la fin de l'upload,
    si ton bean est en request, lors de la requete ajax les paramètres sont bien envoyés, mas, ne seront sauvegardé que pour cette requete;

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 143
    Par défaut
    Mon bean est en scope request.
    Quand tu dis :
    mas, ne seront sauvegardé que pour cette requete;
    "cette requete" correspond à quoi ? La requête ajax qui part quand je clique sur le bouton Upload ou la requête qui part sur l'évènement onuplodcomplete ?

    Pour résumé voici comment je comprends le fonctionnement :

    A - Si je fais avec le fileUploadListener="#{monManagedBean.onUploadCompleted}"


    1) une requête HTTP part quand je clique sur le bouton Upload. Cette requête possède bien tous les request parameters mais JSF ne me les sette pas dans les attributs du bean. Je n'ai accès qu'à l'UploadEvent passé en paramètre de la méthode onUploadCompleted.

    Pourquoi mes attributs ne sont pas settés alors qu'il sont présents dans la requête HTTP ?


    B - Si je fais avec uploadData="#{monManagedBean.uploadedFiles}", que je garde mon fileUploadListener et que j'ajoute <a4j:support event="onuploadcomplete" action="#{monManagedBean.process}" />

    1) Idem. Une requête HTTP part quand je clique sur le bouton Upload. La méthode onUploadCompleted est appelée. Dans cette méthode je constate que ma List<UploadItem> uploadedFiles est bien remplie avec le fichier uploadé. Ce fichier correspond également au fichier que j'obtiens avec UploadEvent passé en paramètre de ma méthode onUploadCompleted ( final UploadItem uploadItem = uploadEvent.getUploadItem(); ).
    Par contre, les attributs de mon bean correspondant aux autres request parameters sont toujours null.

    2) Une seconde requête HTTP se lance sur l'évènement onuploadcomplete. Le bean étant en scope request il est re-instancié. La List<UploadItem> uploadedFiles est donc vide. La méthode process est appelée. Ici les autres request parameters du form sont disponibles. Hourra ! Mais le file uploadé ne l'est plus. Désespoir !


    Es-tu OK avec cette analyse ? Sinon je te remercie par avance de m'indiquer où je foire.

    Merci encore

  7. #7
    Rédacteur

    Profil pro
    Inscrit en
    Juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 184
    Par défaut
    quand tu fais un upload d'un fichier, ya une requete ajax envoyé au serveur,

    si tu utilise a4j:support, c'est une autre requete ajax, lorsque tu envoie le formulaire à la suite de tout ça, c'est une autre requete, les requêtes suivent le même cycle de vie JSF que ce soit une requete ajax ou une requête normale.
    donc, le setter est fait la première fois et le bean est réinitialisé à chaque requete.
    donc, pour résoudre le problème, il faut soit mettre le bean en session, soit utiliser a4j:keepAlive qui permet de garder le bean en vie pendant une période donnée.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 143
    Par défaut
    Désolé mais il est hors de question de polluer la session HTTP pour palier aux lacunes de l'outil. La RAM allouée à mon JBoss n'est pas infinie.

    Il est vraiment aberrant d'en arriver à mettre des beans en session alors que tout est dispo dans la HttpServletRequest sous-jacente !

    A l'intérieur de la méthode spécifiée par le fileUploadListener, je vais donc attraper les params dans la HttpServletRequest comme dans une bonne vieille Servlet. Au risque de passer pour un rétrograde, je pense que j'ai raison.

    Merci pour ton implication sur mon problème. Et je suis vraiment déçu de JSF. Cela permet de faire des trucs vraiment sympa style Swing pour le web, ajouter de la richesse avec des librairies de composant style RichFaces mais il y a des trucs vraiment rédhibitoires. Le sujet dont on vient de parler, mais aussi des appels intempestifs aux getters et setters pour satisfaire les différents cycle du process JSF (ValueChange, etc...), l'incompatibilité entre les différents navigateurs (faut voir la tronche du TogglePanel sur IE 7 !!!), etc.

    Bref. Je pense fortement à passer à Flex pour faire de la RIA lors des prochains projets de mon équipe. Facilité de développement de la GUI, communication avec BlazeDS, compatibilité assuré sur tous les navigateurs car s'exécutant dans le Flash Player, fonctionnalité très riches pour faire des graphiques (camemberts, histogrammes, etc.).

    A +

    Je laisse ce post ouvert au cas où quelqu'un me trouverait une solution pour faire marcher le rich:fileUpload en postant les autres params du form et en laissant le bean en scope request.

    Merci encore

Discussions similaires

  1. [2.x] Upload des fichiers dans plusieurs champs dans le même formulaire
    Par aitiahcene dans le forum Symfony
    Réponses: 1
    Dernier message: 15/06/2012, 11h53
  2. Upload de fichier après vérification d'un champ du formulaire
    Par knnwilliam dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 18/11/2009, 10h07
  3. Réponses: 2
    Dernier message: 28/11/2007, 21h02
  4. Enregistrer fichiers toutes les heures
    Par cflo91 dans le forum Langage
    Réponses: 3
    Dernier message: 06/07/2007, 12h11
  5. Upload 1 fichier,seulement son nom et pas toute l'adresse
    Par nebil dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 12/04/2006, 15h05

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