Announcement Announcement Module
Collapse
No announcement yet.
referencedata and formbackingobject Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • referencedata and formbackingobject

    Hello all..

    Just started with the SpringMVC framework. Writing a test application to get my hands around spring development. My test application for now is basically a simple web page which displays a table of device data pulled from the database.
    This data is retrieved based on certain conditions like starttime, endTime and device-name.

    From what I read of the spring-mvc-reference and from my search on google for spring tutorials, I have gathered that the referencedata method should be used to populate form data, in my case a simple drop-down list. The form backing object is used by the form to fill data in. I am successfully loading the device names in the drop-down via the reference data method and displaying it in the JSP using the following code

    Code:
    <select>
     <option value="">-Please select from the drop-down-</option>
        <c:forEach var="item" items="${devnames}">
            <option value='<c:out value="${item}"/>'><c:out value="${item}"/>   
            </option>
        </c:forEach>
    </select>
    However I would instead like to use the spring's form tag library and code the above like this
    Code:
    <form:select path="devnames" items="${devnames}"/>
    But to do that, I need to define my list of devicenames in my commandclass. I am not sure, if its the right approach to load the list of devicenames via the command class and if so how?? Do i do this via the formbackingobject method?? I am already using a command object to get the starttime and the endtime from the form. When the form is submitted, I need the user selected device name , starttime and the endtime to retrieve data and display the data in the table.

    Should all these (device-names list, startime and endtime) be defined in one command class??

    All help is appreciated!! Thank You

  • #2
    <form:select path="devnames" items="${devnames}"/>
    But to do that, I need to define my list of devicenames in my commandclass. I am not sure, if its the right approach to load the list of devicenames via the command class and if so how??
    you have done the right thing, you dont need to have the devnames in the command object though,
    the devnames is just a variable reference or a key in the map that is returned as part of the referenceData.

    though just beaware that the items must be eithere a java.util.Map, or a list type or a collection type.
    if you have custom objects in the collection then you can use the itemValue and itemLabel attributes of the form select tag.

    for example:
    Code:
    public class DeviceName {
    private String name;
    private String type;
    // setter and getters for this
    }
    you can do the following , assuming you have a collection of DeviceName class
    Code:
    <form:select path="devname" items="${devnames}" itemValue="type" itemLabel="name"/>
    or
    Code:
    <form:select path="devname">
    <form:options items="${devnames}" itemValue="type" itemLabel="name"/>
    </form:select>
    adding the collection of devnames to the command object doesnt make any sense

    Comment


    • #3
      spring throws exception

      Thanks Sami for the detailed post

      I am posting my code below for my controller(MenuController.java), commandclass (Test.java) and front view(menu.jsp)

      Spring throws an exception when I try to use the form:select tag.

      Heres the code

      ****MenuController.java*****************
      Code:
      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServletRequest;
      
      import org.springframework.validation.Errors;
      import org.springframework.web.servlet.ModelAndView;
      import org.springframework.web.servlet.mvc.SimpleFormController;
      import org.springframework.web.servlet.view.RedirectView;
      
      
      import com.test.DeviceManager;
      import com.util.Test;
      
      public class MenuController extends SimpleFormController
      {
      	public MenuController() 
             {        
                 setCommandName("menu");
                 setCommandClass(MenuController.class);       
             } 
      	
      	public Map referenceData(HttpServletRequest req, Object obj, Errors errors) throws Exception {
      		Map devs= new HashMap();		
      		devs.put("names",DeviceManager.getdevsNames());		
      		return devs;
      		}
      
      	
      	 public ModelAndView onSubmit(Object command) throws ServletException {
      	    	
      		 
      	   String startTime = ((Test)command).getStartTime();
      	   String endTime = ((Test)command).getEndTime();       
      	   logger.info("Returning Device Controller view ONSUBMIT");        
      	   logger.info("StartTime is " + startTime + "EndTime is :" + endTime);
      	   return new ModelAndView(new RedirectView(getSuccessView()));
       
      	    }
      
      	    protected Object formBackingObject(HttpServletRequest request) throws ServletException {
      	    	
      	        Test cal = new Test();       
      	        return cal;
      	    }
      
      
      }
      *********Test.java*****************************
      Code:
      import org.apache.commons.logging.Log;
      import org.apache.commons.logging.LogFactory;
      
      public class Test {
      
          /** Logger for this class and subclasses */
          protected final Log logger = LogFactory.getLog(getClass());
      
          private String startTime;
          private String endTime;
        
          
      	public String getStartTime() {
      		return startTime;
      	}
      	public String getEndTime() {
      		return endTime;
      	}
      	public void setStartTime(String startTime) {
      		this.startTime = startTime;
      		logger.info("StartTime set to " + startTime);
      
      	}
      	public void setEndTime(String endTime) {
      		this.endTime = endTime;
      		logger.info("EndTime set to " + endTime);
      
      	}
      	
         
      }
      *******************Menu.jsp*********************** ******

      Code:
           <form:form method="post" commandName="menu">
        
      
         <form:select path="devs">
             <form:option value="-" label="--Please Select"/>
             <form:options items="${devs}"  itemValue="devs" itemLabel="devs"/>
          </form:select>
      
      	  <table cellspacing="0" cellpadding="5">
      	    <tr>
      	      <td align="right" width="20%">StartTime:</td>
      	        <td width="20%">          
      	            <form:input path="startTime" id="startTime"/>                
      	        </td>
      	      <td align="right" width="20%">EndTime:</td>
      	        <td width="20%">          
      	            <form:input path="endTime" id="endTime"/>                
      	        </td>         
      	    </tr>
      	  </table>
      	  <br />
      	  <input type="submit" align="center" value="Execute" />      
      	</form:form>

      The code in red is the offending code...Spring throws the following exception
      Code:
      org.springframework.beans.NotReadablePropertyException: Invalid property 'devs' of bean class [com.util.Test]: Bean property 'devs' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
      at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:540)
      	at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:532)
      	at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:79)
      	at org.springframework.validation.AbstractBindingResult.getFieldValue(AbstractBindingResult.java:226)
      	at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:120)
      .....
      .....
      .....
      I am pretty sure, its because I have defined the commandName for the form , it looks in the corresponding commandclass for the devs property and yells when it doesnt get one. Thats why I wasnt sure If I had to retrieve the devicelist via the commandclass as well. So my basic target is to retrieve the
      1. starttime 2, endtime 3. selected devicename on FORM SUBMIT and then reload the same page with the table of data retrieved from the database.

      Right now I am facing the issue of where and how should these properties be defined?? that is the starttime and endtime and the list of devices. Devicelist , I gather should be retrieved via the referencedata method, so thats solved.
      however I am not sure how to iterate through it in the menu.jsp using the form:select tag ?? also am i right in defining the starttime and endtime as properties of the commandclass?? These might be needed along with other properties across future webpages, how would I then resue the same command class ??

      Thanks for all the help!!
      Last edited by myspringworld; Sep 29th, 2008, 12:40 AM.

      Comment


      • #4
        Hi,


        can you post the MenuController.class since you have defined it as command object.

        what does the DeviceManager.getdevsNames() return?

        if it returns collection what is the type of the object?

        is it the Test.class?

        Comment


        • #5
          Hi Sami25

          I did post the MenuController.java which is my Controller class.

          Also my commandclass is Test.java, which I have posted as well.

          the DeviceManager.getdevsNames() returns a collection (a java.util.ArrayList).

          Here is the snippet from my servlet mapping file

          Code:
          <bean name="/menu.htm" class="com.controllers.MenuController">
                  <property name="commandName" value="menu" />
                  <property name="formView" value="menu"/>    
                  <property name="sessionForm" value="true" />
                  <property name="commandClass" value="com.util.Test"/>
                  <property name="successView" value="menu.htm"/>     
          </bean>
          Also reposting the code as well
          ********MenuController.java****************

          Code:
          import java.util.ArrayList;
          import java.util.HashMap;
          import java.util.List;
          import java.util.Map;
          
          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServletRequest;
          
          import org.springframework.validation.Errors;
          import org.springframework.web.servlet.ModelAndView;
          import org.springframework.web.servlet.mvc.SimpleFormController;
          import org.springframework.web.servlet.view.RedirectView;
          
          
          import com.test.DeviceManager;
          import com.util.Test;
          
          public class MenuController extends SimpleFormController
          {
          	public MenuController() 
                 {        
                     setCommandName("menu");
                     setCommandClass(MenuController.class);       
                 } 
          	
          	public Map referenceData(HttpServletRequest req, Object obj, Errors errors) throws Exception {
          		Map devs= new HashMap();		
          		devs.put("names",DeviceManager.getdevsNames());		
          		return devs;
          		}
          
          	
          	 public ModelAndView onSubmit(Object command) throws ServletException {
          	    	
          		 
          	   String startTime = ((Test)command).getStartTime();
          	   String endTime = ((Test)command).getEndTime();       
          	   logger.info("Returning Device Controller view ONSUBMIT");        
          	   logger.info("StartTime is " + startTime + "EndTime is :" + endTime);
          	   return new ModelAndView(new RedirectView(getSuccessView()));
           
          	    }
          
          	    protected Object formBackingObject(HttpServletRequest request) throws ServletException {
          	    	
          	        Test cal = new Test();       
          	        return cal;
          	    }
          
          
          }
          ***************Test.java*****************

          Code:
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;
          
          public class Test {
          
              /** Logger for this class and subclasses */
              protected final Log logger = LogFactory.getLog(getClass());
          
              private String startTime;
              private String endTime;
            
              
          	public String getStartTime() {
          		return startTime;
          	}
          	public String getEndTime() {
          		return endTime;
          	}
          	public void setStartTime(String startTime) {
          		this.startTime = startTime;
          		logger.info("StartTime set to " + startTime);
          
          	}
          	public void setEndTime(String endTime) {
          		this.endTime = endTime;
          		logger.info("EndTime set to " + endTime);
          
          	}
          	
             
          }
          *************Menu.jsp*****************
          Code:
              <form:form method="post" commandName="menu">
            
          
             <form:select path="devs">
                 <form:option value="-" label="--Please Select"/>
                 <form:options items="${devs}"  itemValue="devs" itemLabel="devs"/>
              </form:select>
          
          	  <table cellspacing="0" cellpadding="5">
          	    <tr>
          	      <td align="right" width="20%">StartTime:</td>
          	        <td width="20%">          
          	            <form:input path="startTime" id="startTime"/>                
          	        </td>
          	      <td align="right" width="20%">EndTime:</td>
          	        <td width="20%">          
          	            <form:input path="endTime" id="endTime"/>                
          	        </td>         
          	    </tr>
          	  </table>
          	  <br />
          	  <input type="submit" align="center" value="Execute" />      
          	</form:form>
          Hope I am clear

          Comment


          • #6
            Hi,

            Code:
            <form:select path="devs">
                   <form:option value="-" label="--Please Select"/>
                   <form:options items="${names}" />
                </form:select>
            its important that you know what is the type of the object inside the java.util.ArrayList , then you can use the members to map to the itemValue and itemLabel of the form tag.

            modify as follows
            Code:
            <bean name="/menu.htm" class="com.controllers.MenuController">
                    <property name="commandName" value="menu" />
                    <property name="formView" value="menu"/>    
                 
                    <property name="commandClass" value="com.util.Test"/>
                    <property name="successView" value="menu.htm"/>     
            </bean>
            Code:
            public class MenuController extends SimpleFormController
            {
            	public MenuController() 
                   {        
                      // setCommandName("menu");
                      // setCommandClass(MenuController.class);       
                   }

            Comment


            • #7
              still getting the same exception...

              Hi sami25,

              The arraylist is a list of STRING OBJECTS. I did the changes suggested by you..have replaced everything by names to avoid any confusion...however I still get the same error.
              Following is the changed code

              ***************servlet-mapping file**************************
              Code:
              <bean name="/menu.htm" class="com.controllers.MenuController">
                      <property name="commandName" value="menu" />
                      <property name="formView" value="menu"/>    
                   
                      <property name="commandClass" value="com.util.Test"/>
                      <property name="successView" value="menu.htm"/>     
              </bean>
              I have hard-coded the arraylist for now..so you get a clear picture

              ************MenuController.java******************

              Code:
              public MenuController() {
                      
                      //setCommandName("menu");
                      //setCommandClass(MenuController.class);       
              } 
              
              public Map referenceData(HttpServletRequest req, Object obj, Errors errors) throws Exception {
              		Map names= new HashMap();
              		List nm= new ArrayList();
              		nm.add("103"); 
              		nm.add("104");
              		nm.add("105");
              		
              		names.put("names",nm);		
              		return names;
              		}
              ******************Menu.jsp*********************


              Code:
              
              <form:form method="post" commandName="menu">
              <form:select path="names">
                     <form:option value="-" label="--Please Select"/>
                     <form:options items="${names}" />
              </form:select>
              The exception thrown by the application is..

              Code:
              SEVERE: Servlet.service() for servlet springapp threw exception
              org.springframework.beans.NotReadablePropertyException: Invalid property 'names' of bean class [com.util.Test]: Bean property 'names' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter? at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:540)
              at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:532)
              .......
              ..........
              ..............
              ............
              ............
              Please note, the application works fine and the drop-down is populated if I
              replace the code in red by the following code

              Code:
              <form:form method="post" commandName="menu">
                     <select>
              		    <option value="">--</option>
              		    <c:forEach var="devname" items="${names}">
              		        <option value='<c:out value="${devname}"/>'>
                                       <c:out value="${devname}"/></option>
              		    </c:forEach>
              </select>
              I think it searches for the property "names" in the commandclass defined com.util.Test and throws an exception because it doesnt find it there.
              Still not sure how to fix this...

              Comment


              • #8
                Code:
                <form:form method="post" commandName="menu">
                <form:select path="names">
                <!-- you should have a member in the command object that is com.util.Test
                the path always refers to a member in the form object -->
                       <form:option value="-" label="--Please Select"/>
                       <form:options items="${names}" />
                </form:select>
                Actually spring is trying to bind the selected item to a datamember in the form object, either you add a member called as names in the com.util.Test or refer to an existing member like startTime and endTime

                I have modified the jsp for you to access
                Code:
                <form:select path="devs">
                       <form:option value="-" label="--Please Select"/>
                       <form:options items="${names}" />
                </form:select>
                Sample code : that has the devs as a data member
                Code:
                package com.test;
                
                import java.io.Serializable;
                import org.apache.commons.logging.Log;
                import org.apache.commons.logging.LogFactory;
                public class Test implements Serializable {
                
                	
                
                	
                
                	    /** Logger for this class and subclasses */
                	    protected final Log logger = LogFactory.getLog(getClass());
                // added for test purpose, you can add any member , but remember to change in the jsp	    
                private String devs;
                	    private String startTime;
                	    private String endTime;
                	  
                	    
                		public String getStartTime() {
                			return startTime;
                		}
                		public String getEndTime() {
                			return endTime;
                		}
                		public void setStartTime(String startTime) {
                			this.startTime = startTime;
                			logger.info("StartTime set to " + startTime);
                
                		}
                		public void setEndTime(String endTime) {
                			this.endTime = endTime;
                			logger.info("EndTime set to " + endTime);
                
                		}
                		public String getDevs() {
                			return devs;
                		}
                		public void setDevs(String devs) {
                			this.devs = devs;
                		}
                		
                	   
                	
                }

                Comment


                • #9
                  hmmn....well I did guess that the path would refer to a member in the commandobject ...however my arguement in the first place(please correct me if I am wrong) was that the referencedata(in this case my collection of device names) should not be a member of the commandObject. Hence I had not made the list of device names (retrieved from the database in the referenceData method and displayed when view first loads) a member of the commandobject.

                  All said , I was wondering if I could somehow use the <form:select> tag to display my drop-down list of device names. From the discussion so far, I think the only way to do that is by making my devicenames collection a part of the commandobject (i.e com.util.Test), which is design-wise incorrect. Am I right??

                  Thanks!!

                  Comment


                  • #10
                    Hi,

                    Yes, the path does refer to the command object. This is where the value(s) selected from the dropdown by the user will be stored during databinding. In your example the Test class get/setDevs methods will be used by Spring to manage the databinding of the device selected from the dropdown by the user.

                    The values that are displayed in the dropdown to the user to make selections from, are loaded using the referenceData method on the controller.

                    So in summary, use referenceData to load the values that the user can make selections from, and use the command object to store the values the user has selected.

                    I believe this matches with the code changes suggested by Sami, the get/setDevs methods are used to store the user selected value, not the values the user can make choices from.

                    Hope this helps,

                    Chris

                    Comment

                    Working...
                    X