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