Handle file download request in JSF 2.1 + PrimeFaces 5.1 - jsf

I have a web application in JSF 2.1 + PrimeFaces 5.1 that has a datatable where I list records from a database. Each row can be expanded to show some details, and there I have a button to download a XML file that has its contents saved in the DB.
<p:dataTable id="event_queue_table_id" var="event" value="#{eventQueueBean.eventQueue}" rowKey="#{event.id}">
...
<p:rowExpansion>
...
<p:commandButton ajax="false" icon="ui-icon-arrowthick-1-s" actionListener="#{eventQueueBean.downloadXml(event.id)}">
<p:fileDownload value="#{fileBean.file}"/>
</p:commandButton>
</p:rowExpansion>
</p:dataTable>
I want to fetch the XML contents from the DB, create the file and prompt the user to open/save it. The bean that controls this datatable looks like this:
#ManagedBean
#ViewScoped
public class EventQueueBean implements Serializable {
#ManagedProperty(value="#{fileBean}")
private FileBean fileBean;
public void downloadXml(BigDecimal eventId) {
try {
logger.entry(eventId);
DtoGetXmlEvent dtoGetXmlEvent = null;
if (eventId != null) {
dtoGetXmlEvent = eventQueueService.getXmlEvent(eventId);
String xml = dtoGetXmlEvent.getXml();
if (xml == null) {
// show error message stating that file does not exist
} else {
this.fileBean.download(xml, eventId + ".xml", "application/xml");
}
}
logger.exit();
} catch (...)
}
}
}
And my FileBean is:
#ManagedBean
#ViewScoped
public class FileBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = LogManager.getLogger(FileBean.class);
private StreamedContent file;
public FileBean() {
logger.entry();
}
public void download(String content, String fileName, String contentType) {
logger.entry(fileName, contentType);
InputStream stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
file = new DefaultStreamedContent(stream, contentType, fileName);
logger.exit();
}
public StreamedContent getFile() {
return file;
}
public void setFile(StreamedContent file) {
this.file = file;
}
When I try to download an empty XML (the DB retrieves NULL content), the open/save file prompt does not show, but if I try to refresh the page I get the "To display this page, Firefox must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.". How can I avoid this?

Related

How to get file upload path location for database by setter and getter in jsf

