JSF CustomeScope reset for specified view - jsf

How can I control what customscope is created during request. Right now I have solution that when I click the commandLink:
<h:commandLink action="orders">
<f:actionListener type="com.mk.web.jsf.scope.ResetScopeListener" />
<span data-shortcut="F6" class="start_link">Orders</span>
</h:commandLink>
The custom scope is destroyed and a new one is created. But the problem is that the custom scope only resets if I enter the customers action using this commandLink from above.
When I enter to customers action by directly entering the url in browser the custom scope is not reset. How can I make that is customers action is loading even by commandLink or by url then always this custom scope should be reset. Can somebody give me some advice how to achieve this?
Thanks...

Typically you use a custom scope when you want your beans to live longer than the original request but shorter than the session. Based on your scenario though, it seems to me that your custom scope is behaving slightly like a request scope. Anyway, maybe I'm not understanding your scenario fully but one thing that comes to mind is that you can use system events in case a user decides to go to the next page when they type the address directly. So suppose the user tries to go to nextPage.xhtml, it could be defined like this
<f:event type="preRenderView" listener="#{bean.performPossibleCustomScopeCleanUp}" />
<h:head>
</head>
The (pseudo) method above will fire before the view root (aka nextPage.xhtml) is rendered. Inside the method you can check to see if your custom scope is still "alive" and you will handle it as needed. Keep in mind though that this event will be fired every time the page is requested. For instance, if you click the h:commandLink performPossibleCustomScopeCleanUp will still be invoked. There are ways around that
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Just scroll down to the section Performing business action on GET parameters of the answer
An even better approach would be to implement a custom NavigationHandler through JSF's ConfigurableNavigationHandler API so you can keep track of the URL and perform actions as needed.
I didn't dig too dig so you might actually find a better code sample. Hope this helps.

Related

h:commandButton with an action and then page-navigation in JSF?

