I have One Jsf form that contains 2 Beans. First Bean scope: Session. Second Bean scope: request.
When some values are added via First Bean to second Bean, the updated value is not displayed in the form. I don't know how to do. Please help me.
Either you fired a redirect which caused the request scoped bean being renewed, or the values are updated at the wrong moment which caused them being overridden later in the JSF lifecycle.
To fix the first, ensure that you aren't including <redirect/> in navigation case nor did call ExternalContext#redirect() in bean action method. To fix the second, well, run a debugger. This article may also help a lot in understanding what's going on under the JSF hoods.
BalusC has shown what are the possible reasons for this problem.
In case it is the redirection one, removing the redirect solves the problem, but adds another - the user is asked to resubmit the form if he refreshes the page.
A preferred way to achieve such transitions from one page to another is to use a conversation. MyFaces Orchestra provides a special conversation scope to solve this and many more problems.
Related
I have a internet shop application. I wanted to improve "removing from the cart" feature. I don't want to ask an user if he wants to "really remove" the position from the cart, instead I'd like to allow him cancel the operation.
Currently when user clicks "X" button at the product in the cart, row of table changes to "removed, click to cancel". In the back there is a list of CartPosition objects every with flag removed. Removed product is still on list, but the flag is set to true. It makes product still visible in proper position on the list, but on the view side I can render it another way. When user clicks another "X", previous one is premamently removed from the list and new one is marked as removed.
Shopping cart is session scoped CDI bean. It means, when I mark some position removed and go somewhere else, then go back to the cart, I'll still have one row marked as removed. I just don't want this.
I thought about changing the bean to JSF one, then create another view scoped which could keep record marked as removed and check if it's empty, if so I could remove the one from list. I have no idea if it's going to work. I'll try this approach, but I'd rather keep my beans managed by CDI.
Is there a way to handle this without implementing my above idea?
EDIT: #BalusC, your assumptions are wrong. You should rather suppose, that I don't exactly know how can I mix CDI and JSF. I actually use JSF 2.2, what means that javax.faces.view.ViewScoped annotation is available for me. Anyway I still don't understand the idea. I understood, that I have to rely on some ViewScoped bean. It's clear, but how it has to be composed. Can you explain your idea? I tried few things, but it looked it didn't work correctly. For example my #PreDestroy method of ViewScoped bean was never called and it's constructed lazily only when I try to use it.
Do the actual remove job in #PreDestroy annotated method of the session or view scoped bean.
#PreDestroy
public void destroy() {
// Do the actual remove job here.
}
Given that your question implies that you don't have CDI based javax.faces.view.ViewScoped available, which is new since JSF 2.2, this in turn suggests that you're still on JSF 2.0/2.1 and thus only have JSF based javax.faces.bean.ViewScoped at hands, then it should be noted that its #PreDestroy is broken in several circumstances. You'd then best do the #PreDestroy in the CDI based #SessionScoped bean. Alternatively, you could use OmniFaces #ViewScoped which has fixed and improved the #PreDestroy of a #ViewScoped bean in several ways. It even gets invoked on window unload.
As far as I understood your problem is the session. One way to solve the problem is to set the list of removed products in a request attribute and remove it from the session bean so that on the next request they will disappear.
Hope that helps
I wrote two pages...one a form where data submitted and second just to confirm the transaction actually carried out some calculation.
I have a managed bean i.e. FormDataBean and a class Reservation.java from which i instantiate for each booking made. Now I have at the end of a form a submit button:
<h:commandButton value="Submit" action="confirmation"/>
in the bean I have setters and getters as usual. in a method i defined I create an instance of Reservation, then set the beans variables to the instance variabels, like
reservation.startDate = startDate;
reservation.endDate = endDate;
reservation.checkRange();
The last method, i.e. checkRange() will use the assigned values to instance variables to carry calculation. it should return a string successful or failure.
Now when I enter data in the form, and press submit, it just refreshes the page but nothing is submitted. because it doesn't go to next page :(
Any idea what is happening? I don't need to define a navigation rule, because in other project, I carry out simple calculation and display result in next page and it worsks! Please advice
Thanks,
Your are missing to tell us some of the more important details so the answer is a kind of guesswork.
As you don't use navigation rules I assume you are using JSF 2, aren't you?
With JSF 2 you can directly set the new navigation target, without navigation rules. A forward to "confirmation" should work if your outcome file is named confirmation.xhtml. Check that. With a navigation rule you could forward it do a different file.
This part should work regardless of the rest.
For the bean not getting any values make sure that you are using the correct scope either through annotation or entry in your faces-config.xml. As you have a quite unusal validation mechanism you probably have to use the session scope.
The correct way would be using an actionlistener that does your checks and then sets the navigation depending on your checks. The bean scope could be more restrictive then.
Did you try action="confirmation?faces-redirect=true"?
I have the following button:
<h:commandButton
disabled="#{mybean.searching}"
binding="#{mybean.searchButton}"
actionListener="#{mybean.searchForLicenses}"
value="Search" />
When I debug I see that the actionListener is called twice first, then three times, next click four times and so on.
It seems like on every reload the actionListener is registered one more time.
I'm using Mojarra 2.1.3 (also tried 2.0.6) and Tomcat 7 with IceFaces.
The binding is done that way:
private javax.faces.component.UICommand searchButton;
public void setSearchButton(UICommand searchButton) {
this.searchButton = searchButton;
}
public UICommand getSearchButton() {
return searchButton;
}
That can happen if you've bound the component to a session or application scoped bean instead of a request scoped bean. This is simply a bad design. The very same component would be reused among multiple requests/views. You need to put the bean in the request scope, or to get rid of the component binding altogether.
Note that binding the component directly to a bean is often a sign of poor design somewhere in the code. What is it, the functional requirement and/or problem for which you thought that this is the solution? If you elaborate on that, we may be able to propose the right approach.
Also note that using an action listener alone is also a design smell. I'd expect "searchForLicenses" to be a normal action method. See also Differences between action and actionListener.
The similar issue takes place when component is using binding and validator or valueChangListener and backing bean is of View, Session or Application scope. Then corresponding listeners are called many times but not once during request (+1 time with every new request).
One possible solution is to override jsf class AttachedObjectListHolder which is used for storing component listeners. Current implementation simply add new listener to component even though the same listener is already there. So the proposed fix is to check that listener does not exist before adding it.
Details of the fix you can see here
In the very early days of using CDI I'm navigating to a page with a long running
conversation active using faces-redirect=true, so I have a URL like ..myPage.xhtml?cid=1.
At some point I end the conversation, I mean this has to be a reasonable thing to do
or you might as well use session scope? Anyway, I end the conversation and then the
user hits F5, and then of course this causes a 'conversation not found' error as cid=1
doesn't exist.
Can anyone suggest how to get around this problem? I'm using the Steven Verborgh
ViewScoped implementation and simply using a conversation scoped bean to pass parameters
between pages. So I have for example 2 #ViewScoped beans each of which back page 1 & 2.
I #Inject the #ConversationScoped ParameterBean into both view scoped beans. I start the
conversation (parameterBean.getConversation().begin()) in the action method called from
page 1. In the preRenderView event for page 2 I take a reference to the properties of
the parameterBean into a page 2 backing bean instance variable and end the conversation,
it's done it's job and no longer required.
Except for the F5 problem it works fine. If anyone has any suggestions I'd appreciate it,
hopefully I'm not missing something really obvious. I kind of assuming there's no getting
away from a redirect.
Thanks.
There is no workaround for it. The default #ConversationScoped is utterly broken. I'm using the #ConversationScoped from MyFaces CODI instead. It solves all problems you can get with the standard scope.
We are using JSF in our project (im pretty new to it) were every page have a back bean Java file.
In order to move (redirect) from one page to another, i need to put all the parameters (search criteria) in the request scope before redirecting and then retrieve it back in the next page constructor. When you have few pages deep and you want to come back to the top, it becomes really annoying to maintain.
For example, if i have page 1 with advanced search filters, which redirects to page 2, depending on the chosen item, and from page 2, you get another list were you can go to page 3 for details. Now each time i need to put all the params in the request scope/read them again, store them in hidden fields and get them back.
Whats exactly wrong with this method and whats a better way to do it in JSF?
EDIT: the environment is IBM Rational Application Developer (RAD), which have its own JSF implementation. Not sure if that makes a difference.
Putting request scoped data in session scope will bite you (very) hard if you're going to open the same page in multiple windows/tabs. Only use the session scope if the data itself is also really session scoped (excellent examples are the "logged-in user" and the "shopping cart", you want it to be exactly the same throughout the entire session). Again, don't put request scoped data in the session scope. It hurts both you and the enduser.
Just design your beans smart (it makes no sense to have different beans containing the same data) and make use of h:inputHidden where needed, if necessary in combination with managed property injection. It's indeed a bit a pain to code and maintain. You can on the other hand also just grab Tomahawk <t:saveState> if the to-be-passed data is actually as big as a "whole" managed bean. It costs only a single line in the JSF page and has always been of great assistance.
*For example, if i have page 1 with advanced search filters, which redirects to page 2, depending on the chosen item, and from page 2, you get another list were you can go to page 3 for details. Now each time i need to put all the params in the request scope/read them again, store them in hidden fields and get them back.
Whats exactly wrong with this method and whats a better way to do it in JSF?*
There's nothing wrong with this method. Maybe you coded it the wrong way which caused that it looks unnecessarily overcomplicated. I can't tell much as long as you don't post details about the code used.
As per your edit:
EDIT: the environment is IBM Rational Application Developer (RAD), which have its own JSF implementation. Not sure if that makes a difference.
This is not true. IBM doesn't have any JSF implementation. It has just a component library (the poorly maintained hx prefixed components, also known as "Faces Client Framework"). WSAD/RAD ships with Sun JSF RI (Mojarra) as standard JSF implementation, although it's usually a heavily outdated version. Ensure that you keep it updated.
I'm only starting out with JSF too to be honest, but I thought you can save managed beans in the session scope, thus being able to access the bean on each request? You can also save the state client-side avoiding nastiness about session stickyness and stuff.
So you could save the data you are currently passing as request parameters in a session-scoped managed bean, and it will be available to any requests in that user's session, destroyed when the session times out or is deliberately invalidated (say on user logout).
I don't think JSF currently supports conversation state which I think might be the exact solution to your problem, maybe a session scoped managed bean would be the pragmatic solution?
Make your managed-bean session scoped.
If you are using MyFaces you can use PageFlowScope. If using Seam then use Conversation scope.
If pageflowscope or conversation scope is not available, then use session scoped beans. In addition you can use PhaseListener to initialize or execute specific methods before the page gets called. In you case if the flow is page1 -> page2 -> page3, then initialize the session scoped bean in PhaseListener if page1 gets called.
I'll update with more info if you need.