Updating Bean from JSF dataTable - forms

I've got this h:dataTable and form:
<h:form>
<h:dataTable value='#{bean.allData.dataItems}' var='item'>
<h:column>
<h:outputText value='#{item.id}' />
</h:column>
<h:column>
<h:inputText value='#{item.name}' />
</h:column>
</h:dataTable>
<h:commandButton value="Save" action="#{bean.saveEntries}"/>
</h:form>
So the table shows the id and a textbox with the name in. That works. When a user clicks the button, I'd like it to save any changes to the name field.
DataBean has:
private Vector<ItemBean> dataItems;
// constructor here
public void setDataItems(Vector v) {
dataItems = v;
}
public Vector getDataItems() {
return dataItems;
}
and ItemBean has...
private String id;
private String name;
// setter for both
// getter for both
Bean has a variable 'allData' of type 'DataBean'.
Bean also has a method saveEntries() which is currently blank (as I'm not sure how it works). How do I reference the inputs to set these values?

JSF has already done it during UPDATE MODEL VALUES phase. Print/debug the local variables and you'll see. All you need to do in the save method is just persisting the data in some datastore.
Also see the following articles for more background information and examples:
Using datatables.
Debug JSF lifecycle.

Related

f:viewAction does not invoke action method

I can't get an action method with the f:viewAction tag to work.
Here's the jsf page:
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<ui:repeat var="genreType" value="#{navigation.genreTypeList}">
<f:metadata>
<f:viewParam name="nameEn" value="#{genreType.name_en}" required="true" />
<f:viewAction action="#{search.searchByGenreType}" />
</f:metadata>
<h:link value="#{genreType.name_de}" outcome="index" includeViewParams="true" /><br />
</ui:repeat>
</ui:composition>
It produces links like this:
[...]/index.jsf;jsessionid=635562E66C7F2FA54504B53D5DAA114C?nameEn=fiction
And here's the bean:
#ManagedBean
#RequestScoped
public class Search implements Serializable {
private static final long serialVersionUID = -5193732222381183093L;
private String nameEn;
public String getNameEn() {
return this.nameEn;
}
public void setNameEn(String nameEn) {
this.nameEn = nameEn;
}
// action methods
public String searchByGenreType() {
System.out.println("searchByGenreType");
return "index";
}
}
I'm using JSF 2.2.5 with Tomcat 7.0.42, IDE is Eclipse Kepler (4.3.1).
I've tried different variations (#PostConstruct in bean, explicit navigation in faces-config.xml, old and new namespaces).
There should be no problem with namespaces since this is fixed since JSF 2.2.5.
This code isn't making any sense. You seem to be confusing <f:viewParam> with <f:param>. You need <f:param> to add HTTP request parameters to links. The <f:viewParam> is to be used to set incoming HTTP request parameters as bean properties.
Given the concrete functional requirement of having a list of links with parameters which in turn should on the target page set the parameter as a bean property and invoke a bean action, here's how you should be implementing it:
The source page with the list of links:
<ui:repeat var="genreType" value="#{navigation.genreTypeList}">
<h:link value="#{genreType.name_de}" outcome="index">
<f:param name="nameEn" value="#{genreType.name_en}" />
</h:link>
<br />
</ui:repeat>
In the target page, apparently index.xhtml, put this somewhere in top, right before <h:head>:
<f:metadata>
<f:viewParam name="nameEn" value="#{search.nameEn}" required="true" />
<f:viewAction action="#{search.searchByGenreType}" />
</f:metadata>
Inside the searchByGenreType() method you can just access that nameEn property directly.
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
When using <ui:composition> templating, where should I declare the <f:metadata>?

How to solve "Conversion Error setting value '2013-10-26' for 'null Converter'" in h:inputText with Date value?

when I press the insert button, I get the error indicated on the title
Conversion Error setting value '2013-10-26' for 'null Converter'
<h:form id="formulario">
<h:outputLabel for="date">Plazo</h:outputLabel>
<h:inputText id="date" required="true" requiredMessage="Campo Obligatorio" value="#{aaaNewDetalles.criterioAaa.plazo}"/>
<h:message for="date" style="color: red;"/>
<h:commandButton actionListener="#{aaaNewDetalles.add()}" value="Ingresar"/>
</h:form>
the form is managed by this class:
#ManagedBean(name = "aaaNewDetalles")
#ViewScoped
public class aaaNewDetallesBean {
private CriterioAaaController controller;
private CriterioAaa criterioAaa;
#PostConstruct
public void init(){
controller= new CriterioAaaController();
criterioAaa= new CriterioAaa();
}
public void add(){
controller.save(criterioAaa);
}
public CriterioAaa getCriterioAaa() {
return criterioAaa;
}
public void setCriterioAaa(CriterioAaa criterioAaa) {
this.criterioAaa = criterioAaa;
}
}
The object CriterioAaa:
import java.sql.Date;
#Table(name = "criterio_aaa", schema = "", catalog = "ciclos_calidad")
#Entity
public class CriterioAaa extends Entidad implements Serializable {
private Date plazo;
public Date getPlazo() {
return plazo;
}
public void setPlazo(Date plazo) {
this.plazo = plazo;
}
}
There are two problems in your current approach:
You should use java.util.Date instead java.sql.Date. JSF and other frameworks work with this type. Also, java.sql.Date extends java.util.Date but its purpose is basically for JDBC usage. More info about this: Date vs TimeStamp vs calendar?
<h:inputText> expects a String as value, and when sending the data to the managed bean, it also expects the class field is from String type as well. In cases like this, you need to use a converter to tell JSF that this String in fact represents a Date. For this, you may use <f:convertDateTime> tag component.
<h:inputText id="date" required="true" requiredMessage="Campo Obligatorio"
value="#{aaaNewDetalles.criterioAaa.plazo}">
<f:convertDateTime pattern="yyyy-MM-dd" />
</h:inputText>
As a recommendation, you may use a calendar component from third party libraries like PrimeFaces or RichFaces whose provide <p:calendar> and <rich:calendar> component respectively.
You should import the appropriate Date package :
import java.util.Date;
In Managed Bean You should use java.util.Date. and specify the converter.
e.g.
<h:inputText id="date" required="true" requiredMessage="Hire Date"
value="#{empBean.empDetail.hireDate}">
<f:convertDateTime pattern="yyyy-MM-dd" />
</h:inputText>
you can specify the pattern for DateTimeConverter also you can use dateStyle,timeStyle, type.

<h:form> within <ui:repeat> not entirely working, only the last <h:form> is processed

I will like to edit a list of items in the same page. Each item should be edited using a separate form. I am creating a h:form within ui:repeat. Only when the last form is submitted, the user input is applied to the managed bean. For all other forms, user input is not applied to the model.
#ManagedBean
public class Controller {
Logger logger = Logger.getLogger("TestWeb");
private List<Customer> customerList;
public List<Customer> getCustomerList() {
if (customerList == null) {
customerList = new ArrayList<Customer>();
customerList.add(new Customer("Daffy Duck", "daffy#example.com"));
customerList.add(new Customer("Bugs Bunny", "bugs#example.com"));
customerList.add(new Customer("Samity Sam", "sam#example.com"));
}
return customerList;
}
public String updateCustomer(Customer c) {
logger.info("Updating: " + c.getName());
return null;
}
}
In the view, I have
<ui:repeat var="c" value="#{controller.customerList}">
<h:form>
<h3>Edit Customer</h3>
Name: <h:inputText value="#{c.name}"/><br/>
E-mail: <h:inputText value="#{c.email}"/><br/>
<h:commandButton value="Update"
action="#{controller.updateCustomer(c)}"/>
</h:form>
</ui:repeat>
I search for hours without any solution. What will be the correct way to do this? I can hack it by using a single form and using a ui:repeat within it. But there are many issues with that and I will rather not take that route. Thanks.
This is a bug in state saving of <ui:repeat> in Mojarra. There are several similar issue reports at http://java.net/jira/browse/JAVASERVERFACES, among others issue 2243.
You have basically 2 options: use another iterating component (e.g. <c:forEach>, <h:dataTable>, <t:dataList>, <p:dataList>, etc), or replace Mojarra by MyFaces (the <ui:repeat> in this construct works properly in there).

What's the Struts 2 equivalent of ASP.NET's Request.Form (or FormCollection)?

I'm dynamically adding textboxes to a form on my jsp page using Javascript. When that form is submitted to an action, how does my action get the values of those textboxes? (I'm using Struts 2, btw.) In ASP.NET, I was able to find them in Form.Request/FormCollection. Is there a Struts 2 equivalent? Thanks a million.
In Struts2, you create beans in the form to do submit values. In order to create the input text-box, use the <s> tag. For example :
<s:textfield name="loginBean.userName" label="UserName" required="true" />
Here loginBean is the bean passed to the jsp page when.
Bean consists of variable declarations and getters-setters for the variable.
Then in the back-end Java where the form is submitted to, you can access the same bean.
Declare getter-setter in Java and then you can access the properties of the bean.
public LoginBean getLoginBean() {
return loginBean;
}
public void setLoginBean(LoginBean loginBean) {
this.loginBean = loginBean;
}
public String authenticate() {
String username = loginBean.getUserName();
I would recommend looking at source codes of open-source Struts projects.
It sounds like you're trying to populate a dynamic list. To do that, you just have to use the [n] index syntax at the end of your Action class property name:
HTML:
<input type="text" name="yourCollection[0]" value="first value" />
<input type="text" name="yourCollection[1]" value="second value" />
<input type="text" name="yourCollection[2]" value="third value" />
Action Class:
public class YourAction extends Action {
public List<String> yourCollection;
public List<String> getYourCollection(){
return yourCollection;
}
public void setYourCollection(List<String> aCollection){
this.yourCollection = aCollection;
}
}

Can't get JSF input field value on JAVA backend

I have following UI part on JSF - it's simple search form with input field and submit:
<h:form>
<h:commandButton action="#{operation.found}" value="#{msg.search}" />
<h:inputText name="searchParam"/>
</h:form>
And correspondingly, on backend, i attempt to get value of input field next way:
public List<Store> getFound() {
String name = (String) FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get(
"searchParam");
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
HibernateTemplate hbt = new HibernateTemplate();
hbt.setSessionFactory(sessionFactory);
foundStores = hbt.find(BEAN_PATH + " WHERE name = ?",
new Object[] { name });
return foundStores;
}
And null name is passed to backend.
It seems that problem in .jsf part, but from first glance looks ok...
You must point the <h:inputText> to a managed-bean property:
<h:inputText name="searchParam" value="#{searchBean.searchParam}" />
and define in your bean:
private String searchParam;
public String getSearchParam() {..}
public void setSearchParam(String searchParam) {..}
and then use the searchParam in your getFound() method;
Of course, you need to have the bean defined as managed bean, but I assume you have done it:
<managed-bean>
<managed-bean-name>searchBean</managed-bean-name>
<managed-bean-class>mypackage.SearchBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
You can check a JSF tutorial (like this, for example)