Primefaces Handle error on media PDF load - jsf

Is it possible to somehow handle error on loading a PDF?
<p:media value="/resources/media/myDoc.pdf" width="100%" height="800px" zoom="100" player="pdf" cache="false"<>/p:media>
Let's say the PDF document it's not there and won't find it, If that happens my web app crash. Possible to handle it? So I show an error message instead in growl for example?
Thanks

You can check the #Jasper de Vries comment, otherwise you can verify if the file is present using a bean method like this:
MyBean.java
public String findFileURL() {
String fileName = "myDoc.pdf";
String relativeWebPath = "/resources/media/" + fileName;
FacesContext facesContext = FacesContext.getCurrentInstance();
String absoluteDiskPath = ((ServletContext) facesContext.getExternalContext().getContext())
.getRealPath(relativeWebPath);
File file = new File(absoluteDiskPath);
if (file.isFile()) {
return relativeWebPath;
} else {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "File: " + fileName + " not found.", "");
facesContext.addMessage(null, message);
return "";
}
}
MyPage.xhtml
<p:media value="#{myBean.findFileURL()}" width="100%" height="800px" zoom="100" player="pdf" cache="false"/>

Related

How to show two pdf in differents tabs from java

Sorry for my poor english but I really want to show two pdf reports from jasper report at the same time in differents tabs on browser. I´m working with java jsf, primefaces. The principal idea is when the button is clicked show this reports in diferents tabs. I try to do this:
I have this in the Managed Bean:
public void showReports() {
RequestContext.getCurrentInstance().execute("document.getElementById('fromGeneral:rep2').click();");
RequestContext.getCurrentInstance().execute("document.getElementById('fromGeneral:rep3').click();");
}
public void printReport(String name) {
try {
Map<String, Object> mapParametros = new HashMap<>();
mapParametros.put("CORR", corr);
printJasper(mapParametros, new File("/Jasper/Reports/" + name));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public void printJasper(Map<String, Object> reportValues, File fileJ) {
ByteArrayInputStream input = null;
BufferedOutputStream output = null;
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
try {
facesContext = FacesContext.getCurrentInstance();
externalContext = facesContext.getExternalContext();
response = (HttpServletResponse) externalContext.getResponse();
FileInputStream file = new FileInputStream(fileJ);
JasperReport compiledTemplate = (JasperReport) JRLoader.loadObject(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
JasperPrint jasperPrint = JasperFillManager.fillReport(compiledTemplate, reportValues, dataSourceP.getConnection());
JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
exporter.setParameter(JRPdfExporterParameter.PDF_JAVASCRIPT, "this.print();");
exporter.exportReport();
input = new ByteArrayInputStream(out.toByteArray());
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(out.toByteArray().length));
response.setHeader("Content-Disposition", "inline; filename=\"ticket.pdf\"");
output = new BufferedOutputStream(response.getOutputStream(), Constants.DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[Constants.DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.flush();
} catch (Exception exception) {
System.out.println(exception.getMessage());
} finally {
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
} catch (Exception exception) {
/* ... */
}
}
facesContext.responseComplete();
}
An this in my view:
<h:form>
<p:commandButton value="Show them" action="#{reportBean.showReports()}"/>
<p:commandButton value="REPORT 1" id="rep1" style="font-size: 25px; float:right;visibility: hidden;" action="#{reportBean.printReport("Report1")}" ajax="false" onclick="this.form.target = '_blank';"/>
<p:commandButton value="REPORT 2" id="rep2" style="font-size: 25px; float:right;visibility: hidden;" action="#{reportBean.printReport("Report2")}" ajax="false" onclick="this.form.target = '_blank';"/>
</h:form>
But doesn´t work, it just show the second report.
Help!.
Thanks!
Try a hit using p:commandLink like i am using.
<p:commandLink id="PreviewR1" value="Print Preview" ajax="false" action="#{reportBean.printReport("Report1")}" target="_blank" />
<p:commandLink id="PreviewR2" value="Print Preview" ajax="false" action="#{reportBean.printReport("Report2")}" target="_blank" />
It will open the report 1 & 2 in separate browser tab while your original web page will remains the same.
You just don't click the correct buttons:
public void showReports() {
RequestContext.getCurrentInstance().execute("document.getElementById('fromGeneral:rep2').click();");
RequestContext.getCurrentInstance().execute("document.getElementById('fromGeneral:rep3').click();");
}
You're clicking on rep2 and rep3. rep3 doesn't exists, you need to click on rep1 instead. That should be the reason why only the 2nd report is shown.
Finally I found other way to solve it.
The method showReports() instead to click two buttons, this open two xhtml that each one has inside of <h.form> a remotecommand with autorun true, that show the reports. I don´t know if it´s the best way to do it, but It works.
Thanks for all your comments

Open generated PDF file into browser tab programmatically

I have created Pdf file on click action of Print button using Apache PDFBox api as shown below. As of now I saved that file into my drive(file system). What I need is to open up Pdf file directly into browser without saving into drive so that it can be print or download as require.
TestPdfBean.java
#ManagedBean(name = "pdfBean")
#ViewScoped
public class TestPdfBean implements Serializable {
public void createAndOpenPdf() {
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
PDFont font = PDType1Font.HELVETICA;
PDPageContentStream content = new PDPageContentStream(doc,page);
content.beginText();
content.setFont(font, 12);
content.moveTextPositionByAmount(100, 700);
content.drawString(" Generating Pdf content...");
content.endText();
content.close();
document.save("/home/ck/Test/test.pdf");
document.close();
}
}
Code snippet of test.xhtml
<h:form id="pdfForm">
<p:panelGrid columns="2">
<h:outputText value="Create Pdf file.." />
<p:commandButton value="Print" actionListener="#{pdfBean.createAndOpenPdf}" />
</p:panelGrid>
</h:form>
I have deployed above portlet into liferay-portal-6.1.1.
Is there any way to open up pdf file directly into browser by Primefaces Or by Jsf Or by Liferay ?
I would recommend that you take a look at the Liferay Faces jsf2-export-pdf-portlet demo for Liferay 6.1. It has an example of a JSF 2.x ResourceHandler that enables the PDF to be generated and downloaded.
Create an HttpServlet and give back the PDF in the response.
Then just link your commandButton to the URL of the servlet and you´re done ...
The browser will open the document if you return a ByteArrayOutputStream.
`FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
response.setContentType("application/pdf");
response.setHeader("Content-disposition", "attachement;filename=Quote_.pdf");
response.encodeRedirectURL("_blank");
byte[] bytes = printPDFBean.createQuotationPDF(current, cfgDoc, cfgEntity, quoteDetailList, customer).toByteArray();
response.getOutputStream().write(bytes);
context.responseComplete();`
This code calls my createQuotationPDF method which returns ByteArrayOutputStream object. The issue is, the document is opened in the current window and not a new one.
`public ByteArrayOutputStream createQuotationPDF(Quotation currentQuote, CfgDoc cfgDoc, CfgEntity cfgEntity, List<QuotationDetail> quoteDetailList, Customer customer) {
String filePath = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/");
String imagesFolder = filePath + FacesContext.getCurrentInstance().getExternalContext().getInitParameter("smefin.images");
String fontsFolder = filePath + FacesContext.getCurrentInstance().getExternalContext().getInitParameter("smefin.fonts");
PDDocument doc = null;
PDPage page = null;
ByteArrayOutputStream output;
output = new ByteArrayOutputStream();
try {
doc = new PDDocument();
page = new PDPage();
doc.addPage(page);
File fontLatoBlackFile = new File(fontsFolder + "Lato-Black.ttf");
File fontLatoLiteFile = new File(fontsFolder + "Lato-Light.ttf");
Encoding encoding = new WinAnsiEncoding();
PDFont fontLatoBold = PDTrueTypeFont.load(doc, fontLatoBlackFile, encoding);
PDFont fontLatoLite = PDTrueTypeFont.load(doc, fontLatoLiteFile, encoding);
content.beginText();
content.setFont(fontLatoBold, 11);
content.newLineAtOffset(50, 60);
content.showText("Text");
content.endText();
}
doc.save("D:/TestData/Quote_.pdf");
doc.close();
} catch (Exception e) {
System.out.println("" + e);
}
return output;
}`

How to display PDF in JSF, with content from ServletResponse

In my application, I use jsf & richfaces, I want to display a generated pdf in web browser , I have generated this PDF in serverside and it is available in ServletResponse, but I am unable to display it in my web page.
I have tried this question but, it did not solve my problem.
Is there any libraries or special ways to do this?
What I have tried to do is given below.
<h:commandLink rendered="#{ fileImportOptionsViewBean.isFileExist(status.myPdf) }" action="#
{fileImportOptionsViewBean.downloadFile(satus.myPdf)}" target="_blank">
<h:graphicImage url="../../resources/xyz/icons/pdf.png" /></h:commandLink>
downloadFile method
public void downloadFile(String filePath){
try {
File file=new File(filePath);
if(file.exists()){
FacesContext fc=FacesContext.getCurrentInstance();
ExternalContext ec=fc.getExternalContext();
ec.responseReset();
ec.setResponseContentType("application/pdf");
ec.setResponseHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
ec.setResponseBufferSize(8192);
OutputStream output = ec.getResponseOutputStream();
URL url = file.toURL();
try(
BufferedInputStream bis = new BufferedInputStream(url.openStream());
BufferedOutputStream bos = new BufferedOutputStream(output);
){
byte[] buff = new byte[8192];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
}
fc.responseComplete();
}
} catch (Exception e) {
}
}
Any help is appreciated,Thanks.
I don't see anything wrong with your current setup.Most probably the problem lies in your XHTML page and something is causing your h:commandLink not to fire the event.Please refer this post for further details,surely this will be of some help to you.

How to Download *.txt or *.log file in JSF [duplicate]

This question already has answers here:
How to provide a file download from a JSF backing bean?
(5 answers)
Closed 5 years ago.
I want to download a .txt/.log file saved in hard disk in JSF, am not getting any error but the issue is am not able to download the file, need some help..
note : am trying to zip the file first and then download.
I have tried :
response.setContentType("text/html");
response.setContentType("text/plain");
Code in page.xhtml:
<h:form>
<a4j:outputPanel id="downloadPanel">
<table><tr>
<td>
<h:commandButton id="dldFiles" title="Download File" image="/images/download.png"
style="width:20px; height:20px;"/>
</td>
<td>
<h:outputText value="Download log file" style="font-size: 11px; color:#56ADF8; font-weight: bold; cursor:pointer;"/>
</td>
</tr></table>
<a4j:support event="onclick" action="#{sqlLoaderAction.downloadFile}" reRender="uploadForm"></a4j:support>
</a4j:outputPanel>
</rich:panel>
</h:form>
In Actin Bean Methods:
public String downloadFile(){
System.out.println("--inside exportGoogleFeed--");
FacesContext fc = FacesContext.getCurrentInstance();
try{
User user = getUserBean();
Object sp = getServiceProxy(user);
HttpServletResponse response = ((HttpServletResponse)fc.getExternalContext().getResponse());
fc.responseComplete();
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition","attachment;filename=downloadname.zip");
OutputStream respOs = response.getOutputStream();
String dldFileName = "SQLLDR_28.txt";
PrintWriter pw1 = new PrintWriter(new FileWriter(dldFileName , false));
BufferedReader readbuffer = new BufferedReader(new FileReader("D:/Sqlldr_Container/downloadFile.txt"));
String strRead;
while((strRead=readbuffer.readLine())!=null){
pw1.println(strRead);
}
pw1.close();
File fil = new File(dldFileName);
ZipUploadStatusFile(dldFileName, respOs);
boolean bool = fil.delete();
System.out.println("-------Temp file Created deleted - "+bool+" ------------");
readbuffer.close();
}
catch (UnAuthenticatedException e) {
e.printStackTrace();
} /*catch (UnAuthorizedAccessException e) {
e.printStackTrace();
}*/ catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void ZipUploadStatusFile(String fileName, OutputStream respOs){
try{
ZipOutputStream out = new ZipOutputStream(respOs);
byte[] data = new byte[1000];
BufferedInputStream in = new BufferedInputStream
(new FileInputStream(fileName));
int count;
out.putNextEntry(new ZipEntry(fileName));
while((count = in.read(data,0,1000)) != -1){
out.write(data, 0, count);
}
in.close();
out.flush();
out.close();
System.out.println("Your file is zipped");
}catch(Exception e){
e.printStackTrace();
}
}
After executing the above method am getting below screen:
Thank you.....
You can't download files by ajax. JavaScript has due to security reasons no facilities to force a Save As dialogue. The best it could do in your particular case is to display the response inline.
Get rid of the <a4j:support> and make it a fullworthy synchronous request by putting the action method straight in the <h:commandButton>.
This is the code that will fulfill the needs of downloading text file in to client system.
public String downloadFileText() {
File file = new File(GlobalPath);
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.setHeader("Content-Disposition", "attachment;filename=file.txt");
response.setContentLength((int) file.length());
ServletOutputStream out = null;
try {
FileInputStream input = new FileInputStream(file);
byte[] buffer = new byte[1024];
out = response.getOutputStream();
int i = 0;
while ((i = input.read(buffer)) != -1) {
out.write(buffer);
out.flush();
}
FacesContext.getCurrentInstance().getResponseComplete();
} catch (IOException err) {
err.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException err) {
err.printStackTrace();
}
}
return null;
}
I dont think that the code will run fine because the code is in JSF MAnaged beans and it is running at server side, so file will be downloaded at the system where application server is running, now what you need to do is to check , use two pcs,
In one pc deploy the web and try to download file from other pc, then check the behaviour of code, if the file could be downloaded in client pc then thats fine other wise you need to find alternatives

How to override default file upload h:message in ICEfaces

i am using the ace:fileEntry component to upload files
and after successful upload i get the message that:
'File Entry' uploaded successfully 'filename'.
and i want to override this message and display other message (some kind of a summary for parsing that uploaded file), any ideas how ?
here's my code:
<h:form>
<ace:fileEntry id="fileEntryComp"
label="File Entry"
relativePath="uploaded"
fileEntryListener="#{mybean.uploadFile}"/>
<h:commandButton value="Upload Excel File" />
<h:message for="fileEntryComp" />
</h:form>
The fileEntry.getResults().getFiles() gives you an ArrayList of FileInfo objects.
If you upload only one file, you can get the FileInfo the following way:
FileInfo fileInfo = fileEntry.getResults().getFiles().get(0);
You should call the updateStatus method of the FileInfo the following way to override the default message:
fileInfo.updateStatus(new FileEntryStatus() {
#Override
public boolean isSuccess() {
return true;
}
#Override
public FacesMessage getFacesMessage(FacesContext facesContext,
UIComponent fileEntry, FileEntryResults.FileInfo fi) {
return new FacesMessage(FacesMessage.SEVERITY_INFO,
"My success message: " + fi.getFileName(),
"My success message: " + fi.getFileName());
}
}, true, true);
You have to create your own message and send it. It will overwrite the default message. Its a strange behavior but it will work.
public void uploadFile(FileEntryEvent e) {
FileEntry fe = (FileEntry)e.getComponent();
FacesContext ctx = FacesContext.getCurrentInstance();
FacesMessage msg = new FacesMessage();
msg.setServity(FacesMessage.SERVITY_INFO);
msg.setSummary("mysummary");
msg.setDetail("mydetail");
ctx.addMessage(fe.getClientId(),msg);
}
You can check the showcase: http://comp-suite.icefaces.org/comp-suite/showcase.jsf?grp=aceMenu&exp=fileEntry
You can override icefaces messages.
Default message bundle (just to know which message to ovverride) can be found in icefaces source package:
icefaces3/ace/component/src/org/icefaces/ace/resources/messages.properties
where:
org.icefaces.ace.component.fileEntry.SUCCESS = ''{0}'' has successfully uploaded ''{1}''
org.icefaces.ace.component.fileEntry.SUCCESS_detail = ''{0}'' has successfully uploaded ''{1}''
and these are lines I put in my application.properties file:
org.icefaces.ace.component.fileEntry.SUCCESS = File ''{1}'' caricato correttamente
org.icefaces.ace.component.fileEntry.SUCCESS_detail = File ''{1}'' caricato correttamente
be sure to have application.properties defined in faces-config.xml and visible by you application:
<application>
<message-bundle>application</message-bundle>
<locale-config>
<default-locale>en</default-locale>
</locale-config>
</application>
This can be done with all Icefaces default messages ...

Resources