I'm using BalusC's FileServlet example:
http://balusc.blogspot.com/2007/07/fileservlet.html
I'm able to get it to work, however, I would like to call a bean function before the download takes place. Is there a way to make that work? I tried with a4j:support and I also tried with h:commandLink and neither worked. Any help is appreciated!
You could do the file download job in bean's action method instead. For some concrete examples, see this answer: How to provide a file download from a JSF backing bean?
You only need to make sure that the request isn't made by Ajax, because the JavaScript language, who is responsible for handling the Ajax request, does not have any facilities to force a Save As dialogue for security reasons. So, use a plain <h:commandLink> or <h:commandButton> for this.
Related
I am currently learning JSF and was rather amazed and puzzled when I realized that whenever we use <h:form>, the standard behavior of JSF is to always show me the URL of the previous page in the browser, as opposed to the URL of the current page.
I understand that this has to do with the way JSF always posts a form to the same page and then just renders whatever page the controller gives it back to the browser which doesn't know the page location has changed.
It seems like JSF has been around for long enough that there must be a clean, solid way to deal with this. If so, would you mind sharing?
I have found various workarounds, but sadly nothing that seems like a real solid solution.
Simply accept that the URL is misleading.
Append "?faces-redirect=true" to the return value of every bean's action and then
figure out how to replace #RequestScoped with something else (Flash Scopes, CDI conversation, #SessionScoped, ...).
accept to have two HTTP round trips for every user action.
Use some method (e.g. 3rd party library or custom code) to hide the page name in the URL, always using the same generic URL for every page.
If "?faces-redirect=true" is as good as it gets, is there a way do configure an entire application to treat all requests this way?
Indeed, JSF as being a form based application targeted MVC framework submits the POST form to the very same URL as where the page with the <h:form> is been requested form. You can confirm it by looking at the <form action> URL of the generated HTML output. This is in web development terms characterized as postback. A navigation on a postback does by default not cause a new request to the new URL, but instead loads the target page as content of the response. This is indeed confusing when you merely want page-to-page navigation.
Generally, the right approach as to navigation/redirection depends on the business requirements and the idempotence (read: "bookmarkability") of the request (note: for concrete code examples, see the "See also" links below).
If the request is idempotent, just use a GET form/link instead of POST form (i.e. use <a>, <form>, <h:link> or <h:button> instead of <h:form> and <h:commandXxx>).
For example, page-to-page navigation, Google-like search form, etc.
If the request is non-idempotent, just show results conditionally in the same view (i.e. return null or void from action method and make use of e.g. <h:message(s)> and/or rendered).
For example, in-page data entry/edit, multi-step wizard, modal dialog, confirmation form, etc.
If the request is non-idempotent, but the target page is idempotent, just send a redirect after POST (i.e. return outcome with ?faces-redirect=true from action method, or manually invoke ExternalContext#redirect(), or put <redirect/> in legacy XML navigation case).
For example, showing list of all data after successful editing, redirect after login, etc.
Note that pure page-to-page navigation is usually idempotent and this is where many JSF starters fail by abusing command links/buttons for that and then complain afterwards that URLs don't change. Also note that navigation cases are very rarely used in real world applications which are developed with respect to SEO/UX and this is where many JSF tutorials fail by letting the readers believe otherwise.
Also note that using POST is absolutely not "more secure" than GET because the request parameters aren't immediately visible in URL. They are still visible in HTTP request body and still manipulatable. So there's absolutely no reason to prefer POST for idempotent requests for the sake of "security". The real security is in using HTTPS instead of HTTP and checking in business service methods if currently logged-in user is allowed to query entity X, or to manipulate entity X, etc. A decent security framework offers annotations for this.
See also:
What is the difference between redirect and navigation/forward and when to use what?
JSF implicit vs. explicit navigation
What URL to use to link / navigate to other JSF pages
Bookmarkability via View Parameters feature
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
When should I use h:outputLink instead of h:commandLink?
Creating master-detail pages for entities, how to link them and which bean scope to choose
Retaining GET request query string parameters on JSF form submit
Pass an object between #ViewScoped beans without using GET params
I have a Spring MVC application where I sometimes have to add a new object to a list, and at some point, save the page. At every point where I need to add something to a list, a controller action is called and when it is done adding it returns the page. The state of the page then is lost. (ie. scrollbar position). I would like to preserve the page state, also after saving the page (which does a redirect to the new page)
Right now I am putting some variables in the session, and reading them out EVERY time. I find this quite ugly.
Does anyone know like a solution to this? Or any third party dependency which can make my life easier on this? :)
Thanks in advance.
Ps. I hope my question is clear, and not too abstract. If so, I will try to clarify it more.
One way to avoid the complete page refresh is to use ajax. Submit the new List item via an ajax request and the browser will not perform the full refresh.
Exists another variant. You may perform AJAX call to Controller method and send only the data you need to save. After that through #ResponseBody annotation you can return refreshed data or any other result. So this solution force you to use AJAX call. You may use JQuery for this purpose.
I have a AjaxFormComponentUpdatingBehavior that i want to make synchronous
This denied feature request is exactly what would of saved me (had it not been denied) -https://issues.apache.org/jira/browse/WICKET-534
I know sync javascript is bad, however i cant live without it on this occasion.
any ideas would be greatly appreicated, or just a working example of the "work around" shown in the link supplied above,
thanks guys.
You can override the getAjaxCallDecorator() method, to return a custom AjaxCallDecorator that decorates the javascript ajax call with some code to block the interface (to disable the form components, or display a blocking div), and decorates the the result callbacks (both onSuccess e onError) to re-enable the form.
If this must be global (all ajax requests), you may do something similar with hooks in Wicket's ajax library.
I need to get access to EL functionality in a Servlet Filter, but... that means I am not within the FacesServlet lifecycle.
Thus, I need to instantiate an ELContext. I do not want to go down the road of instantiating a FacesContext, since that may cause issues when the application does forward to FacesServlet.
Suggestions? Thanks!
Better use a PhaseListener instead of a Filter.
Since I am writing a web-framework, there is no way to use a PhaseListener, this must be done inside the Servlet Filter.
However, I did find the solution in the Seam Solder (WeldX) CDI module - this only works when running on CDI.
http://docs.jboss.org/weld/extensions/reference/latest/en-US/html/elextensions.html
I'm not sure it makes sense to do this. Within a JSP context, you would be able to resolve JSP artefacts; within a JSF context, you would be able to resolve JSF artefacts. In a Filter, these artefacts are not going to be available to you.
If you just want to resolve expressions against objects you define, it is possible to create your own context (you may need to know the platform's ExpressionFactory class if you also want to create expressions).
There is probably a better way to achieve whatever it is you are doing, such as BalusC's suggestion of a PhaseListener.
I am trying to clear everything on my HTML form when I visit it from a hyperlink entry.
Any ideas? My development language is java.
are you using session-scoped data? if so, close your browser and open it again.
I'm not sure the application is, but one way to accomplish this would be to use JavaScript. For example, if it is acceptable to clear the form every time that page is visited you could write a quick function that clears the form when the page is loaded (i.e., using the onload event).
If you only want to clear the form when the page is hit from that link you could add a param to the URL (e.g., clearForm=true) and use JavaScript to pick up the query string and clear the form when that parameter is present.
This is, of course, a purely client-side solution. For a server-side solution it would be helpful to know what framework you are using.