Unable to Pass Parameter from JSP page to Backing Bean - Unresolved Mystery
I have the following situation
2 jsp pages : greetingList.faces, greetingForm.faces
1 Backing Bean : greetingForm.java
1) greetingList.faces list the Ids & greeting Texts as shown below
Id Text
1 Hello World
2 Hello World
2) Pl note Ids are displayed as h:commandLinks. A click on the Id will render another jsp i.e. greetingForm.faces with the data pertaining to that Id and Update, Delete h:CommandButtons
3) When i click on Update command button it results in the following errors
javax.faces.FacesException: Error calling action method of component with id greetingForm:_id4
Caused by: javax.faces.el.EvaluationException: Exception while invoking expression #{greetingForm.update}
Caused by: java.lang.NullPointerException
So i verified with h:message that Id is passed as Null when click on Update button. I also checked greetingForm.jsp has a not null value by printing <h:outputText value="#{greetingForm.message.id}"/>. But onsubmit of update button it becomes null - mystery
So i guess the Id value is overwriteen with null. Also i have defined Id as property in managed bean
<managed-bean-name>greetingForm</managed-bean-name>
<managed-bean-class>com.mycompany.GreetingForm</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>id</property-name>
<value>#{param.id}</value>
</managed-property>
Any pointers/suggestions at the earliest on how to pass the value of Id on a click of update button from greetingForm.jsp to greetingForm.java will be highly appreciated
I am willing to upload my war file. Pl note i have tried all the suggestions posted on the forum like getting the value from RequestMap. Infact the Map doesnt contain the value for Id but it has the value for Text
Regards
Bansi
Hi,try setting the scope of the managed bean to "session"
Hi Seshu
Thanks for quick response. I really appreciate your help. Setting the scope of the managed bean to session results in following error
Caused by: javax.faces.FacesException: Property id references object in a scope with shorter lifetime than the target scope session
Any pointers/suggestions will be highly appreciated
Regards
Bansi
can u paste the JSP code snippets? also the navigation from faces-config.xml
Here are the snippets
-
greetingList.jsp : It will list all the greeting Ids & Text. The Ids are links
--
<h:form id="editGreeting">
<h:commandButton value="Add Greeting" action="add" id="add" immediate="true" styleClass="button"/>
<h:dataTable value="#{testJsfBean.greeting}" var="greeting" id="greetingList">
<h:column>
<f:facet name="header"><h:outputText value="Id"/></f:facet>
<h:outputLink value="detail-page.jsf?id=#{intervention.identifier}"><h:outputText value="#{intervention.identifier}"/></h:outputLink>
<h:commandLink action="#{greetingForm.edit}" value="#{greeting.id}">
<f:param name="id" value="#{greeting.id}"/>
</h:commandLink>
</h:column>
<h:column>
<f:facet name="header"><h:outputText value="Text"/></f:facet>
<h:outputText value="#{greeting.text}"/>
</h:column>
</h:dataTable>
</h:form>
greetingForm.jsp : A click on greeting Id from greetingList.jsp will render greetingForm .jsp and this works correctly as i am passsing paramter thru h:commandLink using f:param. So the good news is greetingForm.jsp displays the data correctly but when i update the Text and Submit the Form the Id looses its value and becomes Null. I verified this with h:message and from Log files. The mystery is Id loosing its value on this page
--
<h:form id="greetingForm">
<h:panelGrid>
<h:outputLabel for="text" value="Greeting Text"/>
<h:inputText value="#{greetingForm.message.text}" id="text"/>
<h:message for="text" />
<h:panelGroup>
<c:choose>
<c:when test="${not empty greetingForm.id}">
<h:commandButton value="Update" action="#{greetingForm.update}"/>
<h:commandButton value="Delete" action="#{greetingForm.delete}"/>
</c:when>
<c:otherwise>
<h:commandButton value="Save" action="#{greetingForm.save}"/>
</c:otherwise>
</c:choose>
</h:panelGroup>
</h:panelGrid>
</h:form>
GreetingForm.java : Is a Backing Bean
public class GreetingForm {
private final Log logger = LogFactory.getLog(GreetingForm.class);
private String id;
public Message message = new Message();
public TestSpringBean testSpringBean;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}
public void setTestSpringBean(TestSpringBean testSpringBean) {
this.testSpringBean = testSpringBean;
}
public TestSpringBean getTestSpringBean() {
return testSpringBean;
}
public String edit() {
logger.info(" *** In greetingForm.edit method with id = "+id);
if (id != null) {
setMessage(testSpringBean.getMessage(id));
}
return "success";
}
public String save() {
logger.info(" *** In greetingForm.save method *** ");
testSpringBean.saveMessage(getMessage());
return "success";
}
public String update() {
/*FacesContext fc = FacesContext.getCurrentInstance();
java.util.Map requestParameter = fc.getExternalContext().getRequestParameterMap();
for (Iterator it = requestParameter.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
logger.info("Key="+key+"Value="+value);
}*/
logger.info(" *** In greetingForm.update method with id = "+getMessage().getId());
testSpringBean.updateMessage(getMessage());
return "success";
}
public String delete() {
logger.info(" *** In greetingForm.delete method *** ");
testSpringBean.removeMessage(getMessage().getId().toString());
return "success";
}
faces-config.xml
-
<faces-config>
<application>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
</application>
<navigation-rule>
<from-view-id>/greetingList.jsp</from-view-id>
<navigation-case>
<from-outcome>add</from-outcome>
<to-view-id>/greetingForm.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/greetingForm.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/greetingForm.jsp</from-view-id>
<navigation-case>
<from-outcome>cancel</from-outcome>
<to-view-id>/greetingList.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/greetingList.jsp</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
<managed-bean>
<managed-bean-name>testJsfBean</managed-bean-name>
<managed-bean-class>
com.mycompany.TestJsfBean
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>testSpringBean</property-name>
<property-class>
com.mycompany.TestSpringBean
</property-class>
<value>#{testSpringBean}</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>greetingForm</managed-bean-name>
<managed-bean-class>com.mycompany.GreetingForm</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<managed-property>
<property-name>id</property-name>
<value>#{param.id}</value>
</managed-property>
<managed-property>
<property-name>testSpringBean</property-name>
<property-class>
com.mycompany.TestSpringBean
</property-class>
<value>#{testSpringBean}</value>
</managed-property>
</managed-bean>
</faces-config>
--
TestSpringBean : Is at Business Layer
--
public void updateMessage(Message message) {
logger.info(" *** In testSpringBean.updateMessage method *** ");
testDaoHibernate.updateMessage(message);
}
TestDaoHibernateBean : Is at Persistence Layer
public void updateMessage(Message message) {
logger.info(" *** In testDaoHibernate.updateMessage method *** ");
hibernateTemplate.update(message);
}
--
hello.hbm.xml : Mapping File
--
<hibernate-mapping>
<class name="com.mycompany.Message" table="MESSAGES">
<id name="id" column="MESSAGE_ID">
<generator class="increment"/>
</id>
<property name="text" column="MESSAGE_TEXT"/>
</class>
</hibernate-mapping>
Once again i really appreciate your help
Regards
Bansi
Hi Bansi,
in the greetingForm.jsp where is "id" being declared? it's not a hidden parameter nor it is any UI component. you are just using it to test a if condition.
are u losing the "id" after you submit greetingForm.jsp (which means that "id" is accessible in greetingForm.jsp before the submit)
-S
Hi Seshu
You are perfectly right. I am loosing the Id when i submit greetingForm.jsp . But before submit the "id" is accessible in greetingForm.jsp .
I am wondering why do i need to declare the "id" in greetingForm.jsp as i expect it to get its value from greetingList.jsp when i click the Id
You are again right it's not a hidden parameter nor it is any UI component . I am just using to test a if condition.
Am i missing something here. Do we need to declare the id in greetingForm.jsp so that it becomes part of UIComponent. I tried even declaring the the id in greetingForm.jsp as follows
<h:outputLabel for="id" value="Id"/>
<h:inputText value="#{greetingForm.message.id}" id="id"/>
When i redeployed the application and click on Update button this time doesnt result in anything even it doesnt show anything in Log file. So i added <h:message for ="id"> . Now click on update button shows following error
"id": Error during model data update.
Also nothing gets displayed in the Log file. Here is the update method in GreetingForm.java
public String update() {
logger.info(" *** In greetingForm.update method with id = "+id);
//testSpringBean.updateMessage(getMessage());
return "success";
}
Regards
Bansi
//I am wondering why do i need to declare the "id" in greetingForm.jsp as i expect it to get its value from greetingList.jsp when i click the Id//
how do you expect the backing bean to get this "id" value? you will get the value of "id" in the greetingForm as it is a request parameter. But when you submit greetingForm it's again a new request. As such, the backing bean gets these values only if "id" is set as some property in the HTML form on the greetingForm.jsp.
clear?
//<h:outputLabel for="id" value="Id"/>
<h:inputText value="#{greetingForm.message.id}" id="id"/>//
when you did this, is the value of "id" displayed in the text field?
Do you have "id" property in the backing bean for greetingForm?
-S
Thanks Seshu. Thats really a wonderful point. I forgot about that as i am new to JSF.
Yep the value of id is displayed in the text field.
Yep i have "id" property in the backing bean for greetingForm. Infact i have designed the Backing Bean to have all the attributes in domain object i.e. Message.java.
So my backing bean i.e.greetingForm.java is
public String id;
public String text;
public Message message = new Message();
public TestSpringBean testSpringBean;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setText(String text){
this.text=text;
}
public String getText(){
return text;
}
public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}
public String update() {
/*Due to the error "id": Error during model data update on click of submit button . I modified the value of "#{greetingForm.message.id} to
"#{greetingForm.id}" i.e. removed the reference to domain object message in value binding expression. Thinking that it will pick up the value from faces-config.xml where "id" is defined as parameter to greetingForm and it worked . I mean the error is gone and the below logger shows the correct value for "Id". But the value for "Text" is shown as null .ie. #{greetingForm.message.text}. That means on submit of the Form the setxxx() and getxxx() methods are not called */
logger.info(" *** Message id = "+getId()+"Message Text="+getText());
//testSpringBean.updateMessage(message);
return "success";
}
Here is the log trace
2006-10-09 13:30:11,516 INFO [com.mycompany.GreetingForm] - < *** Message id = 18Message Text=null>
This time i tried printing the values passed from jsp to backing bean using . Here is the log trace
2006-10-09 13:30:11,514 INFO [com.mycompany.GreetingForm] - <Key=greetingForm:idValue=18>
2006-10-09 13:30:11,516 INFO [com.mycompany.GreetingForm] - <Key=greetingForm:textValue=12318>
2006-10-09 13:30:11,516 INFO [com.mycompany.GreetingForm] - <Key=greetingForm:_id5Value=Update>
2006-10-09 13:30:11,516 INFO [com.mycompany.GreetingForm] - <Key=greetingForm:_link_hidden_Value=>
2006-10-09 13:30:11,516 INFO [com.mycompany.GreetingForm] - <Key=greetingForm_SUBMITValue=1>
2006-10-09 13:30:11,516 INFO [com.mycompany.GreetingForm] - < *** In greetingForm.update method with id = 18>
2006-10-09 13:30:11,516 INFO [com.mycompany.GreetingForm] - < *** Message id = 18Message Text=null>
Regards
Bansi
Hi Seshu
Thinking some more .... i understood that putting #{greetingForm.id} in greetingForm.jsp is wrong. The correct way is
#{greetingForm.message.id} i.e. reference to domain object i.e. message as the Id & Text needs to pick its value from message
But the problem persist . The Id still has Null value when i Submit the Form but it gets displayed with proper value on the Form even with #{greetingForm.message.id}. Now if i submit the form h:message gives the error "id: Error during model data update "
Regards
Bansi
//The Id still has Null value when i Submit the Form but it gets displayed with proper value on the Form even with #{greetingForm.message.id}.//
see, when you use #{greetingForm.message.id}, JSF will retrieve the value from the greetingForm's backing bean, which is null obviously.
Now, just use #{id}. In this case, JSF will look for this variable in the page, request, session etc. But since it finds "id" in request scope it'll use that.
Rest all would be the same.
Hi Seshu
Thank you so much. #{greetingForm.message.id}. works. I couldn't believe myself what was preventing it to work early. The only change i did was to make Backing Bean in synch with model bean i.e. in terms of attributes so i added text attribute with getXXX & setXXX to backing bean. Pl note "id" was already defined in backing bean.
Wondering how do we leverage or update model object from backing bean in real time applications. Currently in my prototype i have
1) Message as my model object
2) GreetingForm.java as backing bean in which i levereage model object as
Message message = new Message()
And
Also define all the attributes of model object in backing bean i.e. in synch.
Is it the right approach even in real time applications.
I would like to thank you once again for your HELP and would like to keep in touch with you to share your experience and knowledge in JSF.
My email is mail2bansi@yahoo.com and i am in Seattle. Wish you are somewhere around me for more help :)-
Glad that i cud be of help. I'm a beginner in JSF too. Looks like that's the way of doing it.But, every JSP will have "code behind" java file just like your GreetingForm.java, that could be used to effectively synch.So, are the duke dollars mine now? :)
Thanks Seshu. I am still wondering how do we populate Model Object in real time applications using JSF.
Here is the situation
Step 1:
The moment you submit a Form on JSP page it populates the Backing Bean using Java Reflection i.e. the plain JSP-JavaBean technology.
Step 2:
After doing Validations & Conversions in Backing Bean the data is submitted to Buisness Layer ( e.g. userManager in Spring) for Business Logic Processing
Step 3:
Then data goes to Integration & Persistence Layer
In all these steps when and where exactly the Model object gets updated with the values from JSP page . There might be a situation where business logic operates on Model object
For example in my case
Model Object is Message.java and its being instantiated inside Backing Bean as Message message = new Message();
Now when i do CRUD i need to get a handle to message object as its defined within backing bean. Is it how its done even in real time applications
Regards
Bansi
Hi,
I dint have enough time to read all replies, but I think ur problem is to pass parameters from UI to Backing bean. This is been explained in the following link.
http://balusc.xs4all.nl/srv/dev-jep-com.html.
If u use session scope u can easily do it. Using request scope, need to check once.
Regards
Sravan