Marko Asplund wrote:
Simon Kitching wrote:
How about:
<t:div rendered="#{pageBean.showPopup}">
<f:verbatim>
<script type="text/javascript">
window.open("/popup.jsf", "popupwin", "....");
</script>
</f:verbatim>
</t:div>
Then in your method that is connected to the commandButton used to
submit the page, just set a flag so that showPopup returns true.
The flag will be false initially, so the script won't render. After a
successful submit, showPopup will return true so the script is rendered
and the window will open.
I would need to execute a backing bean method in order to generate
content (backing bean produces the whole response by streaming data
from a back-end server) for the new window.
Is there a better way to invoke the backing bean method than to create
an invisible submit button whose action/actionListener method is bound
to the method to be executed and modify the above Javascript code to
submit the form using the new button?
I've implemented exactly what you are describing just yesterday :-)
The solution I ended up with was for a page to use <t:outputLink> to
render a list of links to available documents. Each link looks like:
<h:outputLink value="/showDoc" target="document">
<f:param name="docId" value="#{row.id}"/>
<t:outputText value="#{row.docName}"/>
</h:ouputLink>
I then have a servlet mapped to "/showDoc" that gets parameter "docId"
from the request and passes it to an EJB to retrieve the doc contents
then writes it to the response (together with the appropriate http
headers). Note that the EJB performs the appropriate access checks to
ensure that the current user has access to that document.
I don't happen to need to access any JSF managed beans from that
servlet; it just needs access to the EJB layer. However if it was
necessary then I would have just used the code here to enable access to
JSF functionality:
http://wiki.apache.org/myfaces/AccessFacesContextFromServlet
If the anchor approach is used to create a new window (or javascript as
in my earlier reply) then the url used as the window content cannot be a
JSP page (including a JSF view) - or at least I couldn't get that
working. The problem is that JSP automatically sets up a "writer" for
the page to write to, and flushes it at end of the page. However the
existence of this writer prevents all access to the binary OutputStream
for the response; the flush throws an exception "Output Stream already
accessed" or somesuch. Don't know if this is an issue when using
Facelets, but it was the reason I had to implement the doc-serving code
as a servlet not a backing bean for a JSF page.
It is possible to stream the file contents from an action method in a
backing bean. However this will cause the file contents to be displayed
in the same browser window, not in a popup window. Well, not quite: for
Firefox the header "Content-Disposition: attachment" can be used to
force the data to appear in a popup. IE doesn't respect this setting
though. Serving the content from a backing bean action method does work
because there is never a "render" phase (the action sets
responseComplete). The FacesServlet therefore never has forwarded to a
jsp page, and therefore the jsp response-writer was never created.
However this limits the application to serving the content into the same
window that did the submit (for IE at least).
One last tip: IE plugins fail completely for "popup windows" if the
returned content has a "no-cache" header set. It appears that IE informs
plugins of the document content by passing them the name of a file in
the cache - which doesn't exist if an http header indicates no-cache.
The plugin then simply says "invalid data". This doesn't happen when the
same plugin is rendering content in the same window that did the submit,
even when no-cache is set. Bloody IE. Firefox has no problems of course.
Regards,
Simon