I want to open a pdf document on click of a command button. In its action method, I have an inputStream object from which I need to read the content and display the pdf document.
Have gone through IFileExportBean and its implementing classes, couldn’t find any of the implementing classes having a constructor / method which accepts an input stream or can write bytes to it by reading from an input stream in fixed size packets(may be with 1024B packet size) in an iteration.
Following implementing classes might be useful but not in our usecase :(.
FileContentExportBean - In my usecase, we should not create any temp file in any temp location to give that file path as an input to this class’s constructor. SimpleFileExportBean - In my usecase, as the documents which I am going to display are of larger size, I should not convert it to a byteArray(to avoid Java Heap space error) to give this byteArray as an input to this class’s constructor.
Do you have any idea if any other alternative is present which I can use to display contents by reading from an inputstream.
You can implement the IFileExportBean interface with your own class. For example, using an anonymous class like this:
final InputStream inStream = [TODO get input stream here];
//stream the file back to the user
streamFileDataToResponse(new IFileExportBean() {
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#isDownloadForced()
*/
public boolean isDownloadForced() {
return false; //open the file inline rather than forcing the user to choose what to do with it.
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#getExportContentLength()
*/
public int getExportContentLength() {
return IFileExportBean.UNKNOWN_CONTENT_LENGTH; //use this for unknown file size, or the actual file size if known.
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#getExportContentType()
*/
public String getExportContentType() {
String contentType = "application/pdf";
return contentType;
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#getExportFileName()
*/
public String getExportFileName() {
return "export.pdf";
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#isExportBinary()
*/
public boolean isExportBinary() {
return true;
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#writeExportBytes(java.io.OutputStream)
*/
public void writeExportBytes(OutputStream outStream) throws IOException {
byte [] buffer = new byte[1024 * 8]; //8k buffer
int len = -1;
while ( (len = inStream.read(buffer)) != -1 ) {
//copy the buffer to the outstream
outStream.write(buffer, 0, len);
}
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#writeExportText(java.io.PrintWriter)
*/
public void writeExportText(PrintWriter arg0) {
//not used, since the export is a binary file
}
});
I am having the same problem trying to display the bytes as an image on the screen.
But the way of linking image url to the action that does the streaming implementation you provided does not work because the action does not get invoked after all. I refer to the article below which I tried.
here is my action below, could you advise what is wrong, or is it another way doing this task.
Thank you
Leonard
/**
* Use this custom method to build the action url that you can bind to the
* Image control value.
*/
public String getDynamicImageURL() {
try {
IPortletURL actionUrl = createActionUrl();
// set the target action to an expression that resolves to the JSF action
actionUrl.setTargetAction("#{activePageBean.doStreamImage}");
System.out.println("----getting image url:" + actionUrl.toString());
return actionUrl.toString();
} catch (Exception e) {
e.printStackTrace();
error(e);
}
return null;
}
/**
* Use this custom action method to retrieve the image data and stream it
* back
*/
public String doStreamImage() {
System.out.println("---doStreamImage");
IFileExportBean fileExportBean = null;
try {
streamFileToUser();
} catch (Exception e) {
e.printStackTrace();
}
return OUTCOME_OK;
}
private void streamFileToUser() throws Exception{
final InputStream inStream = new BufferedInputStream(
new FileInputStream("C:\\path-to-dfs-sdk\\output\\09002329800130a8.pdf"));
//stream the file back to the user
streamFileDataToResponse(new IFileExportBean() {
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#isDownloadForced()
*/
public boolean isDownloadForced() {
return false; //open the file inline rather than forcing the user to choose what to do with it.
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#getExportContentLength()
*/
public int getExportContentLength() {
return IFileExportBean.UNKNOWN_CONTENT_LENGTH; //use this for unknown file size, or the actual file size if known.
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#getExportContentType()
*/
public String getExportContentType() {
String contentType = "application/pdf";
return contentType;
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#getExportFileName()
*/
public String getExportFileName() {
return "export.pdf";
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#isExportBinary()
*/
public boolean isExportBinary() {
return true;
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#writeExportBytes(java.io.OutputStream)
*/
public void writeExportBytes(OutputStream outStream) throws IOException {
byte [] buffer = new byte[1024 * 8]; //8k buffer
int len = -1;
while ( (len = inStream.read(buffer)) != -1 ) {
//copy the buffer to the outstream
outStream.write(buffer, 0, len);
}
}
/* (non-Javadoc)
* @see com.webmethods.caf.faces.bean.IFileExportBean#writeExportText(java.io.PrintWriter)
*/
public void writeExportText(PrintWriter arg0) {
//not used, since the export is a binary file
}
});
}
/**
* Action Event Handler for the control with id='button'
*/
public String button_action() {
String url = getDynamicImageURL();
System.out.println("----url: "+ url);
FacesContext context = getFacesContext();
url = "C:\\path-to-dfs-sdk\\output\\09002329800130a8.pdf";
url = context.getExternalContext().encodeResourceURL(url);
System.out.println("url: --"+ url);
// getHtmlGraphicImage().setUrl(url);
getHtmlGraphicImage().setValue(url);
System.out.println("url: ----"+ getHtmlGraphicImage().getUrl());
return null;
}
/**
* Getter method for the control with id='defaultForm:htmlGraphicImage'
*/
public com.webmethods.caf.faces.component.standard.HtmlGraphicImage getHtmlGraphicImage() {
return (com.webmethods.caf.faces.component.standard.HtmlGraphicImage)findComponentInRoot("defaultForm:htmlGraphicImage");
}
public com.webmethods.caf.is.wsclient.investecpoc.flows.front.documentum.doczwsd.GetContent1 getGetContent() {
if (getContent == null) {
getContent = (com.webmethods.caf.is.wsclient.investecpoc.flows.front.documentum.doczwsd.GetContent1)resolveExpression("#{GetContent}");
}
resolveDataBinding(GETCONTENT_PROPERTY_BINDINGS, getContent, "getContent", false, false);
return getContent;
}
public com.webmethods.caf.is.wsclient.investecpoc.ws.consumer.xpression.PublishAndReturnDocument getPublishAndReturnDocument() {
if (publishAndReturnDocument == null) {
publishAndReturnDocument = (com.webmethods.caf.is.wsclient.investecpoc.ws.consumer.xpression.PublishAndReturnDocument)resolveExpression("#{PublishAndReturnDocument}");
}
resolveDataBinding(PUBLISHANDRETURNDOCUMENT_PROPERTY_BINDINGS, publishAndReturnDocument, "publishAndReturnDocument", false, false);
return publishAndReturnDocument;
}
public com.webmethods.caf.is.wsclient.investecpoc.ws.consumer.xpression.PublishAndReturnDocument2 getPublishAndReturnDocument2() {
if (publishAndReturnDocument2 == null) {
publishAndReturnDocument2 = (com.webmethods.caf.is.wsclient.investecpoc.ws.consumer.xpression.PublishAndReturnDocument2)resolveExpression("#{PublishAndReturnDocument2}");
}
resolveDataBinding(PUBLISHANDRETURNDOCUMENT2_PROPERTY_BINDINGS, publishAndReturnDocument2, "publishAndReturnDocument2", false, false);
return publishAndReturnDocument2;
}
}
I applied the changes you advised and it almost works, i.e. the screen displays the correct image url in the debug section.
The problem is now likely with the image control configuration (Dynamic Image URL), where I am setting the Value->URL (or Value->Value) to my custom property DynamicImageURL that appears in the binding after defining the respective method getDynamicImageURL() that is actually called on the screen load.
I do not see anything wrong, and it worked for the other url images such as
Ok. If the action url is a relative url (starts with ‘/’ instead of http://) then the image control may be making the url relative to the portlet application servlet context instead of relative to the root (MWS) context.
If so, you can change the java code in your getDynamicImageURL method like this:
return "fe:" + actionUrl.toString(); //prepend fe: to make url relative to the mws front end url instead of this webapp context
…oh, one more thing you may need:
On your action URL, you probably will need to call this:
actionUrl.setAXSRFT(true);
which will add the anti-cross-site-request-forgery token to the URL which is required by default when running a portlet action from a url.
You should see an error like this in the MWS logs if the axsrft is missing:
2012-06-12 12:13:56 PDT (jsf:INFO) [RID:53] - [POP.016.0050] The target action was invalid: The target action "exportImageButton_action" requires an anti-xsrf token.
Now the action is triggered, url is right but the image still does not want to appear on load.javascript:emoticon(‘:roll:’);
As I mentioned when the action is called directly from the command action (‘Display Document’), the former brings the content to the whole screen.
To return user needs to use Backspace because all controls then replaced by the content.
So, I can not display content on load in the limited screen area, and limited to use push button with the full screen
Here is the project attached with the discussed portlet called Documentum, wamhich contains the image to stream.
The following line needs modification in regards of this image location.
I am trying to display an image inline in the CAF, I am not able to display image inline even though I tried all the methods that were discussed in this thread.
Are you able to verify the PortletAction method is getting called? Either using an attached java debugger or logging a message to the log file?
The way you are getting the image file looks suspicious and seems to violate the intent of that API (see ServletContext (Java EE 6 ) ). Instead of getting the file from the faces external context, you could probably just get the file directly instead. For example:
java.io.File file = new java.io.File("d:/wM8.2/checkImage.png");
IFileExportBean exportBean = new FileContentExportBean(file, false);