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

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;
}
}

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>?

<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).

Simple form to edit only one field of model in Spring MVC

What is the best way to change data of, for example, User?
I got lots of properties like 'username', 'city', 'phone' and when I want to edit just one field ('password'), I have to do this:
<form:form action="editUser.htm?id=${user.id}" commandname="user">
<form:hidden path='username' />
<form:hidden path='city' />
<form:hidden path='phone' />
<form:input path='password' />
....
In my controller action is defined:
#RequestMapping(value = "/editUser.htm", method=RequestMethod.POST)
public ModelAndView ordertypeedit(#ModelAttribute("user") User user,
BindingResult result, HttpServletRequest request)throws Exception{
userTypeValidator.validate(orderType, result);
if(result.hasErrors()){
(...)
return new ModelAndView(...);
}
orderTypeDAO.update(orderType);
return new ModelAndView(...);
I don't like to set all the to my action form... If I miss it, it shows error 'column 'username' cannot be null".
It depends if your properties are validated or mandatory on that form:
If not, then you don't need to submit them with your form:
<form:form action="editUser.htm?id=${user.id}" commandname="user">
<form:input path='password' />
and in your controller you will get user object with only user parameter.
Alternative way is to pass regular (not Spring MVC) form and create inside user object with only id and password properties.
you can use simple (without spring tags) form with one input and get it in controller using #RequestParam

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)

Updating Bean from JSF dataTable

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.