In Struts 1.x , I have prepopulated the forms text fields using form bean's with default values as follows,
<html:form action="/actions/signup1">
First name: <html:text property="firstName"/><BR>
And in form bean, I have default value as follows...
public class ContactFormBean {
private String firstName = "First name";
But in Struts 2.x , when I tried with struts-tags textfield as follows, its not prepopulating the default value from the bean,
<s:form action="signup1">
<s:textfield name="formBean.firstName" label = "First Name" />
I have the formBean declared in my Action class as follows with appropriate getter and setter methods...
public class SignupAction1 extends ActionSupport {
private ContactFormBean formBean;
#Override
public String execute() throws Exception {
....
}
public ContactFormBean getFormBean(){
return formBean;
}
public void setFormBean(ContactFormBean fb){
formBean = fb;
}
}
Please let me know if this can be accomplished at Request level and not at session level.
Thanks in advance.
<--Edited-->
struts.xml
<struts>
<constant name="struts.devMode" value="true" />
<package name="basicstruts2" extends="struts-default">
<action name="index">
<result>/index.jsp</result>
</action>
<action name="signup">
<result>/SignUp.jsp</result>
</action>
<action name="signup1" class="coreservlets.action.SignupAction1" method="execute">
<result name="success">/SignUp-Confirmation.jsp</result>
<result name="error">/SignUp.jsp</result>
</action>
</package>
</struts>
SignUp.jsp
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Sign UP</title>
</head>
<body>
<H1 ALIGN="CENTER">Sign Up</H1>
<s:form>
<s:textfield name="formBean.firstName" label = "First Name" />
<s:textfield name="formBean.lastName" label = "Last Name" />
<s:textfield name="formBean.email" label = "Email Address" />
<s:textfield name="formBean.faxNumber" label = "Fax Number" />
<s:submit action="signup1" method="loginAfterSubmit" value="Click here to Submit"/>
</s:form>
</body>
</html>
ContactFormBean.java
public class ContactFormBean {
private String firstName = "First name";
private String lastName = "Last name";
private String email = "user#host";
private String faxNumber = "xxx-yyy-zzzz";
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return(lastName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return(email);
}
public void setEmail(String email) {
this.email = email;
}
public String getFaxNumber() {
return(faxNumber);
}
public void setFaxNumber(String faxNumber) {
this.faxNumber = faxNumber;
}
public boolean isMissing(String value) {
if ((value == null) || (value.trim().equals(""))) {
return(true);
} else {
for(int i=0; i<defaultValues.length; i++) {
if (value.equals(defaultValues[i])) {
return(true);
}
}
return(false);
}
}
}
SignupAction1.java
public class SignupAction1 extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private ContactFormBean formBean;
#Override
public String execute() throws Exception {
this.formBean = new ContactFormBean();
return SUCCESS;
}
public String loginAfterSubmit() {
String firstName = formBean.getFirstName();
String lastName = formBean.getLastName();
String email = formBean.getEmail();
String faxNumber = formBean.getFaxNumber();
if (formBean.isMissing(firstName)) {
return ERROR;
} else if (formBean.isMissing(lastName)) {
return ERROR;
} else if ((formBean.isMissing(email)) ||
(email.indexOf("#") == -1)) {
return ERROR;
} else if (formBean.isMissing(faxNumber)) {
return ERROR;
} else {
return SUCCESS;
}
}
public ContactFormBean getFormBean(){
return this.formBean;
}
public void setFormBean(ContactFormBean fb){
formBean = fb;
}
}
Change your signup action declaration to
<action name="signup" class="coreservlets.action.SignupAction1">
<result>/SignUp.jsp</result>
</action>
and signup1 to
<action name="signup1" class="coreservlets.action.SignupAction1" method="signup1">
create method signup1 in your SignupAction1 action class and move your logic from execute to it. In execute then create new instance of your ContactFormBean.
put your default value to the constructor:
public class ContactFormBean {
private String firstname;
public ContactFormBean (){
this.firstName = "First name";
}
}
You are returning a null formBean object with the getFormBean method,
then the constructor is never called and the attempt to acces the formBean attribute firstName is giving an error (that is not showed because it is wrapped by the Struts2 tag on the JSP.
You can
1) instantiate it on your execute method:
public String execute() throws Exception {
this.formBean = new ContactFormBean();
}
2) instantiate it lazily on your getter:
public ContactFormBean getFormBean(){
if (formBean==null)
this.formBean = new ContactFormBean();
return this.formBean;
}
EDIT (due to your comments):
I don't know how you've structured your web application;
But if you are on a JSP, an Action (and its execute() method, or another method if specified) was called BEFORE rendering the JSP.
So, regardless if you have ActionOne loading stuff and ActionTwo called after submit, or ActionOne loading stuff and another method of ActionOne called after submit, you can know if you are in a "pre-JSP" state or in a "post-submit" state...
That said, if you are exposing an Object, and you want its value or its attributes to be different from null, you have to instantiate it in one of the way described above.
Obviously, your object should contain getters and setters for its attributes, and they must have been bound to your JSP objects.
In your example, you could have:
ContactFormBean:
public class ContactFormBean {
private String firstName = "First name";
public String getFirstName(){
return this.firstName;
}
public String setFirstName(String firstName){
this.firstName = firstName;
}
}
Your Action:
public class SignupAction1 extends ActionSupport {
private ContactFormBean formBean;
public ContactFormBean getFormBean(){
return formBean;
}
public void setFormBean(ContactFormBean fb){
formBean = fb;
}
#Override
public String execute() throws Exception {
/* this method is executed before showing the JSP */
/* first time initialization */
this.formBean = new ContactFormBean();
return SUCCESS;
}
public String loginAfterSubmit() throws Exception {
/* this method is executed after the submit button was pressed */
/* i don't initialize nothing here,
ContactFormBean is coming from the page */
System.out.println("ContactFormBean's firstName value is: " +
this.formBean.getFirstName());
return "goSomewhereElse";
}
}
and in Your JSP:
<s:form>
<s:textfield name="formBean.firstName" label = "First Name" />
<s:submit action="signup1" method="loginAfterSubmit" value="Press here to submit" />
</s:form>
You can do this with two Action by splitting the execute() and the loginAfterSubmit() methods into two execute() methods of two different Actions;
Then you must have your formBean in BOTH the Actions, with at least the getter in the first, and the setter in the second.
You can also set the Name value in your bean in execute method, it will populate it in your JSP page. Example is :
public String execute() throws Exception {
this.formBean = new ContactFormBean();
//Set your Name value here
formBean.setName("John Doe");
return SUCCESS;
}
Once JSP is populated you will find this value in Name text box.
Hope this will help.
Tapan
Related
My requirement is, at beginning I want to show users data on page and when user make changes in form, I want to access changed data.
Below is my code in Action class,
public class DisplayData extends ActionSupport implements ModelDriven<List<User>>, Preparable {
private List<User> userList;
#Override
public void prepare() throws Exception {
userList = new ArrayList<User>();
userList.add(new User("Demo","N"));
userList.add(new User("Demo1","Y"));
userList.add(new User("Demo2","Y"));
userList.add(new User("Demo3","N"));
}
#Override
public List<User> getModel() {
return userList;
}
public String execute(){
for (User value: userList) {
System.out.println(value.getName() +":"+value.getFlag());
}
return "success";
}
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
}
User class,
public class User implements Serializable
{
private String name;
private String flag;
public User() {}
public User(String name,String flag) {
super();
this.name = name;
this.flag = flag;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
}
Code in Jsp page,
<s:form name="getData" action="getData" method="post">
<table>
<s:iterator value="model" status="rowStatus">
<tr>
<td>
<s:textfield name="model[%{#rowStatus.index}].name" value="%{model[#rowStatus.index].name}"/>
<s:select name="%{model[#rowStatus.index].flag}" value="%{model[#rowStatus.index].flag}"
list="#{'Y':'Yes','N':'No'}" />
</td>
</tr>
</s:iterator>
</table>
<s:submit name="ok" value="ok" />
</s:form>
When page get rendered, it shows appropriate value of textfield and dropdown.
If I changed the values in Textfield and droprdown and submit the form then I am getting modified value of textfield but for the dropdwon it shows old value. How can I access selected value of dropdown?
Got the answer... :)
It was syntax mistake. Instead of
<s:select name="%{model[#rowStatus.index].flag}" value="%{model[#rowStatus.index].flag}"
list="#{'Y':'Yes','N':'No'}" />
Use
<s:select name="model[#rowStatus.index].flag" value="%{model[#rowStatus.index].flag}"
list="#{'Y':'Yes','N':'No'}" />
I have used %{ } in name attribute..
I filled my rightList of the PickList with Objects from a web service, but when i select some elements, i want to get these elements in myManagedBean, because i'll affect them to an Object.
JSF :
<h:form>
<rich:panel>
<h:panelGrid columns="2" styleClass="criteresSaisie"
rowClasses="critereLigne" columnClasses="titreColonne,">
<h:outputLabel for="libelleCoplement" value=" "
size="20" />
<rich:pickList d="libelleCoplement" sourceCaption="Compléments"
targetCaption="Compléments sélectionnés"
value="#{listeCmpltDispoModel.listeCmpltSelect}" size="15"
addText=">" addAllText=">>" removeText="<"
removeAllText="<<" listWidth="270px" listHeight="110px"
orderable="true">
<f:converter converterId="cmpltsTitresConcerter" />
<f:selectItems value="#{listeCmpltDispoModel.listeCmpltDispo}"
var="liste" itemLabel="#{liste.libelleComplement}"
itemValue="#{liste.cdComplement}"/>
</rich:pickList>
</h:panelGrid>
<h:panelGroup>
<div align="right">
<h:panelGrid columns="8">
<h:commandButton value="Valider"
action="#{saisieCmpltsTitreCtrl.valider}" />
</h:panelGrid>
</div>
</h:panelGroup>
</rich:panel>
</h:form>
The bean :
#ManagedBean(name = "listeCmpltDispoModel")
#SessionScoped
public class ListeCmpltDispoModel implements Serializable {
private static final long serialVersionUID = 1L;
private Long cdComplement;
private String libelleComplement;
private int nbCompl;
private List<ComplementsDispoSortieDTO> listeCmpltDispo ;
private List<ComplementsDispoSortieDTO> listeCmpltSelect ;
public ListeCmpltDispoModel() {
}
public Long getCodeComplement() {
return cdComplement;
}
public void setCodeComplement(Long cdComplement) {
this.cdComplement = cdComplement;
}
public String getLibelleComplement1() {
return libelleComplement;
}
public void setLibelleComplement1(String libelleCoplement) {
this.libelleComplement = libelleCoplement;
}
public Long getCdComplement() {
return cdComplement;
}
public void setCdComplement(Long cdComplement) {
this.cdComplement = cdComplement;
}
public String getLibelleComplement() {
return libelleComplement;
}
public void setLibelleComplement(String libelleComplement) {
this.libelleComplement = libelleComplement;
}
public List<ComplementsDispoSortieDTO> getListeCmpltDispo() {
return listeCmpltDispo;
}
public void setListeCmpltDispo(List<ComplementsDispoSortieDTO> listeCmpltDispo) {
this.listeCmpltDispo = listeCmpltDispo;
}
public int getNbCompl() {
return nbCompl;
}
public void setNbCompl(int nbCompl) {
this.nbCompl = nbCompl;
}
public List<ComplementsDispoSortieDTO> getListeCmpltSelect() {
return listeCmpltSelect;
}
public void setListeCmpltSelect(List<ComplementsDispoSortieDTO> listeCmpltSelect) {
this.listeCmpltSelect = listeCmpltSelect;
}
}
Converter :
#FacesConverter(value="cmpltsTitresConcerter")
public class CmpltsTitresConcerter implements Converter {
#SuppressWarnings("null")
public Object getAsObject(FacesContext context, UIComponent component,
String value){
ComplementsDispoSortieDTO cmpltSelect = null;
cmpltSelect.setCdComplement(Long.parseLong(value));
return cmpltSelect;
}
public String getAsString(FacesContext arg0, UIComponent arg1, Object obj) {
return String.valueOf(((ComplementsDispoSortieDTO) obj).getCdComplement());
}
}
Any help is greatly apprectiated!
Roughtly you need 3 things :
Custom converter for your object (Object to String, String to Object)
Getter/Setter with the List of your Objects choices
Getter/Setter with the List of your Objects selected
Everything is perfectly described here : RichFaces Showcase - pickList
EDIT :
Adding this should fix your problem :
<rich:pickList ...>
<f:converter converterId="cmpltsTitresConcerter" />
</rich:pickList>
also the converter property in <f:selectItems /> is not valid : f:selectItems
EDIT :
You should modify your converter like that to remove converting exceptions :
#FacesConverter(value="cmpltsTitresConcerter")
public class CmpltsTitresConcerter implements Converter
{
public Object getAsObject(FacesContext context, UIComponent component, String value)
{
ComplementsDispoSortieDTO cmpltSelect = null;
if(value != null)
{
cmpltSelect = new ComplementsDispoSortieDTO();
cmpltSelect.setCdComplement(Long.parseLong(value));
}
return cmpltSelect;
}
public String getAsString(FacesContext arg0, UIComponent arg1, Object obj)
{
String result = null;
if(obj != null)
{
result = String.valueOf(((ComplementsDispoSortieDTO) obj).getCdComplement());
}
return result;
}
}
Your selected objects are bound to the value attribute which must have a getter and setter.
Using jsf I want to edit a employee profile, when user will click on any particular datatable row,then
I am able to get all that deatils of selected patient in an
arraylist. Now I want to set all the attritbutes in arraylist to
page1.xhtml backingbean , so When user will select a particular row,
he will navigate to page1.xhtml where he will get all these fields in
the form set already by arraylist attributes.
I am trying in this way.
> page1.xhtml
<h:outputLabel value="Name" />
<p:inputText id="name1" value="#{employeeBB.emp.name}" >
</p:inputText>
<h:outputLabel value="age" />
<p:inputText id="ag" value="#{employeeBB.emp.age}" >
</p:inputText>
<h:outputLabel value="code" />
<p:inputText id="code1" value="#{employeeBB.emp.code}" >
</p:inputText>
#ManagedBean(name = "employee")
#ViewScoped
public class emp {
private String name;
private String age;
private String code;
public String getName()
{ return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
#SessionScoped
#ManagedBean
public class EmployeeBB implements serializable{
private Employe emp;
public Employee getEmp() {
return emp;
}
public void setEmp(Employee emp) {
this.emp = emp;
}
}
#SessionScoped
#ManagedBean
public class AddEmployeeBB{
private ArrayList<Employee>empList;
private ArrayList<Employee>empList;
public ArrayList<Employee> getEmpList() {
if(empList==null){
empList=new ArrayList<Employee>();
}
return empList;
}
public void setEmpList(ArrayList<Employee> empList) {
this.empList = empList;
}
public void method() throws IOException{
String code='123';
EmployeeDAO obj=new EmployeeDAO(); // DAO class
empList=obj.getAllEmplInfo(code); // will get all needed information about employee of this code in this arrayist
for(int i=0;i<empList.size();i++){
String name=empList.get(i).getName();
String age=empList.get(i).getAge();
String code=empList.get(i).getCode();
Employee e=new Employee();
e.setName(name);
e.setAge(age);
e.setCode(code);
EmployeeBB obj1=new EmployeeBB();
obj1.setEmp(e); // now according to my logic object e will set to emp object of Employee, and
// that means all these values name ,agem and code will be set to my page1.xhtml and I will be able to see it.
}
}
But I am unable to get pag1.xhtml with filled values.
Show me the way.
The reason for it not being shown is that you are setting values in a object which you are creating
EmployeeBB obj1=new EmployeeBB();
obj1.setEmp(e);
JSF lifecycle doens't know about this object and everytime you are seeing blank.
In AddEmployeeBB add this
#ManagedProperty(value="employeeBB")
private EmployeeBB employeeBB = null; // create getter setter for this
then instead of this :
EmployeeBB obj1=new EmployeeBB();
obj1.setEmp(e);
Use this:
this.employeeBB.setEmp(e);
I am facing an issue with <s:hidden /> The value is not populated.
<s:hidden name="objectName.stringName" /> works.
<s:hidden name="stringName" /> doesn't. I have getters and setters and I tried in debug mode. The getter function is called.
I also tried <s:hidden name="stringName" value="%{stringName}"/> But it did not work.
Could someone please provide any solution to this behaviour ?
EDIT :
Action class :
public class Test extends ActionSupport implements
ParameterAware, SessionAware {
private String stringName;
private ObjectA objectName;
public String getStringName() {
return stringName;
}
public void setStringName(String s) {
this.stringName = s;
}
public String getObjectName() {
return objectName;
}
public void setObjectName(ObjectA oa) {
this.objectName = oa;
}
public String execute() throws Exception {
objectName = POPULATE_THIS_OBJECT_SOMEHOW
this.stringName = objectName.getStringName();
return SUCCESS;
}
}
ObjectA :
public class ObjectA {
private String stringName;
public String getStringName() {
return stringName;
}
public void setStringName(String s) {
this.stringName = s;
}
}
I have a POJO named "FlashCard" which has a field named "links" which is collection (set) of Link objects. When I submit a FORM to my Action all the POJO fields are populated with values from the form except the collection of "links". I have no idea why this isn't getting populated.
Any advice on how to resolve this problem or how to better troubleshoot it would be much appreciated.
Also, my POJO's collection is a Set. Does it matter (or complicate things) that I'm using a Set and not a List?
I'm including a simplified version of my code below.
Here's my POJO:
public class FlashCard implements java.io.Serializable {
private int flashCardId;
private String question;
private String answer;
private Set<Link> links = new HashSet<Link>(0);
public FlashCard() {
}
public FlashCard(String question, String answer) {
this.question = question;
this.answer = answer;
}
public FlashCard(String question, String answer, Set<Link> links) {
this.question = question;
this.answer = answer;
this.links = links;
}
public int getFlashCardId() {
return this.flashCardId;
}
public void setFlashCardId(int flashCardId) {
this.flashCardId = flashCardId;
}
public String getQuestion() {
return this.question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getAnswer() {
return this.answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public Set<Link> getLinks() {
return this.links;
}
public void setLinks(Set<Link> links) {
this.links = links;
}
}
Here's the POJO for the Link object:
public class Link implements java.io.Serializable {
private int linkId;
private String url;
private Set<FlashCard> flashcards = new HashSet<FlashCard>(0);
public Link() {
}
public Link(String url) {
this.url = url;
}
public Link(String url, Set<FlashCard> flashcards) {
this.url = url;
this.flashcards = flashcards;
}
public int getLinkId() {
return this.linkId;
}
public void setLinkId(int linkId) {
this.linkId = linkId;
}
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
public Set<FlashCard> getFlashcards() {
return this.flashcards;
}
public void setFlashcards(Set<FlashCard> flashcards) {
this.flashcards = flashcards;
}
}
Here's the relevant part of the Action
public class FlashCardAction extends FlashCardsAppBaseAction implements ModelDriven<FlashCard>, Preparable, SessionAware {
static Logger logger = Logger.getLogger(FlashCardAction.class);
FlashCard flashCard = new FlashCard();
Map <String,Object> httpSession;
Session session;
FlashCardPersister fcPersister;
public Map<String, Object> getHttpSession() {
return httpSession;
}
public FlashCard getFlashCard() {
return this.flashCard;
}
public void setFlashCard(FlashCard flashCard) {
this.flashCard = flashCard;
}
public void validate() {
logger.debug("Entering validate()");
if ( flashCard.getQuestion().length() == 0 ){
addFieldError("flashCard.question", getText("error.flashcard.question"));
}
if ( flashCard.getAnswer().length() == 0 ) {
addFieldError("flashCard.answer", getText("error.flashcard.answer"));
}
}
public String saveOrUpdate() {
logger.debug("Entering saveOrUpdate()");
// assume we'll fail
boolean result = false;
// are we creating a New Flash Card or Updating and existing one
// for now, let's assume we are creating a New Flash Card
boolean newFlashCard = true;
// if this is an Update of an existing Flash CArd then we'll have a Flash Card Id other than 0
if (this.flashCard.getFlashCardId() != 0) {
newFlashCard = false;
}
try {
result = fcPersister.saveOrUpdateFlashCard(this.flashCard, session);
// did we save a new FlashCard successfully?
if (result == true && newFlashCard) {
logger.debug("Flash Card created successfully");
this.addActionMessage(getText("actionmessage.flashcard.created"));
}
// did we update an existing Flash Card successfully?
else if (result == true && newFlashCard == false) {
logger.debug("Flash Card updated successfully");
this.addActionMessage(getText("actionmessage.flashcard.updated"));
}
// such a failure
else {
logger.error("unable to create or update FlashCard");
return "error";
}
return "success";
} catch (Exception e) {
logger.error("Exception in createFlashCard():", e);
return "error";
}
}
#Override
public FlashCard getModel() {
return this.flashCard;
}
#Override
public void setSession(Map<String, Object> httpSession) {
this.httpSession = httpSession;
}
#Override
public void prepare() throws Exception {
logger.debug("Entering prepare()");
// get a handle to a Hibernate session
session = getHibernateSession();
// get a handle to the FlashCard persistance utility class
fcPersister = new FlashCardPersister();
}
}
And lastly here's the JSP
<%#page import="com.opensymphony.xwork2.ActionContext"%>
<%#page import="com.opensymphony.xwork2.ActionSupport"%>
<%# page contentType="text/html; charset=UTF-8"%>
<%# taglib prefix="s" uri="/struts-tags"%>
<%# taglib prefix="sjr" uri="/struts-jquery-richtext-tags"%>
<h3><s:text name="label.flashcard.title"/></h3>
<s:actionerror theme="jquery" />
<s:actionmessage theme="jquery"/>
<s:fielderror theme="jquery"/>
<s:form action="saveOrUpdate" method="post">
<s:hidden name="flashCard.flashCardId" />
<s:textfield name="flashCard.question" key="label.flashcard.question" size="66" />
<sjr:tinymce
id="flashCard.answer"
name="flashCard.answer"
key="label.flashcard.answer"
rows="20"
cols="50"
editorTheme="simple"
/>
<s:textfield name="flashCard.links.url" key="label.flashcard.link" size="66" />
<tr>
<td>
<s:submit label="label.flashcard.submit" align="center" theme="simple" />
</td>
<td>
<s:submit key="label.flashcard.cancel" name="redirectAction:list" theme="simple" />
</td>
</tr>
</s:form>
<%((ActionSupport)ActionContext.getContext().getActionInvocation().getAction()).clearErrorsAndMessages();%>
First of all I don't think you can use Set here, because Sets are unordered and you can't get an item from a set by an index or key like List and Map. The only way is to iterate through the set and get the items.
Second assuming you're using a collection other than set, in:
<s:textfield name="flashCard.links.url" key="label.flashcard.link" size="66"/>
You try to set the value of the text field to url field of links which is a collection and doesn't have such a field. So you need to get the specific item from the collection you're editing and pass the value. Like:
<s:textfield name="flashCard.links[0].url" key="label.flashcard.link" size="66"/>
But since you can't get the specific item you are editing I suggest you create a link field in your Action and set the updated link to it. Then you can perform a logic to relace the updated link with obsolete one in you flashcards. Hope this helps.
Since you are using modeldriven and the model is FlashCard, i think the following
<sjr:tinymce
id="flashCard.answer"
name="flashCard.answer"
key="label.flashcard.answer"
rows="20"
cols="50"
editorTheme="simple"/>
should be changed to
<sjr:tinymce
id="flashCard.answer"
name="answer"
key="label.flashcard.answer"
rows="20"
cols="50"
value="answer"
editorTheme="simple"/>
the name field should be given without the prefix flashcard.also you should provide the 'value' attribute in order for it to be pre-populated.