I am generating pdf and displaying it in separate window/tab using the approach described in The BalusC Code: PDF handling.I need to display blockui ajax loader when i select the commandlink to display pdf.The pdf gets generated but the ajax loader image remains as it is.I need to manually refresh the page to hide it.Is there any way using which it can be hidden as soon as the pdf gets displayed.
My code snippet is as below
JSF page
<h:form id="subFrm">
<p:commandLink value="Download PDF" action="#{pdfBean.downloadPDF}"
onclick="blkUi.show()" oncomplete="blkUi.hide()" id="cmdLink"
ajax="false" />
<p:blockUI block="subFrm" trigger="cmdLink" widgetVar="blkUi">
processing...<br />
<p:graphicImage value="/images/ajaxLoader.gif" />
</p:blockUI>
</h:form>
snippet of Managed bean which is of request scope
#ManagedBean
#RequestScoped
public class PdfBean {
// Constants ----------------------------------------------------------------------------------
private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
// Actions ------------------------------------------------------------------------------------
public void downloadPDF() throws IOException {
// Prepare.
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
String filePath=externalContext.getRealPath("/pdf");
File file = new File(filePath, "modified.pdf");
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
// Open file.
input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
// Init servlet response.
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + "modified.pdf" + "\"");
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);
// Write file contents to response.
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
// Finalize task.
output.flush();
} finally {
// Gently close streams.
close(output);
close(input);
}
// Inform JSF that it doesn't need to handle response.
// This is very important, otherwise you will get the following exception in the logs:
// java.lang.IllegalStateException: Cannot forward after response has been committed.
//externalContext.redirect(((HttpServletRequest)externalContext.getRequest()).getRequestURI());
facesContext.responseComplete();
/*FacesContext.getCurrentInstance().getExternalContext()
.redirect("index.xhtml");*/
}
// Helpers (can be refactored to public utility class) ----------------------------------------
private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
// Do your thing with the exception. Print it, log it or mail it. It may be useful to
// know that this will generally only be thrown when the client aborted the download.
e.printStackTrace();
}
}
}
}
You don't need to open the blockui explicitly. Just remove the code from your commandLink
onclick="blkUi.show()" oncomplete="blkUi.hide()"
remove above. The BlockUI will show up and hides itself.
Related
In Struts2 Application I tried to have my Custome Result Type. but am getting no Effect, My JSP page image based action is not getting called.And No Exception am getting also.Please correct me where am doing wrong.
HTTPFox says 404 but am not getting anything in JAVA Console.
HTML :
<img src=" <s:url action='ExternalImageAction' />" />
XML :
<package name="externalImage_package" extends="struts-default">
<result-types>
<result-type name="myBytesResult" class="leo.struts.CustomeImageResult" />
</result-types>
<action name="ExternalImageAction" class="leo.struts.ExternalImageAction">
<result name="myImageResult" type="myBytesResult">
</result>
</action>
</package>
HTTPFOX :
00:18:06.762 0.044 432 1258 GET 404 text/html (NS_ERROR_FAILURE) http://localhost:8888/Struts2Whole/%3Cs:url%20action=%27ExternalImageAction%27%20/%3E
CustomeImageResult:
public void execute(ActionInvocation invocation) throws Exception {
ExternalImageAction action = (ExternalImageAction) invocation.getAction();
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType(action.getContentType());
response.getOutputStream().write(action.getImageInBytes());
response.getOutputStream().flush();
}
ExternalImageAction :
public String execute()
{
System.out.println("execute of the ExternalImageAction...........");
setContentType("jpg");
setImageInBytes(getFileBytes("C:/Users/Joseph.M/Desktop/ocwcd5.jpg"));
return "myImageResult";
}
public static byte[] getFileBytes(String filePath)
{
File file = new File(filePath);
System.out.println("file : "+file.getName());
byte[] b = new byte[(int) file.length()];
try {
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(b);
for (int i = 0; i < b.length; i++) {
System.out.print((char)b[i]);
}
fileInputStream.close();
} catch (FileNotFoundException e) {
System.out.println("File Not Found.");
e.printStackTrace();
}
catch (IOException e1) {
System.out.println("Error Reading The File.");
e1.printStackTrace();
}
System.out.println("byes of image size : "+b.length);
return b;
}
If you return something to the src attribute of an <img /> tag, it thinks it is an URL, try to open it and receives 404 Not Found.
Since you are not returning an URL, but the actual image in a byte array, you need to use a Data URI scheme as defined in RFC 2397.
Assuming your result only return the bytes, you should put the Data URI in the html, like described here: https://stackoverflow.com/a/20019398/1654265
Otherwise, you could return the complete Data URI (that must include the Mime Type) in the struts result itself, and keeping your current JSP unchanged.
Simply turn the byte[] to a Base64 String with Apache Commons's encodeBase64URLSafeString, append it to a String like data:image/jpeg;base64, and return that.
I want to use to generate a pdf dataexporter, use the method preprocessor to insert some content. By giving the type letter size page assimilates well as formats of texts. Then make a page break to put the chart on a new page, right there is the problem that generates the second page with other size and also find a way to change the font size of the text of the exported table.
<h:commandLink>
<p:graphicImage value="/images/pdf.png"/>
<p:dataExporter type="pdf" target="dataTableAddDetalles" fileName="pdf" preProcessor="#{serviciosMB.preProcessPDF}"/>
</h:commandLink>
backing bean
public void preProcessPDF(Object document) throws Exception {
try {
Document pdf = (Document) document;
pdf.open();
pdf.setPageSize(PageSize.LETTER);
ServletContext servletContext = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
String logo = servletContext.getRealPath("") + File.separator + "images" + File.separator + "header.gif";
// pdf.add(Image.getInstance(logo));
pdf.add(new Paragraph("EMNI", FontFactory.getFont(FontFactory.HELVETICA, 22, Font.BOLD, new Color(0, 0, 0))));
SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yyyy");
pdf.add(new Phrase("Fecha: " + formato.format(new Date())));
pdf.newPage();
} catch (Exception e) {
//JsfUtil.addErrorMessage(e, e.getMessage());
}
}
You can't do what you want using dataexporter, you need to change your code to:
<h:commandLink actionListener="#{serviciosMB.createPDF}">
<p:graphicImage value="/images/pdf.png" />
</h:commandLink>
And your managed bean:
public void createPDF() {
try { //catch better your exceptions, this is just an example
FacesContext context = FacesContext.getCurrentInstance();
Document document = new Document();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter.getInstance(document, baos);
if (!document.isOpen()) {
document.open();
}
PdfPTable pdfTable = exportPDFTable();
document.add(pdfTable);
//Keep modifying your pdf file (add pages and more)
document.close();
String fileName = "PDFFile";
writePDFToResponse(context.getExternalContext(), baos, fileName);
context.responseComplete();
} catch (Exception e) {
//e.printStackTrace();
}
}
exportPDFTable method:
private PdfPTable exportPDFTable() {
int numberOfColumns = 1;
itemOfList item = null;
PdfPTable pdfTable = new PdfPTable(numberOfColumns);
pdfTable.setWidthPercentage(100);
BaseFont helvetica = null;
try {
helvetica = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.EMBEDDED);
} catch (Exception e) {
//font exception
}
Font font = new Font(helvetica, 8, Font.NORMAL);
pdfTable.addCell(new Paragraph("columnName", font));
for (int i = 0; i < lstPdfTable.size(); i++) { //lstPdfTable is the list from your datatable. A List of "itemOfList" type
item = new itemOfList();
item = lstPdfTable.get(i);
//pdfTable.addCell(new Paragraph('any_string_field', font));
pdfTable.addCell(new Paragraph(item.getStringField(), font));
}
return pdfTable;
}
and writePDFToResponse method is:
private void writePDFToResponse(ExternalContext externalContext, ByteArrayOutputStream baos, String fileName) {
try {
externalContext.responseReset();
externalContext.setResponseContentType("application/pdf");
externalContext.setResponseHeader("Expires", "0");
externalContext.setResponseHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
externalContext.setResponseHeader("Pragma", "public");
externalContext.setResponseHeader("Content-disposition", "attachment;filename=" + fileName + ".pdf");
externalContext.setResponseContentLength(baos.size());
OutputStream out = externalContext.getResponseOutputStream();
baos.writeTo(out);
externalContext.responseFlushBuffer();
} catch (Exception e) {
//e.printStackTrace();
}
}
The primefaces documentation (as of 4.0) does not mention any ability to write a custom data exporter, only pre & post processors, which in the case of PDF prevents you from doing extensive modifications to data, etc.
But what you can do is create a package in your project called
org.primefaces.component.export
and copy ExporterFactory.java from primefaces source.
You can then replace the original PDFExporter call with your own implementation.
The exporter implementation is fairly simple. It uses iText library (although an outdated version) and you can easily extend it to your needs.
An obvious problem with this approach is that you may have to be extra careful when (and if) you are updating your primefaces library in the future.
I am working on blackberry project where i want to download image & save it in sd card in blackberry. By going through many sites i got some code & based on that i wrote the program but when it is executed the output screen is displaying a blank page with out any response. The code i am following is..
code:
public class BitmapDemo extends UiApplication
{
public static void main(String[] args)
{
BitmapDemo app = new BitmapDemo();
app.enterEventDispatcher();
}
public BitmapDemo()
{
pushScreen(new BitmapDemoScreen());
}
static class BitmapDemoScreen extends MainScreen
{
private static final String LABEL_X = " x ";
BitmapDemoScreen()
{
//BitmapField bmpFld1=new BitmapField(connectServerForImage("http://images03.olx.in/ui/3/20/99/45761199_1.jpg"));
//add(bmpFld1);
setTitle("Bitmap Demo");
// method for saving image in sd card
copyFile();
// Add a menu item to display an animation in a popup screen
MenuItem showAnimation = new MenuItem(new StringProvider("Show Animation"), 0x230010, 0);
showAnimation.setCommand(new Command(new CommandHandler()
{
public void execute(ReadOnlyCommandMetadata metadata, Object context)
{
// Create an EncodedImage object to contain an animated
// gif resource.
EncodedImage encodedImage = EncodedImage.getEncodedImageResource("animation.gif");
// Create a BitmapField to contain the animation
BitmapField bitmapFieldAnimation = new BitmapField();
bitmapFieldAnimation.setImage(encodedImage);
// Push a popup screen containing the BitmapField onto the
// display stack.
UiApplication.getUiApplication().pushScreen(new BitmapDemoPopup(bitmapFieldAnimation));
}
}));
addMenuItem(showAnimation);
}
private static class BitmapDemoPopup extends PopupScreen
{
public BitmapDemoPopup(BitmapField bitmapField)
{
super(new VerticalFieldManager());
add(bitmapField);
}
protected boolean keyChar(char c, int status, int time)
{
if(c == Characters.ESCAPE)
{
close();
}
return super.keyChar(c, status, time);
}
}
}
public static Bitmap connectServerForImage(String url) {
System.out.println("image url is:"+url);
HttpConnection httpConnection = null;
DataOutputStream httpDataOutput = null;
InputStream httpInput = null;
int rc;
Bitmap bitmp = null;
try {
httpConnection = (HttpConnection) Connector.open(url,Connector.READ_WRITE);
rc = httpConnection.getResponseCode();
if (rc != HttpConnection.HTTP_OK) {
throw new IOException("HTTP response code: " + rc);
}
httpInput = httpConnection.openInputStream();
InputStream inp = httpInput;
byte[] b = IOUtilities.streamToBytes(inp);
EncodedImage hai = EncodedImage.createEncodedImage(b, 0, b.length);
return hai.getBitmap();
} catch (Exception ex) {
System.out.println("URL Bitmap Error........" + ex.getMessage());
} finally {
try {
if (httpInput != null)
httpInput.close();
if (httpDataOutput != null)
httpDataOutput.close();
if (httpConnection != null)
httpConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmp;
}
public static void copyFile() {
// TODO Auto-generated method stub
EncodedImage encImage = EncodedImage.getEncodedImageResource("rim.png");
byte[] image = encImage.getData();
try {
// Create folder if not already created
FileConnection fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/images/");
if (!fc.exists())
fc.mkdir();
fc.close();
// Create file
fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/images/" + image, Connector.READ_WRITE);
if (!fc.exists())
fc.create();
OutputStream outStream = fc.openOutputStream();
outStream.write(image);
outStream.close();
fc.close();
System.out.println("image saved.....");
} catch (Exception e) {
// TODO: handle exception
//System.out.println("exception is "+ e);
}
}
}
This is the code which i am using. Not getting any response except blank page.. As i am new to blackberry development unable to find out what is the problem with my code. Can anyone please help me with this...... Actually i am having other doubt as like android & iphone does in blackberry simulator supports for SD card otherwise we need to add any SD card slots for this externally...
Waiting for your reply.....
To simply download and save that image to the SDCard, you can use this code. I changed your SDCard path to use the pictures folder, which I think is the standard location on BlackBerrys. If you really want to store it in images, you may just need to create the folder if it doesn't already exist.
package com.mycompany;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.file.FileConnection;
public class DownloadHelper implements Runnable {
private String _url;
public DownloadHelper(String url) {
_url = url;
}
public void run() {
HttpConnection connection = null;
OutputStream output = null;
InputStream input = null;
try {
// Open a HTTP connection to the webserver
connection = (HttpConnection) Connector.open(_url);
// Getting the response code will open the connection, send the request,
// and read the HTTP response headers. The headers are stored until requested.
if (connection.getResponseCode() == HttpConnection.HTTP_OK) {
input = new DataInputStream(connection.openInputStream());
int len = (int) connection.getLength(); // Get the content length
if (len > 0) {
// Save the download as a local file, named the same as in the URL
String filename = _url.substring(_url.lastIndexOf('/') + 1);
FileConnection outputFile = (FileConnection) Connector.open("file:///SDCard/BlackBerry/pictures/" + filename,
Connector.READ_WRITE);
if (!outputFile.exists()) {
outputFile.create();
}
// This is probably not a robust check ...
if (len <= outputFile.availableSize()) {
output = outputFile.openDataOutputStream();
// We'll read and write this many bytes at a time until complete
int maxRead = 1024;
byte[] buffer = new byte[maxRead];
int bytesRead;
for (;;) {
bytesRead = input.read(buffer);
if (bytesRead <= 0) {
break;
}
output.write(buffer, 0, bytesRead);
}
output.close();
}
}
}
} catch (java.io.IOException ioe) {
ioe.printStackTrace();
} finally {
try {
if (output != null) {
output.close();
}
if (connection != null) {
connection.close();
}
if (input != null) {
input.close();
}
} catch (IOException e) {
// do nothing
}
}
}
}
This class can download an image in the background, as I suggested. To use it, you can start a worker thread like this:
DownloadHelper downloader = new DownloadHelper("http://images03.olx.in/ui/3/20/99/45761199_1.jpg");
Thread worker = new Thread(downloader);
worker.start();
This will save the file as /SDCard/BlackBerry/pictures/45761199_1.jpg. I tested it on a 5.0 Storm simulator.
There are several problems with the code posted. It's also not completely clear what you're trying to do. From the question title, I assume you want to download a jpg image from the internet, and display it.
1) You implement a method called connectServerForImage() to download an image, but then it's commented out. So, the method isn't going to download anything if it's not called.
2) Even if it's uncommented, connectServerForImage() is called here
BitmapField bmpFld1=new BitmapField(connectServerForImage("http://images03.olx.in/ui/3/20/99/45761199_1.jpg"));
This will block the main (UI) thread while it downloads your image. Even though you can do it this way, it's not a good thing to do. Instead, you could create a Thread to download the image as a background task, and then use UiApplication.invokeLater() to load the image into your BitmapField on the main/UI thread.
3) Your copyFile() method tries to copy a file named rim.png, which must be an image bundled with your application, and saves it to the SDCard. Is this really what you want? Do you want to save the downloaded image instead? This method doesn't seem to be connected to anything else. It's not saving the image downloaded from the internet, and the image it does save is never used anywhere else.
4) In copyFile(), this line
fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/images/" + image, Connector.READ_WRITE);
is passing a byte[] in as part of the filename to open (your variable named image). You should probably be adding a String name to the end of your SDCard path. As the code is, it's probably opening a file in the /SDCard/BlackBerry/images/ folder with a very long name that looks like a number. Or it might fail entirely, if there are limits on the length of filenames.
5) In Java, it's not usually a good idea to make everything static. Static should normally be used for constants, and for a very few methods like the main() method, which must be static.
Try to clean these things up, and then repost the code, and we can try to help you with your problem. Thanks.
i am trying to embed twitter posting feature in my application.
i am using twitter api_me-1.8
i am able to reach the login screen(though most of the text is displayed as boxes- i am guessing that the text is in hindi/tamil as i am in india...), but as soon as i enter my credentials,i get taken to another page with some text in the top in boxes...
and more text in english below that(you can revoke access to any application...) ...then i get an illeagalArguementException after a minute...
i tried to debug the application,
public TwitterUiScreen(String wallMsg) {
System.out.println("Twitter UI BEGINS!");
setTitle("Twitter");
this.wallMsg = wallMsg;
BrowserContentManager browserMngr = new BrowserContentManager(0);
RenderingOptions rendOptions = browserMngr.getRenderingSession()
.getRenderingOptions();
rendOptions.setProperty(RenderingOptions.CORE_OPTIONS_GUID,
RenderingOptions.SHOW_IMAGES_IN_HTML, false);
rendOptions.setProperty(RenderingOptions.CORE_OPTIONS_GUID,
RenderingOptions.ENABLE_EMBEDDED_RICH_CONTENT, true);
rendOptions.setProperty(RenderingOptions.CORE_OPTIONS_GUID,
RenderingOptions.DEFAULT_FONT_FACE, true);
rendOptions.setProperty(RenderingOptions.CORE_OPTIONS_GUID,
RenderingOptions.DEFAULT_CHARSET_VALUE, true);
rendOptions.setProperty(RenderingOptions.CORE_OPTIONS_GUID,
RenderingOptions.JAVASCRIPT_ENABLED, true);
/*
* browserMngr.getRenderingSession().getRenderingOptions().setProperty(
* RenderingOptions.CORE_OPTIONS_GUID,
* RenderingOptions.DEFAULT_FONT_FACE, Font.getDefaultFont());
*/
add(browserMngr);
OAuthDialogWrapper pageWrapper = new BrowserContentManagerOAuthDialogWrapper(browserMngr);
pageWrapper.setConsumerKey(CONSUMER_KEY);
pageWrapper.setConsumerSecret(CONSUMER_SECRET);
pageWrapper.setCallbackUrl(CALLBACK_URL);
pageWrapper.setOAuthListener(this);
pageWrapper.login();
}
i had breakpoints upto the last line, and all of them were hit, with no problems...
but as soon as i logged in, i hit the exception.( i think it was in this page:-
BrowserContentManagerOAuthDialogWrapper.java (version 1.1 : 45.3, super bit)
after which i get to a third screen.
the comment was barely legible- so i thought i might as well add the code over here:
public static final String OAUTH_CALLBACK_SCHEME = "x-oauthflow-twitter";
public static final String OAUTH_CALLBACK_HOST = "callback";
public static final String OAUTH_CALLBACK_URL = OAUTH_CALLBACK_SCHEME+ "://" + OAUTH_CALLBACK_HOST;
private final String CALLBACK_URL = OAUTH_CALLBACK_URL;
i managed to get the source and attach it to the jar file. the exception that the BrowserContentManagerOAuthDialogWrapper.java throws is:: Protocol not found: net.rim.device.cldc.io.x-oauthflow-twitter.Protocol
in this method::
protected void loadUrl(final String url, final byte[] postData,
final Event event) {
new Thread() {
public void run() {
try {
HttpConnection conn = getConnection(url);
//
if (postData != null) {
conn.setRequestMethod(HttpConnection.POST);
conn.setRequestProperty(
"Content-Type",
"application/x-www-form-urlencoded");
conn.setRequestProperty(
"Content-Length", String.valueOf(postData.length));
//
OutputStream out = conn.openOutputStream();
out.write(postData);
out.close();
}
//
browserManager.setContent(
conn, renderingListenerOAuth, event);
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}.start();
}
feel like hitting myself.
my clients had told us that the twitter posting was not working...
so i assumed that it did not work.
for some reason, it does not work in the simulator- but seems to work fine on the device.
the clients have assumed that it does not work, as after we try logging in, it takes too long to post, and displays the third screen for about 20 seconds, and they seem to have clicked back early, deciding that posting did not work.
now i need to figure out a way to post a message on the third screen asking the user to wait for the post to be successful.
I am implementing an embedded browser in my app, and because it has to be compatible with OS 4.0, BrowserContent is my only choice.
When opening a HTTPS page the screen is blank, but this problem doesn't occur when a BrowserSession is used. So I put a println after the BrowserContent part, and it doesn't show up in the console output. So I think this is something wrong with that.
class BrowserScreen extends MainScreen {
private RenderingSession _renderingSession;
private HttpsConnection _connection;
public BrowserScreen(String url) {
_renderingSession = RenderingSession.getNewInstance();
final String _url = url;
new Thread() {
public void run() {
try {
_connection =
(HttpsConnection)Connector.open(_url, Connector.READ, true);
BrowserContent content =
_renderingSession.getBrowserContent(_connection, null, 0);
content.finishLoading();
Field field = content.getDisplayableContent();
synchronized (UiApplication.getEventLock()) {
add(field);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
}
There is a bug in the sample, and the BB people have done nothing in this regards for years.. You will never know that your page is not rendered and you will be redirected to the calling page all by itself. When they are unable to render the page they insert a redirection code in the HTTP response instead of giving a render exception (check it out in the inputstream and convert it into string and you shall know), and the intended page is never shown. They have resolved this in 5.0 and higher using BrowserField, but we need solution for the low end mobiles.