Is it possible to have a commandButton that executes a method of a certain backing bean and then also navigates to a different page?
I know that I could return a String in the method that the commandButton calls, but the method is also used on the target-page, meaning it's often called from that same page.
So for calls that come from the same page, the redirect would be unnecessary and I would like to avoid that.
The options that I have in mind right now:
Create a separate method for the "remote" call of the method that does the same logic and also redirects to the page
Use an additional h:button and use JavaScript so that if the commandButton is pressed, the h:button is pressed at the same time (Probably bad practice tho)
Any option I am missing? Is there any way to tell the commandButton itself that it's supposed to navigate somewhere or do I have to implement this in the backing-beans?
Your title and first sentence are 'dangerous' and sort of not on topic since to both, the answer is yes and you sort of describe (= answer) that in your second paragraph already yourself.
The real question further on effectively asks about conditional navigation. But let me state first that your solution of two methods is also not wrong if you just make sure you don't do actual work in the bean (which you should not).
Now conditional navigation is by itself not difficult
returning null (to stay on the same page) without a refresh, "" to stay on the same page with a refesh,
return the new page (with redirect).
All basic JSF which I assume you are already aware of and this just requires something to do one or the other
So then the question remains if you can
detect the page you are on when the method is executed or
pass on a parameter to the action
which in turn can be used to return null or the other new page in an if/else.
Page1:
<h:commandButton action="#{mybean.action(true))" />
Page2:
<h:commandButton action="#{mybean.action(false))" />
Bean:
public String action(boolean navigate) {
doWork();
if (navigate) {
return "page2.xhtml?faces-redirect=true";
} else {
return null;
}
And if you'd want it, you could even pass null or the page name as a parameter to the method call.
Implementing detection of the source page of the action has the advantage that in the UI you do not need any knowledge on how to navigate, you always call the same method without any parameters and each new page you'd use this action on navigates to the right page without the developer needing any knowledge.
So take you pick.
I'm not completely sure if I got you right, but you could do something like this:
<h:commandButton value="Click" action="otherPage.xhtml?faces-redirect=true">
<f:actionListener binding="#{bean.method}" />
</h:commandButton>
Keep in mind that actionListener will be fired first and after that action from commandButton. Hope it helps.
Update:
Due to the fact that there was no further thinking you can use commandButton with or without redirect.
<h:commandButton value="Click" action="{bean.method}"/>

How to stop action delete when reload page in jsf [duplicate]

We're using JSF 2.0 on WebSphere v8.5 with several component libraries PrimeFaces 4.0, Tomahawk 2.0, RichFaces, etc.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed, or when the submit button is clicked once again. I have many applications with different scenarios.
For now I have considered disabling the button with a piece of JavaScript in onclick attribute, but this is not satisfying. I'm looking for a pure Java implementation for this purpose, something like the Struts2 <s:token>.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed
For that there are at least 2 solutions which can not be combined:
Perform a redirect after synchronous post. This way the refresh would only re-execute the redirected GET request instead of the initial request. Disadvantage: you can't make use of the request scope anymore to provide any feedback to the enduser. JSF 2.0 has solved this by offering the new flash scope. See also How to show faces message in the redirected page.
Perform the POST asynchronously in the background (using ajax). This way the refresh would only re-execute the initial GET request which opened the form. You only need to make sure that those forms are initially opened by a GET request only, i.e. you should never perform page-to-page navigation by POST (which is at its own already a bad design anyway). See also When should I use h:outputLink instead of h:commandLink?
or when the submit button is clicked once again
For that there are basically also at least 2 solutions, which could if necessary be combined:
Just block the enduser from being able to press the submit button during the submit and/or after successful submit. There are various ways for this, all depending on the concrete functional and design requirements. You can use JavaScript to disable the button during submit. You can use JSF's disabled or rendered attributes to disable or hide the button after submit. See also How to do double-click prevention in JSF 2. You can also use an overlay window during processing ajax requests to block any enduser interaction. PrimeFaces has <p:blockUI> for the purpose.
Validate uniqueness of the newly added entity in the server side. This is way much more robust if you absolutely want to avoid duplication for technical reasons rather than for functional reasons. It's fairly simple: put a UNIQUE constraint on the DB column in question. If this constraint is violated, then the DB (and DB interaction framework like JPA) will throw a constraint violation exception. This is best to be done in combination with a custom JSF validator which validates the input beforehand by performing a SELECT on exactly that column and checking if no record is returned. A JSF validator allows you to display the problem in flavor of a friendly faces message. See also among others Validate email format and uniqueness against DB.
Instead of creating a token manually, you can use BalusC' solution. He proposed a Post-Redirect-GET pattern in his blog
Alternative solutions can be found in these answers:
Simple flow management in Post-Redirect-Get pattern
How can Flash scope help in implementing the PostRedirectGet (PRG) pattern in JSF2.0
<!--Tag to show message given by bean class -->
<p:growl id="messages" />
<h:form>
<h:inputText a:placeholder="Enter Parent Organization Id" id="parent_org_id" value="#{orgMaster.parentOrganization}" requiredMessage="Parent org-id is required" />
<h:commandButton style="margin-bottom:8px;margin-top:5px;" class="btn btn-success btn-block " value="Save" type="submit" action="#{orgMaster.save}" onclick="resetform()" />
</h:form>
public String save() {
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getFlash().setKeepMessages(true); //This keeps the message even on reloading of page
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Your submission is successful.", " ")); // To show the message on clicking of submit button
return "organizationMaster?faces-redirect=true"; // to reload the page with resetting of all fields of the form.. here my page name is organizationMaster...you can write the name of form whose firlds you want to reset on submission
}

Get url parameter into facelets view after user session timeout

I am building a CRUD web application using JSF. I have a problem with loading a page after the user session has timed out. That is i lose the parameters I need to construct the view (even though the parameters are still visible in the url like so: 'someurl/view.xhtml?pid=5'.
In the .xhtml file the parameter pid is used to load some content from an underlying database when constructing the view. When the user has been inactive for a while their session times out, and if they try to reload the page in the browser they are forwarded to the login page (the 'someurl/view.xhtml?pid=5' still intact) and on succesful login go back to the view.xhtml page where I wan't the view to be constructed as if their session had never timedout.
However this does not happen because the 'pid' parameter is no longer set in the view. But since the 'pid' parameter is still visible in the url I feel like I should be able to get it into the view and load the protein with this id from the database.
These are the things I've tried:
#{protein.setProteinById(param.pid)}
and
#{protein.setProteinById(param['pid'])}
and
#{protein.setProteinById(request.getParameter('pid'))}
and
<c:set value="${request.getParameter('pid')}" var="pid" />
#{protein.setProteinById(pid)}
Is this possible to do? Then how?
I'm no expert, but wouldn't you set it in the managed bean?
As far as I know there are two methods for doing this.
One method is using in your facelet to push a view parameter back into a bean (I have a scenario where this doesn't work because of other things, so have no experience with it)
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
I have a prerender method, which is always called before a render
<f:metadata>
<f:event type="preRenderView" listener="#{MyController.prerenderMethod}" />
</f:metadata>
And inside the method, I look at the parameters:
public void prerender(ComponentSystemEvent event) {
value = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("key");
}

How to change the order of creation/restoring managed beans?

I have a complex problem with order of 'JSF bean life cycle actions'.
I have two beans with different scopes. The first, let's call it, managerBean is session scope bean. The second one, someBean has view scope (someBean really is many different beans). ManagerBean takes some action once per page loading and few others view scope beans are using the results of this action in their constructors.
Everything was working just fine until I've started getting forms IDs in xhtml files from java beans. Now action from managerBean is taken after someBean is created and I'm getting expected result only when the page is reloaded (on refresh, so someBean is using the first results of ManagerBean work).
This is how it looks like now:
<!-- mainTemplate is a main templete of the page which is rendered once
per page view (every other actions are taken via ajax). This is a place
of ManagerBean work after re rendering the page -->
<ui:composition template="/mainTemplate.xhtml">
<ui:define name="mainContent">
<h:form id="#{someBean.formID}">
some inputs
</h:form>
(...)
</ui:define>
</ui:composition>
So when form id was constant String everything worked like I want and now it doesn't. It looks like JSF must calculate ID first and take any other after this (including ManagerBean action).
My question is: Is there a way to change this situation?
If something isn't clear enought, please ask. I was trying to simplify the problem because it has many factors. Maybe all my thinking is wrong (the way I want to take some action per page and some actions after it).
Any help will be good!
The id (and binding) attribute of a JSF UI component is evaluated during view build time. The view build time is that moment when the XHTML source code is turned into a JSF UI component tree. All other attributes of a JSF UI component like value and all events like preRenderView are evaluated/executed after the view build time, usually during view render time (when the JSF UI component tree needs to produce HTML output). This is not something which you can change by just turning a setting or so. It's just the way how JSF works. You can't render something which isn't built yet. You can only change this by writing code the right way.
I can't think of any real world scenario why you need to make the ID attribute dynamic like this. If it were inside a <c:forEach>, or part of dynamic component generation, then okay, but this seems just to be a static form. So I would in first place recommend to forget it and just hardcode the ID in the view and rely on other variables (perhaps a hidden input field? depends all on concrete functional requirement which isn't mentioned anywhere in the question nor guessable based on the code posted so far).
If you really need to make it dynamic, then you need to split the formID property off from the view scoped bean and move it to a different and independent bean, perhaps an application scoped one.
See also:
JSTL in JSF2 Facelets... makes sense? - component's id attribute has same lifecycle as JSTL tags

Semantics of "?faces-redirect=true" in <commandlink action=...> and why not use it everywhere

I would like to understand what are the semantics behind appending the "?faces-redirect=true" in the action property of a <h:commandlink> tag in JSF2.0. Whether with it or with out it, the application indeed navigates to the target page specified in the action. So at first glance it seems that the only effect is cosmetic, i.e. to provide feedback to the user (if he is looking at the browser's visited URL) that he has moved to a new page. But if it is so innocuous and side-effects-free I cannot see why it is not the default behaviour. I suspect that it has to do with the post-based mechanism of JSF2.0. I 've noticed when browsing through a JSF application that the URLs one sees at his browser (when ?faces-redirect=true is not used) are the ones of the "previous" "page".
meta-NB. I am behind a firewall and plagued with the "SO requires external JavaScript from another domain" issue so I apologize for the absence of formatting. I will also provide feedback on your answers in a few hours, when I can access from another domain.
Page-to-page navigation should not be performed using POST at all. You should be using normal <h:link> or <h:button> for this instead of <h:commandLink> or <h:commandButton>.
So instead of
<h:commandLink value="Next page" action=nextpage.xhtml?faces-redirect=true" />
you should actually be using
<h:link value="Next page" outcome="nextpage.xhtml" />
This has the major benefit that the website is now SEO friendly. Searchbots namely doesn't index forms.
Use the <h:commandLink> only if you need to submit a form with some user input. But more than often the result is just presented in the same page, if necesary conditionally rendered/included. Only on successful submits which absolutely needs to go to a different page (e.g. login/logout), you should indeed be sending a redirect. This is the so-called Post-Redirect-Get pattern.
See also
How to navigate in JSF? How to make URL reflect current page (and not previous one)
When should I use h:outputLink instead of h:commandLink?

Resources