Question concerning remoting
campi Aug 13, 2007 6:58 AMHi,
I have a little problem that i cannot resolve, and I wanted to known your point of vue concerning my problem.
I'am using :
- EJB3
- SEAM 1.2.1-GA
- JPBM 3.1.4
- JRules 3.0.8
- ....
My problem is in a part of the application I need to generate forms using xml and xsl transformation. I have worked a lot on this point and everything is working fine except the upload of files. I'm explaining the problem.
I'am using :
@In (value="#{facesContext.externalContext}") private ExternalContext extCtx;
With this I can get all the data submitted, and with JAXB (classes generated from the xsd of the xml file) I stock the new xml with all the data into an eXist Database (xml database).
My problem is concerning the part where I need to download a file that where submitted to consult it. Due to the fact that I could map use jsf tag, I wanted to use seam remoting to access a method use to download, but the problem is that I don't have any access to the FaceContext when the javascript call is made...
I post my test code example :
The JSF Page :
<div class="main-part" id="main-part"> <script type="text/javascript" src="../seam/resource/remoting/resource/remote.js"></script> <script type="text/javascript" src="../seam/resource/remoting/interface.js?fileAction"></script> <script type="text/javascript"> //<![CDATA[ Seam.Remoting.setDebug(true); function download(fileName) { Seam.Component.getInstance("fileAction").downloadFromRemoteJavascript(fileName , downloadCallback); } function downloadCallback(result) { alert(result); } // ]]> </script> <h:form id="form1" name="form1" enctype="multipart/form-data"> <f:subview rendered="#{testAction.fileName!=null}"> <a href="#" onclick="javascript:download('#{testAction.fileName}');">Download #{testAction.fileName}</a><br/> </f:subview> File : <input type="file" id="idFileInput" name="nameFileInput" title="titleFileInput" /><br /> <div class="breaker" /> <h:commandButton action="#{testAction.submit}" value="Submit" /> </h:form> </div>
The coordination Action Bean that is called when I sumit the form:
@Name("testAction") @Stateful public class TestActionBean implements TestAction { @Logger private Log log; @In (value="#{facesContext.externalContext}") private ExternalContext extCtx; @In(create=true) private Processor processor; @In(create=true) private FileManager fileManagerLocal; private String fileName; @Create @Begin(join=true) public void begin() { log.info("Instanciation de la conversation"); } /** * @see ...#submit() */ public void submit() { log.info("Submit"); try { //on convertis la request en multipart MultipartRequest multipartRequest = (MultipartRequest)extCtx.getRequest(); //dans le cas où on aurait déjà uploadé un fichier, un supprime l'ancien fichier pour que le nouveau le remplace if(this.fileName!=null){ this.fileManagerLocal.deleteFile(this.fileName); } //on crée un objet de type Fichier avec les informations récupéré depuis la request Fichier fichier = new Fichier(); fichier.setFileContentType(multipartRequest.getFileContentType("nameFileInput")); fichier.setFileName(multipartRequest.getFileName("nameFileInput")); fichier.setFileSize(multipartRequest.getFileSize("nameFileInput")); fichier.setFileData(multipartRequest.getFileBytes("nameFileInput")); //on sauvegarde sur le disque le fichier et on conserve le nom unique de ce fichier this.fileName = FileTools.getFileNameFromUrl(this.fileManagerLocal.saveFile(fichier),"/"); } catch (IOException e) { log.error("Error : "+e); e.printStackTrace(); } catch (InterruptedException e) { log.error("Error : "+e); } } ...
The coordination Action Bean called into the javascript :
@Name("fileAction") @Stateless public class FileActionBean implements FileAction { // déclaration du logger @Logger private Log log; //Injections des managers situés dans les différentes couches services @In(create = true) private FileManager fileManagerLocal; /** * @see ...#downloadFromRemoteJavascript */ public boolean downloadFromRemoteJavascript(String fileName){ boolean result = false; try { //Récupération de l'object Fichier associé au réglement choisi log.info("Recherche du fichier en cours..."); Fichier fichier = fileManagerLocal.searchFile(FileTools.getFileNameFromUrl(fileName, "/")); if(fichier != null){ //this.popupFaceContextFileDownload(fichier); result = true; } else { FacesMessages.instance().addFromResourceBundle("file_not_found_exception"); } } catch (IOException e) { log.error("Erreur lors de la tentative de récupération du fichier nommée "+fileName+" : "+e.getMessage()); } return result; } /** * Méthode permettant de déclencher le popup de téléchargement du fichier qui a été demandé * @param Fichier fichier */ private void popupFaceContextFileDownload (Fichier fichier) throws IOException { FacesContext facesContext = FacesContext.getCurrentInstance(); HttpServletResponse response = (HttpServletResponse)facesContext.getExternalContext().getResponse(); response.flushBuffer(); response.setHeader("Content-Disposition", "attachment; filename=\"" + fichier.getFileName() + "\""); response.setBufferSize((int)fichier.getFileSize()); response.setContentLength((int)fichier.getFileSize()); response.setContentType(fichier.getFileContentType()); ServletOutputStream servletOutputStream = response.getOutputStream(); servletOutputStream.write(fichier.getFileData()); servletOutputStream.flush(); servletOutputStream.close(); response.flushBuffer(); facesContext.responseComplete(); } }
The service manager bean used into the two differents action bean of the coordination layer :
@Name("fileManagerLocal") @Stateless public class FileManagerBeanLocal implements FileManager { private static final String FILE_PROPERTIES = "file.properties"; private Properties properties = new Properties(); @Logger Log log; .... /** * @throws IOException * @throws InterruptedException * @see ...FileManager#saveFile(java.io.File) */ public String saveFile(Fichier fichier) throws IOException, InterruptedException { // Déclaration : String path; StringBuffer absolutePath; FileOutputStream fileOutputStream; // Traitement : path = properties.getProperty("savePath"); absolutePath = new StringBuffer(); /* Créer le chemin de sauvegarde */ absolutePath.append(path).append("/").append(DateTools.getFormattedDateNow()).append("-").append(fichier.getFileName()); /* Ecriture du fichier */ fileOutputStream = new FileOutputStream(absolutePath.toString()); fileOutputStream.write(fichier.getFileData()); fileOutputStream.flush(); fileOutputStream.close(); return absolutePath.toString(); } /** * @throws IOException * @see ...#searchFile(java.lang.String) */ public Fichier searchFile(String fileName) throws IOException { String path = properties.getProperty("savePath") + "/"; File searchedFile = new File(path + fileName); if (searchedFile.exists()) { Fichier fichier = new Fichier(); fichier.setFileData(this.readFile(searchedFile)); fichier.setFileName(searchedFile.getName()); fichier.setFileContentType(new MimetypesFileTypeMap().getContentType(searchedFile)); fichier.setFileSize(searchedFile.length()); return fichier; } else return null; } ... }
My is that i calling the method downloadFromRemoteJavascript form the fileAction Class when we arrive to the line commented that is calling the private methode popupFaceContextFileDownload :
FacesContext facesContext = FacesContext.getCurrentInstance();
The current instance is null so i cannot popup the download file. Any suggestion or advise will be welcome...
Thanks in advance,
Louis