This question already has answers here:
How do I process GET query string URL parameters in backing bean on page load?
(4 answers)
When to use f:viewAction / preRenderView versus PostConstruct?
(2 answers)
ViewParam vs #ManagedProperty(value = "#{param.id}")
(2 answers)
Closed 2 years ago.
Can you tell me what is the order of events on page load in JSF?
I have a problem with passing parameter with f:param
I am using Eclipse, postgresql, Wildfly17 and primefaces 7.0.
I have two databases, connected with OneToMany relation. In first are pests with their properties. In second database are names of every pest in different languages (index of English is 1, German is 4, ...)
On first page is searching in first database (side One) for specific pests. Results are displayed in datatable under it. In last column of datatable is Edit button. By clicking on it you go on second page with data from both databases of specific pest.
Entity SmPests is:
Integer idPest;
String latinName;
String code:
#OneToMany(fetch = FetchType.LAZY, mappedBy = "smPests", cascade = CascadeTyoe.ALL, orphanRemoval = true)
List<SmPestsNames> smPestsNames = new ArrayList<SmPestsName>();
...
Entity SmPestsNames is:
Integer idPest;
int idLanguage;
String name;
In SmPestList.xhtml i have:
<p:button outcome="SmPestsEditable"update="pestsListEdit" value="Edit" style="fontsize:3em" title="edit">
<f:param name="id" value="#{zuzek.idPest}" />
<f:param name="code" value="#{zuzek.code}" />
<f:param name="lname" value="#{zuzek.latinName}" />
In SmPestsEdit.xhtml I have:
<f:viewParam name="id" value="#{smPestsEditable.idPest}" />
<f:viewParam name="code" value="#{smPestsEditable.code}" />
<f:viewParam name="lname" value="#{smPestsEditable.latinName}" />
My problem is that I when second page loads, idPest (passed by f:param) is not yet detected by backing bean and if I want to display names from second database I get
java.lang.NullPointerException
If i set static idPest it works but it doesn't display names of current element.
I want to se idPest before page loads.
Thank you in advance.
AFTER the page loads program does find correct children, but I want it happen BEFORE page loads.
I tried with ManagedBean but it says it is deprecated.
I also tried with viewAction
<f:viewParam name="id" value="#{smPestsEditable.idPest}" />
<f:viewParam name="code" value="#{smPestsEditable.code}" />
<f:viewParam name="lname" value="#{smPestsEditable.latinName}" />
<f:viewAction action="#{smPestsEditable.onload}" />
public void onload() {
idPest = id; // to avoid NullPointerException I use static idPest and try to change it to current before page loads
}
UPDATE: Problem is that parameter "id" is identifier for OneToMany relation. I want to load this OneToMany relation BEFORE the page loads. In the backing bean of the second page I have this:
private int idPest = 55; // This one is set so there is something set
#ManagedProperty(value="{param.id}")
private Long Id;
#ManagedProperty(value="{param.id}")
private int id;
public void onload() {
System.out.println(" ONLOAD: id: "+id);
System.out.println(" idpest: "+idPest);
System.out.println(" Id: "+Id);
}
I tried to get parameter using #ManagedBean using variables both int and Long type but what I get is:
ONLOAD: id: 0
idpest: 55
Id: null
Right now it seems to me I can't get (integer) value of parameter "id" in onload
Related
This question already has answers here:
How does the 'binding' attribute work in JSF? When and how should it be used?
(2 answers)
Closed 7 years ago.
I just want to generate dynamically HtmlInputFields, in this sample i just generated 3 fields. In out.xhtml i want to render these components in with ui:repeat and bind them using binding attribute (not value!!).
The loop.index used with varStatus allways fails when using the binding attribute.
exception:
binding="#{loop.index}": Target Unreachable, identifier 'loop' resolved to null
out.xhtml:
<ui:repeat value="#{myBean.htmlInputs}" varStatus="loop" var="bItem">
<!-- THIS WORKS -->
<h:inputText value="#{loop.index}" />
<!-- THIS WORKS -->
<h:inputText value="#{myBean.htmlInputs[0]}" />
<!-- THIS WORKS ALSO -->
<h:inputText binding="#{myBean.htmlInputs[0]}" />
<!-- AND THIS FAILES ?? WHY ?? -->
<h:inputText binding="#{myBean.htmlInputs[loop.index]}" /><p/>
</ui:repeat>
MyBean.java
#Named
#SessionScoped
public class BookingBean implements Serializable {
private List<HtmlInputText> htmlInputs = new ArrayList<>();
#PostConstruct
public void init() {
HtmlInputText hInput;
for (int i=0 ; i<3 ; i++) {
hInput = new HtmlInputText();
hInput.setValue("item #:" + i);
htmlInputs.add( hInput );
}
}
public List<HtmlInputText> getHtmlInputs() {
return htmlInputs;
}
public void setHtmlInputs(List<HtmlInputText> htmlInputs) {
this.htmlInputs = htmlInputs;
}
}
My Question is now:
How do i use bindings with dynamically generated JSF Components properly with ui:repeat in JSF 2.2 ?
Thanx
All binding attributes are evaluated (along with id attribtues and taghandlers like JSTL) during the view build time
the ui:repeat is processed during the Render phase (later).
You shoudn't bind your inputs, you are probably interested in their values, so use a related expression (to the bean) in the Value field
I have two <f:viewParam> tags enclosed within an <f:metaData> tag on a JSF page as shown below.
The index.xhtml file:
<h:form id="form" prependId="true">
<f:metadata>
<f:viewParam name="userId" id="paramId" rendered="#{not empty param.userId}" converter="#{userRoleConverter}" value="#{testManagedBean.userTable}"/>
<f:viewParam name="userRoleId" id="userParamId" rendered="#{not empty param.userRoleId}" converter="#{userAuthorityRowSelectionConverter}" value="#{testManagedBean.entity}"/>
<f:event type="preRenderView" listener="#{testManagedBean.preRenderEvent}" />
</f:metadata>
<p:messages id="messages" globalOnly="false" showDetail="true" showSummary="false" autoUpdate="false" closable="true"/>
</h:form>
each of them is associated with a converter as specified by the converter attribute.
When two parameters namely userId and userRoleId are appended as a querystring to the URL, two properties namely userTable and entity are set to the associated managed bean - testManagedBean after conversion is taken place by the converters specified.
The managed bean:
#ManagedBean
#ViewScoped
public final class TestManagedBean implements Serializable
{
private UserRoles entity; //Both are POJOs.
private UserTable userTable;
public TestManagedBean(){}
//Setters and getters of both the properties entity and userTable.
public void preRenderEvent(ComponentSystemEvent event) throws AbortProcessingException
{
System.out.println((entity==null)+" : "+(userTable==null));
}
}
When conversion fails on one of the properties, either userId or userRoleId, the other property along with the failed one is also not set to the managed bean (which is expected to be set because the conversion of this other property is not likely to fail) and both of them are null.
For example, if I entered a URL like,
/index.jsf?userId=100&userRoleId=12
then, the following statement in the preRenderEvent() method (associated with <f:event>),
System.out.println((entity==null)+" : "+(userTable==null));
displays true : true.
In this case, the conversion of userId fails (the value 100 doesn't exist in the database) but the conversion of userRoleId should succeed (but it doesn't) and shouldn't be null (which exists in the database).
Similarly, the following URL,
/index.jsf?userId=1&userRoleId=120
again displays true : true.
It is the reverse case of the previous one. userId exists in the database but userRoleId doesn't.
Finally, the following URL,
/index.jsf?userId=1&userRoleId=12
shows false : false. The values of both of the parameters in this case exist in their respective table in the database.
The failure of conversion is notified by throwing ConverterException that need not mention.
So, why is the value of both the properties set to null, when the conversion of one of them fails? Is only one of the converters executed, when conversion of one of them fails?
You shouldn't use a converter to validate, but a validator. Let the converter return null if nothing can be found (and throw ConverterException only if value is not interpretable as an user ID, i.e. it's inconvertible). Use required="true" instead if you'd like the value to be non-null.
E.g.
if (value == null) {
return null;
}
if (!value.matches("[0-9]+")) {
throw new ConverterException("Supplied parameter value can't be interpreted as an user ID.");
}
return service.getById(Long.valueOf(value)); // May return null if it doesn't exist.
By the way, the rendered attribute isn't making any sense there on <f:viewParam>. That's a taghandler which builds JSF component tree, not an UI component which renders some HTML. Even more, it's not documented at all. Also, it's somewhat strange to see <f:metadata> nested inside a form. Refer When using <ui:composition> templating, where should I declare the <f:metadata>?
I want to process this form (valueChangueListener is not valid in real case).
This is the back bean:
public class TestBean extends PrivateBaseBean implements Serializable {
private List<String> strings;
#PostConstruct
public void init() {
strings = new ArrayList<String>();
strings.add("");
strings.add("");
strings.add("");
}
public void saveAction(ActionEvent event) {
StringBuilder textToShowInMessage = new StringBuilder();
for (String string : strings) {
textToShowInMessage.append(string);
textToShowInMessage.append("; ");
}
FacesMessage msg = new FacesMessage(super.getBundle().getString(
textToShowInMessage.toString()), "");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
getters... setters...
An the view:
....
<h:form>
<ui:repeat var="string" value="#{testBean.strings}">
<h:inputText value="#{string}" />
<br />
</ui:repeat>
<p:commandButton value="#{msg.save}"
actionListener="#{testBean.saveAction}" icon="ui-icon-disk"
update="#form" />
</h:form>
...
When the form is processed in the back bean string list always is blank.
How to process form intput's inside iteration, without any value changue listener?
There are some screenshots:
The same problem occurs with action or actionListener on
Your problem is not connected with PrimeFaces <p:commandButton>'s behaviour, but rather with a scoping problem that is implicilty created when using the <ui:repeat> tag.
First of all, let's depart from your example. Basically, you've got
<ui:repeat value="#{bean.strings}" var="s">
<h:inputText value="#{s}"/>
</ui:repeat>
with the backing List<String> strings.
The culprit is here: value="#{s}". The exported by <ui:repeat> variable s is visible only within its loop and it is not bound to any managed bean's property, but instead only to a local variable. Put it differently, s is not bound/equal to bean.strings[index] as one would expect and has no knowledge, as we see, where it originated from. So basically, you're off with a unilateral relationship: value from the bean is printed in your input properly, but the reverse is not happening.
The workarounds
Workaround #1: wrapper classes / model objects
The situation can be overcome by using a wrapper object for your class. In case of a string it could be a 'simple mutable string', like below:
public class MString {
private String string;//getter+setter+constructor
}
In this case the iteration will be working as predicted:
<ui:repeat value="#{bean.mstrings}" var="ms">
<h:inputText value="#{ms.string}"/>
</ui:repeat>
with the backing List<MString> mstrings.
Note that if you have your model class, like User, and will change its properties within <ui:repeat> the class itself will be effectively a wrapper, so that the properties will be set appropriately.
Workaround #2: chained property access
Another workaround consists of accessing an element of your collection directly from within a <h:inputText> tag. This way, any such property will be set by accessing the bean, then collection, then setting the property at the desired index. Excessively long, but that's how it is. As to the how question, <ui:repeat> provides for an exported current iteration status variable, varStatus, that will be used to access the array/collection in the managed bean.
In this case the iteration will also be working as predicted:
<ui:repeat value="#{bean.strings}" var="s" varStatus="status">
<h:inputText value="#{bean.strings[status.index]}"/>
</ui:repeat>
with the ordinary backing List<String> strings.
My workaround solution take the value directly from the page:
<ui:repeat id="repeat" value="#{bean.strings}" var="s" varStatus="status">
<h:inputText id="x" value="#{s.field}"/>
<h:commandLink style="margin: .5em 0" styleClass="commandLink" actionListener="#{bean.save(status.index)}" value="#{bundle.Send}"/>
</ui:repeat>
The save method:
public void save(String rowid) {
String jsParam = Util.getJsParam("repeat:" + rowid + ":x");
System.out.println("jsParam: " + jsParam); //persist...
}
The getJsParam method:
public static String getJsParam(String paramName) {
javax.faces.context.FacesContext jsf = javax.faces.context.FacesContext.getCurrentInstance();
Map<String, String> requestParameterMap = jsf.getExternalContext().getRequestParameterMap();
String paramValue = requestParameterMap.get(paramName);
if (paramValue != null) {
paramValue = paramValue.trim();
if (paramValue.length() == 0) {
paramValue = null;
}
}
return paramValue;
}
This question already has answers here:
How to populate options of h:selectOneMenu from database?
(5 answers)
Closed 6 years ago.
I want to pick a custom object from select one menu. It neither shows an error nor values. What should I do?
My xhtml document:
<h:panelGrid columns="2">
<p:outputLabel value="" />
<p:selectOneMenu id="CurrencyMenu" value="#{CurrencyMB.currency}" >
<f:selectItem itemLabel="-- Select Currency--" itemValue="#{null}"/>
<f:selectItems value="#{CurrencyMB.currencyList}" var="currency" itemValue="#{currency.currencyId}" itemLabel="#{currency.currencyName}" >
</f:selectItems>
<p:ajax update="currencyOut" />
</p:selectOneMenu>
<p:outputLabel value="Currency Id : #{CurrencyMB.currency.currencyId}" id="currencyOut" />
</h:panelGrid>
My managedBean class:
#ManagedBean(name = "CurrencyMB")
#RequestScoped
public class CurrencyManagedBean {
private Currency currency;
private List<Currency> currencyList;
public Currency getCurrency() {
return currency;
}
public void setCurrency(Currency currency) {
this.currency = currency;
}
public List<Currency> getCurrencyList() {
currencyList = new ArrayList<Currency>();
currencyList.addAll(getiCurrencyService().getCurrencies());
return currencyList;
}
public void setCurrencyList(List<Currency> currencyList) {
this.currencyList = currencyList;
}
}
You are trying to map a Java object of class Currency to a string that comes as a HTTP request parameter. A converter is intended to be used in a situation when you need to create an object from a its string representation, and vice versa, like in the situation you faced.
Basically there are two approaches.
1. Utilize converter.
With this approach you define item value as a Currency object and use a converter to create string representation from an object and recreate an object back from a string. For the converter part, just follow the tutorial Luiggi pointed at. Basically you need to create a class that implements Converter, annotate it with #FacesConverter("currencyConverter") to be able to refer to the converter by id, like in converter="currencyConverter" attribute of a JSF tag:
<p:selectOneMenu id="CurrencyMenu" value="#{CurrencyMB.currency}" converter="currencyConverter">
<f:selectItems value="#{CurrencyMB.currencyList}" var="currency" itemValue="#{currency}" itemLabel="#{currency.currencyName}" />
<p:ajax update="currencyOut" />
</p:selectOneMenu>
2. Utilize plain Strings (or java primitive wrappers).
With this approach you bind item values, as well as user selection to a bean property of String type, and not to an actual object. Using it this way you won't need any converter, and string values will be set for you:
<p:selectOneMenu id="CurrencyMenu" value="#{CurrencyMB.currencyName}">
<f:selectItems value="#{CurrencyMB.currencyList}" var="currency" itemValue="#{currency.currencyName}" itemLabel="#{currency.currencyName}" />
<p:ajax update="currencyOut" />
</p:selectOneMenu>
Finally, it is worth reading the question to the answer Why selectOneMenu Send ItemLabel to the converter?.
You can create Converter for your Custom Object Currency.
Step 1: Create a Converter class and Implement javax.faces.convert.Converter Interface,Override getAsObject and getAsString methods and write your logic for String to Object Conversion and Object to String Conversion.
Step 2: Simply declare something like #FacesConverter("currencyConverter") in your converter class or If you want use Spring Inject or Autowired Annotation in Converter class declare your Converter Class with #Component("currencyConverter") Annotation and don't use #FacesConverter.And your converter class should in component scan package.
Step 3: Declare your converter in Selectonemenu Using converter property.
If you still have any problem please refer this link
http://www.techpages.org/jsf/jsf-custom-object-converter-from-selectonemenu/2428/
This question already has answers here:
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
(3 answers)
Closed 1 year ago.
I'm relatively new to JSF and trying to learn how current JSF 2 applications are designed. I've seen reference to single page applications that use ajax. Can someone fill me in on some of the techniques used and / or point me to a model or book? The books I've seen (JSF Complete Reference etc.) are good for basic tech issues but I can't find a source for current design techniques.
Thanks
Dave
In order to implement your Single Page Application, you should state which piece of your page should be rendered. This can be accomplished making use of a boolean flag such as create, edit, list, and so on. For instance, see the following (Just relevant code)
<h:body>
<h:form rendered="#{userController.stateManager.create}">
<h:panelGroup rendered="#{not empty facesContext.messageList or userController.stateManager.failure}">
<!--render error message right here-->
</h:panelGroup>
<div>
<label>#{messages['br.com.spa.domain.model.User.name']}</label>
<h:inputText value="#{user.name}"/>
</div>
<h:commandButton action="#{userController.create}">
<f:ajax execute="#form" render="#all"/>
<f:actionListener type="br.com.spa.web.faces.listener.StateManagerActionListener" />
<f:setPropertyActionListener target="#{userController.stateManager.create}" value="true"/>
<f:setPropertyActionListener target="#{userController.user}" value="#{user}" />
</h:commandButton>
</form>
</h:body>
Notice that our form will be rendered when a flag create is true - See second line above. To wrap our flags, we create a classe named StateManager as follows
/**
* I am using lombok, which takes care of generating our getters and setters. For more info, please refer http://projectlombok.org/features/index.html
*/
#Setter #Getter
public class StateManager {
private boolean create;
private boolean edit;
private boolean list;
}
Now, because we are using only a single page, we should use a ViewScoped managed bean, which keep our managed bean scoped active as long as you are on the same view - Is it a single page application, right ? So, no navigation. With this in mind, let's create our managed bean.
#ManagedBean
#ViewScoped
public class UserController implements StateManagerAwareManagedBean {
private #Inject UserService service;
private #Getter #Setter stateManager = new StateManager();
private #Getter #Setter List<User> userList = new ArrayList<User>();
private #Getter #Setter User user;
#PostConstruct
public void initialize() {
list();
}
public void create() {
service.persist(user);
stateManager.setCreate(false);
stateManager.setList(true);
stateManager.setSuccess(true);
}
public void edit() {
service.merge(user);
stateManager.setEdit(false);
stateManager.setList(true);
stateManager.setSuccess(true);
}
public void list() {
userList = service.list();
stateManager.setList(true);
}
}
For each action method, we define which piece of our page should be rendered. For instance, consider that our form was processed, covering all of JSF lyfecycle, which implies that their values was successfully converted and validated, and our action method invoked. By using as example our create action method - see above -, we set its create flag as false because our form was converted and validated, so we do not need to show it again (Unless you want). Furthermore, we set both list and success flag as true, which indicates that the list of our page should be rendered and our form was successfully processed - You could use this flag to show something like "User created" such as bellow
<h:panelGroup rendered="#{userController.stateManager.success}">
#{messages['default.created.message']}
</h:panelGroup>
Now, let's discuss which piece of our page should be rendered when it is called for the first time. Maybe you do not know but a void method annotated with #PostConstruct will be called first. So we define which piece of our page should be rendered. In our example, we call list method, which sets its list flag as true and populate a backing list.
#PostConstruct
public void initialize() {
list();
}
Finally, let's review the following order nested within h:commandButton
<h:commandButton action="#{userController.create}">
<f:ajax execute="#form" render="#all"/>
<f:actionListener type="br.com.spa.web.faces.listener.StateManagerActionListener" />
<f:setPropertyActionListener target="#{userController.stateManager.create}" value="true"/>
<f:setPropertyActionListener target="#{userController.user}" value="#{user}" />
</h:commandButton>
First of all, you should call an ActionListener - here called StateManagerActionListener - which takes care of resetting any StateManager - code bellow. It must be called first before any other setPropertyActionListener designed to control any flag because the order defined within h:commandButton is the order in which they will be called. keep this in mind.
public class StateManagerActionListener implements ActionListener {
public void processAction(ActionEvent e) throws AbortProcessingException {
Map<String,Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
for(Map.Entry<String,Object> entry: viewMap.entrySet()) {
if(entry.getValue() instanceof StateManagerAwareManagedBean) {
((StateManagerAwareManagedBean) entry.getValue()).setStateManager(new StateManager());
}
}
}
}
StateManagerAwareManagedBean - used in our ViewScoped Managed bean -, which allows that we reset any StateManager of any ManagedBean instead of resetting one by one in our ActionListener, is defined as follows
public interface StateManagerAwareManagedBean {
StateManager getStateManager();
void setStateManager(StateManager stateManager);
}
Second, after defining our ActionListener, we use a setPropertyActionListener which set the flag which controls the enclosing piece of the view as true. It is needed because our form is supposed to be not converted and validated. So, in our action method, we set this flag as false as discussed before.
A couple of notes
User is marked as a RequestScoped ManagedBean so that it can not be injected into a ViewScoped one using a ManagedProperty because its scope is shother. To overcome this issue, i set its value by using a <f:setPropertyActionListener target="#{userController.user}" value="#{user}"> - See our form
Our example use JEE features which need a proper Application Server. For more info, refer http://docs.oracle.com/javaee/6/tutorial/doc/
ManagedBean can play different roles such as a Controller, DTO and so on. When it play a role of a Controller, i prefer suffix its name with Controller. For more info, refer http://java.dzone.com/articles/making-distinctions-between