I m having trouble to set value for entity bean. the problem is that when i populate form file will be upload but i need file path to store in data base. In my bean i have used setter of employee entity to set file url but And I think the code is enough to set file path for database but data is storing on database leaving employeePicture as null..
#Named
#RequestScoped
public class EmployeeAddController {
private Employees employees;
private String fileNameForDataBase;
private Part file;
#Inject
private EmployeeUpdateService updateService;
#PostConstruct
public void init() {
employees = new Employees();
}
public Employees getEmployees() {
return employees;
}
public void setEmployees(Employees employees) {
this.employees = employees;
}
public String getFileNameForDataBase() {
return fileNameForDataBase;
}
public void setFileNameForDataBase(String fileNameForDataBase) {
this.fileNameForDataBase = fileNameForDataBase;
}
public Part getFile() {
return file;
}
public void setFile(Part file) {
this.file = file;
}
public void upload() throws IOException {
ServletContext ctx = (ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext();
String realPath = ctx.getRealPath("/");
int random =(int) (Math.random() * 10000 + 1);
String fileString= realPath + File.separator + "resources/image/employee"+random+".jpg";
employees.setEmployeePicture(fileString);
try (InputStream input = file.getInputStream()) {
Files.copy(input, new File(fileString).toPath());
}
}
public String addEmployee() {
try {
this.updateService.add(employees);
return "index?faces-redirect=true";
} catch (Exception e) {
return null;
}
}
}
in My jsf page
"<div class="form-group">
<h:outputText value=" Employee Picture" class="col-sm-3 control-label"/>
<div class="col-sm-9">
<h:inputFile value="#{employeeAddController.file}">
<f:ajax listener="#{employeeAddController.upload()}"/>
</h:inputFile>
<h:outputText value="#{employeeAddController.fileNameForDataBase}"/>
</div>
<div>
<h:message for="fileUpload" class="text-primary"/>
</div>
</div>"***strong text***

Handling currency using <h:selectOneMenu> in JSF

I'm using an <h:selectOneMenu>on the header of a template <p:layoutUnit position="north".../> as follows.
<h:selectOneMenu value="#{currencyRateBean.currency}" onchange="submit();">
<f:selectItems var="row" value="#{currencyBean.currency}" itemLabel="#{row}" itemValue="#{row}"/>
</h:selectOneMenu>
This list is populated using a List<String> representing a list of currencies. The list is stored in an application scoped bean, CurrencyBean.
The JSF managed bean involved is as follows.
#ManagedBean
#SessionScoped
public final class CurrencyRateBean implements Serializable
{
private static final long serialVersionUID = 1L;
private String currency;
private BigDecimal currencyRate;
public CurrencyRateBean() {}
#PostConstruct
private void init()
{
currencyRate=new BigDecimal(1);
}
public BigDecimal getCurrencyRate() {
return currencyRate;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) throws MalformedURLException, IOException
{
BufferedReader in = null;
URLConnection connection;
try
{
URL url = new URL("http://www.exchangerate-api.com/INR/"+currency+"/1?k=FQRxs-xT2tk-NExQj");
connection = url.openConnection();
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String jsonObject = "";
String line;
while ((line = in.readLine()) != null)
{
jsonObject += line;
}
this.currencyRate = new Gson().fromJson(jsonObject, BigDecimal.class);
this.currency = currency;
}
finally
{
if(in!=null){in.close();}
}
}
}
The setCurrency() method is invoked on changing a currency in <h:selectOneMenu> (onchange="submit();") which is a POST request as it should be.
After this request is completed, there is a duplicate page submit on refreshing the page. To avoid this duplicate submit, a GET Http request should arise after this POST request is made.
How can this be made?
Please suggest, if there is a better, new, precise alternative for handling a multi-currency application.
Try this, and avoid onchange as much as possible.
<h:selectOneMenu value="#{currencyRateBean.currency}">
<p:ajax event="valueChange" update="here write the id(s) of component(s) or "#all" to rerender the whole page (which is really bad)" process="#this" partialSubmit="true"/>
<f:selectItems var="row" value="#{currencyBean.currency}" itemLabel="#{row}" itemValue="#{row}"/>
</h:selectOneMenu>

Managed property between SessionScoped ManagedBeans

I have the following problem!
On one of my sites i have a button:
<h:commandButton value="IDA Analyzer Results" action="#{SelectionBean.monitoringLog()}"/>
The method it calls with some part of the bean:
#ManagedBean(name = "SelectionBean")
#SessionScoped
public class TableSelectionBean {
private List<String> analyzerLog = new ArrayList<String>();
public String monitoringLog() throws FileNotFoundException, IOException{
String fileName = "/opt/IDA2/Linux/bin/"+"filtered_"+selectionMonitoringData.get(0).getMonitoringName()+"_result.txt";
if(selectionMonitoringData.get(0).getIsExecuted())
{
BufferedReader br = new BufferedReader(new FileReader(fileName));
try {
String line;
while ((line=br.readLine()) != null) {
getAnalyzerLog().add(line);
}
} finally {
br.close();
System.out.println(getAnalyzerLog());
}
}
return "analyzerresult.xhtml";
}
After i click this button as you can see it navigates me to an other page:
<h:body>
<h:form>
<h:commandButton value="hi" action="#{AnalyzerBean.myMethod()}"></h:commandButton>
</h:form>
</h:body>
Here is the Bean:
#ManagedBean(name = "AnalyzerBean")
#SessionScoped
public class AnalyzerResultBean {
#ManagedProperty(value="#{SelectionBean.analyzerLog}")
private List<String> analyzerLog;
public void myMethod(){
System.out.print(analyzerLog);
}
/**
* #return the analyzerLog
*/
public List<String> getAnalyzerLog() {
return analyzerLog;
}
/**
* #param analyzerLog the analyzerLog to set
*/
public void setAnalyzerLog(List<String> analyzerLog) {
this.analyzerLog = analyzerLog;
}
So when I'm trying to use this Managed property it says:
The scope of the object referenced by expression #{SelectionBean.analyzerLog}, view, is shorter than the referring managed beans (AnalyzerBean) scope of session but as you can see both of the is Session Scoped. What could be the problem?
If you use JSF 2.x and you want to navigate analyzerresult.xhtml page return analyzerresult
public String monitoringLog() throws FileNotFoundException, IOException{
return "analyzerresult";
}
.xhtml extension is not needed.

show UploadedFile content from Primeface's p:fileUpload in same form without refresh

I'm trying to implement an ImageUpload and show the uploaded Image immediately on same page using DynamicImage. My Problem is, I can't force the p:graphicImage content be refreshed and show the uploaded image after uploading it.
#ManagedBean(name = "myformbean")
#Controller
#ViewScoped
#Data
public class MyFormBean implements Serializable {
private StreamedContent listImage = null;
public StreamedContent getListImage() {
if (listImage == null) {
try {
listImage = new DefaultStreamedContent(new FileInputStream("E:/t.jpg"), "image/png"); // load a dummy image
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
return listImage;
}
public void handleFileUpload(FileUploadEvent event) {
final UploadedFile uploadedFile = event.getFile();
listImage = new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()), "image/png");
}
}
And in .xhtml file:
<p:graphicImage value="#{myformbean.listImage}" />
if your upload does the work
all you need to do is to set id to <p:graphicImage like this
<p:graphicImage id="refreshMe" value="#{myformbean.listImage}" />
and in your <p:fileUpload set the update attribute to point to the image
like this
<p:fileUpload auto="true" ... update="refreshMe" ....

Icefaces tree + outputResource

I implemented a tree with an outputResource as "content" (see Downloading file from IceFaces tree).
However, when I try to download a file (I have only txt or csv files) I get the HTTP 500 Status error.
The tree structure is something like
Root
|-infoFiles
| |-A.csv
| |-B.csv
|-validateFiles
| |-C.txt
| |-D.txt
And the exception once I click on the resource is
java.io.FileNotFoundException: C:\SRC\dataFiles\998\validateFiles (Access denied)
java.io.FileInputStream.open(Native Method)
java.io.FileInputStream.<init>(FileInputStream.java:138)
java.io.FileInputStream.<init>(FileInputStream.java:97)
mx.gob.sagarpa.utilidades.FileResource.open(FileResource.java:39)
com.icesoft.faces.component.outputresource.RegisteredResource.open(OutputResource.java:474)
com.icesoft.faces.context.ResourceRegistryLocator$DynamicResourceDispatcherAdapter$DynamicResourceAdapter.open(ResourceRegistryLocator.java:117)
org.icefaces.impl.push.DynamicResourceDispatcher$ResourceServer.respond(DynamicResourceDispatcher.java:224)
org.icefaces.impl.push.DynamicResourceDispatcher$ResourceServer.handleResourceRequest(DynamicResourceDispatcher.java:201)
org.icefaces.impl.push.DynamicResourceDispatcher$Mapping.handleResourceRequest(DynamicResourceDispatcher.java:370)
org.icefaces.impl.push.DynamicResourceDispatcher.handleResourceRequest(DynamicResourceDispatcher.java:89)
org.icefaces.application.ResourceRegistry.handleResourceRequest(ResourceRegistry.java:75)
org.icefaces.impl.application.WindowScopeManager.handleResourceRequest(WindowScopeManager.java:165)
javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:591)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
Sometimes it happens just with csv files and sometimes even with txt
Tree.xhtml
<ice:tree id="tree"
value="#{treeBean.model}"
var="item"
hideRootNode="false"
hideNavigation="false"
>
<ice:treeNode>
<f:facet name="icon">
<ice:panelGroup style="display: inline">
<h:graphicImage value="#{item.userObject.icon}" />
</ice:panelGroup>
</f:facet>
<f:facet name="content">
<ice:panelGroup style="display: inline-block">
<ice:outputResource resource="#{item.userObject.resource}"
fileName="#{item.userObject.resource.filename}"
mimeType="#{item.userObject.resource.mimeType}"
/>
</ice:panelGroup>
</f:facet>
</ice:treeNode>
</ice:tree>
TreeBean.java
#ManagedBean
#ViewScoped
public class TreeBean implements Serializable {
private DefaultTreeModel model;
public final String openFolderImg = "./img/tree_folder_open.gif";
public final String closeFolderImg = "./img/tree_folder_close.gif";
public final String fileImg = "./img/tree_document.gif";
#ManagedProperty("#{userBean}")
private UserBean userBean;
#PostConstruct
public void init() {
// create root node with its children expanded
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
FileResourceUserObject rootObject = new FileResourceUserObject(rootTreeNode);
rootObject.setText("Sistema de RendiciĆ³n de Cuentas");
rootObject.setExpanded(true);
rootObject.setResource(new FileResource("Sistema de RendiciĆ³n de Cuentas", null));
rootObject.setBranchContractedIcon(openFolderImg);
rootObject.setBranchExpandedIcon(closeFolderImg);
rootTreeNode.setUserObject(rootObject);
// model is accessed by the ice:tree component
model = new DefaultTreeModel(rootTreeNode);
File f = new File("./998/");
createTree(f, rootTreeNode);
}
public DefaultTreeModel getModel() {
return model;
}
public UserBean getUserBean() {
return userBean;
}
public void setUserBean(UserBean userBean) {
this.userBean = userBean;
}
private void createTree(File fileRoot, DefaultMutableTreeNode treeRoot) {
File[] files = fileRoot.listFiles();
DefaultMutableTreeNode branchNode;
for (File f : files) {
if (f.isDirectory()) {
branchNode = new DefaultMutableTreeNode();
FileResourceUserObject branchObject = new FileResourceUserObject(branchNode);
branchObject.setExpanded(false);
branchObject.setText(f.getName());
branchObject.setResource(new FileResource(f.getName(), f.getAbsolutePath()));
branchObject.setBranchContractedIcon(openFolderImg);
branchObject.setBranchExpandedIcon(closeFolderImg);
branchNode.setUserObject(branchObject);
treeRoot.add(branchNode);
createTree(f, branchNode);
}
if (f.isFile()) {
branchNode = new DefaultMutableTreeNode();
FileResourceUserObject branchObject = new FileResourceUserObject(branchNode);
branchObject.setText(f.getName());
branchObject.setResource(new FileResource(f.getName(), f.getAbsolutePath()));
branchObject.setLeaf(true);
branchObject.setLeafIcon(fileImg);
branchNode.setUserObject(branchObject);
treeRoot.add(branchNode);
}
}
return;
}
}
FileResourceUserObject.java
public class FileResourceUserObject extends IceUserObject{
private FileResource resource;
public FileResourceUserObject(DefaultMutableTreeNode wrapper) {
super(wrapper);
}
public FileResource getResource() {
return resource;
}
public void setResource(FileResource resource) {
this.resource = resource;
}
}
FileResource.java
public class FileResource implements Resource{
private String filename;
private String fileAbsolutePath;
private String mimeType;
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
public FileResource(String filename, String fileAbsolutePath) {
this.filename = filename;
this.fileAbsolutePath = fileAbsolutePath;
this.mimeType = ec.getMimeType(filename);
}
#Override
public String calculateDigest() {
return filename;
}
#Override
public InputStream open() throws IOException {
return new FileInputStream(fileAbsolutePath);
}
#Override
public Date lastModified() {
return new Date();
}
#Override
public void withOptions(Options optns) throws IOException {
}
public String getFileAbsolutePath() {
return fileAbsolutePath;
}
public void setFileAbsolutePath(String fileAbsolutePath) {
this.fileAbsolutePath = fileAbsolutePath;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getMimeType() {
return mimeType;
}
}
UPDATE
What I noticed was that when I get the 500 Status Error the FileNotFoundException is always pointing to the same path java.io.FileNotFoundException: C:\SRC\dataFiles\998\validateFiles (Access denied)
I'm starting to think that all my FileResources are pointing to the same path... why is this happening?
There was a report of a bug on the IceFaces page where it says that using multiple outputResource tags had a strange behavior. See this link http://jira.icefaces.org/browse/ICE-3667
I think this was happening with I had the tree and many outputResource tags.
Moreover, I also read that using the outputResource tag it creates an Object at render time (or something like that I'm very new to JSF and all the stuff related) and it was memory-cpu consuming and it was better to use a servlet to perform the download. See http://www.dantoomeysoftware.com/pencils-down/2009/09/08/dont-use-icefaces-resource-for-download-use-a-download-servlet/
So it's better to implement a servlet, you can find useful info in http://balusc.blogspot.com/2007/07/fileservlet.html and (if your are new to all this stuff) Custom download servlet

Resources