I have a update form, with composite keys All composite keys are displayed in outputbox as I have hidden field for each composite keys. These outputbox values are empty after validation error. How do I resolve this. I am on the same page so doesn't it has to have the values.
This is indeed a non-intuitive behaviour of the h:inputHidden (I've ever filed a issue against it at the Mojarra issue list, but they didn't seem to do anything with it). The whole problem is that the component's value unnecessarily is also taken into the entire validation cycle while there's no means of user-controlled input. It will get lost when the validation fails. There are at least three ways to fix this non-intuitive behaviour.
First way is to use the binding on the h:inputHidden instead:
<h:inputHidden binding="#{bean.hidden}" />
This way the value won't undergo the unnecessary validation cycle. This however requires changes in the way you get/set the values in the backing bean code. For example:
private HtmlInputHidden hidden = new HtmlInputHidden(); // +getter +setter.
public void setHiddenValue(Object hiddenValue) {
hidden.setValue(hiddenValue);
}
public Object getHiddenValue() {
return hidden.getValue();
}
Second (and IMHO the preferred way) is to use Tomahawk's t:saveState instead.
<t:saveState value="#{bean.property}" />
The major advantage is that you don't need to change anything in the backing bean code. It will restore the value early before the apply request values phase. You only need to add extra libraries if not done yet, but as Tomahawk provides much more advantages than only the t:saveState, such as the in basic JSF implementation missing components/features t:inputFileUpload, t:dataList, t:dataTable preserveDataModel="true", t:selectOneRadio layout="spread" and so on, it is worth the effort.
The third way is to store it in a session scoped bean, but you actually don't want to do that for request scoped variables. It would only give "wtf?" experiences when the enduser has multiple tabs/windows open in the same session.
Related
First of all, sorry for my english. I have a RequestScoped ManagedBean in order to send parameters to other views, without getting the The scope of the object referenced by expression is shorter than the referring managed beans error. I also have in the same RequestScoped view a p:dataTable showing these beans objects, with an update button for each row, that retrieves this bean to another form in the same view to be update with new values.
The problem is, when I hit the submit button to record the new values, another record is created, instead of the older one being updated. Of course, because the bean is killed when the submit button is pressed (RequestScoped), creating a new bean and another record in the DB. How can I fix it in this scope?
I've seen some alternatives using #PostConstruct here, however I'm not entirely sure it would solve my specific problem.
EDIT:
After researching a bit more into this topic, I came to another doubt: I am using the same Bean in both views (in my case, ProjectBean), should I create a new Bean with RequestScoped annotation (something like ProjectIdBean), set the older one to ViewScoped (so I can reproduce updates naturally on my Database), and let this new Bean handle the requests for other views?
Submit button:
<p:commandButton value="Gravar" action="#{projetoBean.gravar}"
process="#form" update="#form :formTabelaProjetos:tabelaProjetos" />
'Gravar' method:
public void gravar() {
System.out.println("Gravando projeto " + this.projeto.getNome());
ProjetoDAO dao = new ProjetoDAO();
if (this.projeto.getId() == null) {
dao.adiciona(this.projeto);
projetosAtivos = this.getProjetosAtivos();
} else {
dao.atualiza(this.projeto);
}
this.projeto = new Projeto();
}
You can use request scoped backing bean for updating entities. The problem is, that the request life cycle ends when your page is rendered. So anything you loaded will get discarded. The submit creates another request, that will try to reload resources, but it is a different request than the previous one and for example request parameters often do not contain what the programmer expects. But this is what you found out already. There are two ways how to deal with the problem:
1) use simple getters and setters to set "String, Integer" and similar variables in your request scoped bean, that you use to reconstruct and modify the entity you want to update. It is not convenient for the programmer but request scoped beans save resources of your server.
2) change the scope of your backing bean. Session scope is not ideal, because it can stay in memory for a really long time. And you might realize you need to clean it up manually. Much better is ViewScoped bean as it allows you to work with the entities you loaded over several steps. It gets wiped out when the user leaves the page.
#javax.faces.bean.ViewScoped
#javax.faces.bean.ManagedBean
public class SomethingBean {
......
}
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
When a JSF form field is wired into an entity bean field (which is mapped to a DB field), each setter in the entity bean is called regardless of whether the user changed the form field value in the front end, i.e. the setters on unchanged fields are invoked the same as those that have changed but their new value is the same as the old value.
My question is simple: Is there a way to configure JSF to only call the setters mapped to the fields that have changed in the front end? The reason for this is that I have a requirement by which I have to detect deltas on every persist and log them, more about which can be read in this question.
Maybe I didn't understand you clearly, but why are you mapping directly your entity beans to a JSF view ?! IMHO it would be better if you add managed beans between your JSF pages and the entities in order to better separate your business logic from data access.
Any way, I think the easiest solution to impelement for that case is by making use of Value Change Events which are invoked "normally" after the Process Validations phase (unless you make use of the immediate attribute).
The good news about Value Change Events (regarding your example) is they are invoked ONLY after you force form submit using JavaScript or Command components AND the new value is different from the old value.
So, as an example on how to use value change listeners, you can add valueChangeListner attribute to each of your JSF tags like following:
<h:inputText id="input" value="#{someBean.someValue}"
valueChangeListener="#{someBean.valueChanged} />
Then, implement your valueChanged() method to look something like:
public void valueChanged(ValueChangeEvent event) {
// You can use event.getOldValue() and event.getNewValue() to get the old or the new value
}
Using the above implementation, may help you to separate your logging code (it will be included in the listeners) from your managed properties setters.
NB: Value Change Listeners may also be implemetend otherwise using the f:valueChangeListener Tag, but this is not the best choice for your example (you can find some examples in the section below, just in case)
See also:
Valuechangelistener Doubt in JSF
JSF 2 valueChangeListener example
When to use valueChangeListener or f:ajax listener?
I often face the following problem. I have a JSF application and a facelet where I write EL expressions, like this:
<h:outputText value="#{myBean.foo}">
As long as myBean, as a variable, has a life long enough, there's no problem to evaluate myBean.foo at any given time, but if myBean is a variable that references some bean within a short period of time, when myBean.foo is evaluated it might be too late, so that JSF complains that myBean resolves to null. This is something well-known, but the problem is that it is not clear to me what to expect in different situations.
Concrete example n. 1: if you try the following with PrimeFaces OrderList:
<p:orderList value="#{bean.myValue}" var="item">
<p:column>
<p:commandLink action="#{bean.doSomething(item)}" />
</p:column>
</p:orderList>`
This is not going to work, because when doSomething is called, the item variable is no longer defined (although the object it references is still alive) and hence it's resolved to null. It's a known issue. However the same pattern works fine with <p:dataTable>, for instance. Anyway, I'm not interested right now in this specific problem, I just want to explain my doubt.
Concrete example n. 2: I have written a composite component with a backing bean. The backing bean extends UINamingContainer and uses its StateHelper to retain a model object. This composite allows to write child tags and I would like to write something like this:
<myns:myCc var="myVar">
<h:inputText value="#{myVar.foo}" />
</myns>
With "myVar" I want to give a name to the model object. To make this work, I tried to store the model object in the request map at the beginning of encodeChildren method and remove it afterwards: this works for rendering, but if I then process the input with a commandButton action, it does not work because when the action gets executed it says that myVar can't be resolved: in other words, it tries to resolve the entire expression too late. I then tried to "permanently" save the model object in the view scope map, but it doens't work either. However, if I change this to:
(assuming modelObject is the property field in the backing bean that stores my model object)
it works. So, it is not a problem in my model, but in the way I try to make the model object available to EL expressions for child tags.
Concrete example n. 3: I often use the <ui:param> tag to give beans a shorter name and to ease templating. For instance:
<ui:param name="bean" value="#{longNamedAndPageSpecificBean}" />
So that, in the remainder of the page I can just use #{bean.foo} instead of #{longNamedAndPageSpecificBean.foo}. This works fine even for actions passed to command buttons. However, if I pass a method expression like #{bean.myActionMethod} to a composite component attribute declared with method-signature, when this method expression is actually invoked I receive an error that bean resolves to null... The reason why it works in one case (with commandButton actions) and not in the other (with actions used by the composite component) is a big source of confusion for me.
I would appreciate if someone can help me to understand better this JSF aspect and suggest better approaches/workarounds with the aforementioned concrete examples.
Your question looks too large, but i could say that, during the build time only Session and request scoped values are avaiaible.
The same thing is true for the Execution phase.
Only the render phase should ensure the avaibility of temporal vars "myVar".
The best way to understand what its realy hapening is to debug because its depends on the component implementation
As described in this question I try to perform some field validation in a form on the backing bean side. For this I would like to access the violating fields to mark them.
From searching the web there seem to be two ways to do this:
store the components in the backing bean for access and use them in the JSF pages via the binding attribute.
Use standard value binding in the JSF pages and when needing access to a component from the bean, look it up via UIViewRoot.findComponent(String id)
As far as I can see both ways have drawbacks:
Component bindings blows up the backing bean with variables and getters/setters, some sites strongly discourage the use of component binding at all. In any case, a request scope is advised. On the other hand, findComponent() always traverses the tree, which may or may not be costly, right? (Plus, at the moment I can't find my component at all, but that is another problem)
Which would be the way to go? Are these interchangeable alternatives and if not, based on what criteria do you chose? Currently I just don't have enough insight to make a decent decision...
First of all, regardless of the choice, both are a poor practice. See also How does the 'binding' attribute work in JSF? When and how should it be used?
If you had to make the choice, component bindings are definitely faster and cheaper. It makes logically completely sense that a tree scan as done by UIComponent#findComponent() has its performance implications.
Indeed, the backing bean holding the component bindings must be request scoped, but you could easily inject a different scoped backing bean holding the business logic in it by #ManagedProperty.
A cleaner approach would be to use a Map as holder of all component bindings. You only need to add the following entry to faces-config.xml:
<managed-bean>
<managed-bean-name>components</managed-bean-name>
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
This can just be used as
<h:inputSome binding="#{components.input1}" />
<h:inputSome binding="#{components.input2}" />
<h:inputSome binding="#{components.input3}" />
And this can be obtained in other beans as
Map<String, UIComponent> components = (Map<String, UIComponent>) externalContext.getRequestMap().get("components");
This way you don't need to worry about specifying individual properties/getters/setters. In the above example, the Map will contain three entries with keys input1, input2 and input3, each with the respective UIComponent instance as value.
Unrelated to the concrete question, there may be a much simpler solution to the concrete problem as you described in the other question than performing the validation in the action method (which is actually Bad Design). I've posted an answer over there.