I'm using Primefaces
p:fileDownload
to download a file which is not in class path.
So I'm passing FileInputStream as parameter to DefaultStreamedContent.
Every thing works fine when my bean is kept at @SessionScoped...,
But
java.io.NotSerializableException: java.io.FileInputStream
is thrown when I keep my bean in @Viewscoped.
My Code:
DownloadBean.java
@ManagedBean
@ViewScoped
public class DownloadBean implements Serializable {
private StreamedContent dFile;
public StreamedContent getdFile() {
return dFile;
}
public void setdFile(StreamedContent dFile) {
this.dFile = dFile;
}
/**
* This Method will be called when download link is clicked
*/
public void downloadAction()
{
File tempFile = new File("C:/temp.txt");
try {
dFile = new DefaultStreamedContent(new FileInputStream(tempFile), new MimetypesFileTypeMap().getContentType(tempFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
index.xhtml
<h:form>
<h:commandLink action="#{downloadBean.downloadAction}">
Download
<p:fileDownload value="#{downloadBean.dFile}"/>
</h:commandLink>
</h:form>
Isn't there any method to make it work?
The NotSerializableException
is thrown because the view scope is represented by the JSF view state which can in turn be serialized to HTTP session in case of server side state saving or a HTML hidden input field in case of client side state saving. The FileInputStream
can in no way be represented in a serialized form.
If you absolutely need to keep the bean view scoped, then you should not be declaring StreamedContent
as an instance variable, but instead recreate it in the getter method. True, doing business logic in a getter method is usually frowned upon, but the StreamedContent
is a rather special case. In the action method, you should then only prepare serializable variables which are later to be used during DefaultStreamedContent
construction.
@ManagedBean
@ViewScoped
public class DownloadBean implements Serializable {
private String path;
private String contentType;
public void downloadAction() {
path = "C:/temp.txt";
contentType = FacesContext.getCurrentInstance().getExternalContext().getMimeType(path);
}
public StreamedContent getdFile() throws IOException {
return new DefaultStreamedContent(new FileInputStream(path), contentType);
}
}
(note that I also fixed your way to get the content type; you have this way much more freedom to configure mime types via <mime-mapping>
entries in web.xml
)
The <p:graphicImage>
has by the way exactly the same problem with StreamedContent
. See also among others Display dynamic image from database with p:graphicImage and StreamedContent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With