Announcement Announcement Module
Collapse
No announcement yet.
IoC for SimpleFormController.commandClass Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • IoC for SimpleFormController.commandClass

    Hi,

    SimpleFormController usually used so:

    Code:
    <bean id="queryController" class="web.QueryController">
      <property name="sessionForm"><value>true</value></property>
      <property name="commandName"><value>queryBuilder</value></property>
      <property name="commandClass"><value>bus.QueryBuilder</value></property>
      <property name="validator"><ref bean="queryValidator"/></property>
      <property name="formView"><value>query</value></property>
      <property name="successView"><value>result</value></property>
    </bean>
    How can I use IoC for SimpleFormController.commandClass in this way:

    Code:
    <bean id="queryBuilder" class="bus.QueryBuilder">
    ...
    </bean>
    
    <bean id="queryController" class="web.QueryController">
      <property name="sessionForm"><value>true</value></property>
      <property name="command"><ref bean="queryBuilder"/></property> 
      <property name="validator"><ref bean="queryValidator"/></property>
      <property name="formView"><value>query</value></property>
      <property name="successView"><value>result</value></property>
    </bean>
    What is the right way to use some objects (DataSource, for example) in command?

  • #2
    If you're looking to pass some helper objects, like a datasource or a business facade, you shouldn't use the command properties.
    The command is used to represented data from and to the user, it is purely business related, without logic. When you need logic (datasources, ...) add a custom property in your subclass of simple form controller and use your own setters to inject those dependancies

    HTH

    Olivier

    Comment


    • #3
      You can actually override the formBackingObject() method, in which case you don't need to set the commandClass property. So your formBackingObject() method could do whatever it wanted.

      But, make sure it doesn't return a normal singleton bean you have injected in somehow. The controllers are supposed to be singletons, they get used for multiple requests. So if you always return the same command instance, multiple requests will trample on each other.

      One completely viable approach is to do lookup method injection as defined in the bean s chapter in the manual, to inject a lookup method into your form controller, with this lookup method returning a new prototype instance of the command on each invocaiton. Then you just hook up the formBackingObject() method to return the result of the lookup method you have injected. I hope this is clear....

      Comment


      • #4
        Are you wanting to do something like:

        Code:
        <bean id="dataSource" ...>...</bean>
        
        <bean id="queryBuilder" class="bus.QueryBuilder">
        ...
        </bean>
        
        <bean id="queryController" class="web.QueryController">
          <property name="sessionForm"><value>true</value></property>
          <property name="command"><ref bean="queryBuilder"/></property>
          <property name="validator"><ref bean="queryValidator"/></property>
          <property name="formView"><value>query</value></property>
          <property name="successView"><value>result</value></property>
          <property name="queryBuilder"><ref bean="queryBuilder"></property>
          <property name="dataSource"><ref bean="dataSource"></property>
        </bean>
        if so, it works beautifully, just keep in mind that Spring manages the Controller as a singleton and everything will be fine.

        Comment


        • #5
          No.

          Simplest way for me is using separate bean for perfoming query:

          Code:
          <bean id="dataSource" ...>...</bean>
          
          <bean id="requester" class="bus.Requester">
            <property name="dataSource"><ref bean="dataSource"/></property>
            <property name="params"><value>null</value></property>
          </bean>
          I can set params property to queryBuilder by code in SimpleFormController.onSubmit. But how can I use requester object in my code? What I need to write to web.xml, dbquery-servlet.xml and onSubmit?

          Now them looks like:

          web.xml:

          Code:
          <web-app>  
            <servlet>
              <servlet-name>dbquery</servlet-name>    	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
              <load-on-startup>1</load-on-startup>
            </servlet>
            <servlet-mapping>
              <servlet-name>dbquery</servlet-name>
              <url-pattern>*.html</url-pattern>
            </servlet-mapping>
            <welcome-file-list>
              <welcome-file>
                index.jsp
              </welcome-file>
            </welcome-file-list>
            <taglib>
              <taglib-uri>/spring</taglib-uri>
              <taglib-location>/WEB-INF/spring.tld</taglib-location>
            </taglib>    
          </web-app>
          dbquery-servlet.xml:

          Code:
          <beans>
              <bean id="queryValidator" class="bus.QueryValidator"/>    
              <bean id="queryController" class="web.QueryController">
          	<property name="sessionForm"><value>true</value></property>
              	<property name="commandName"><value>queryBuilder</value></property>
              	<property name="commandClass"><value>bus.QueryBuilder</value></property>
              	<property name="validator"><ref bean="queryValidator"/></property>
          	<property name="formView"><value>query</value></property>
          	<property name="successView"><value>result</value></property>
              </bean>    
              <bean id="resultController" class="web.ResultController"/>    
              <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> 
                  <property name="mappings">
                      <props>
                          <prop key="/query.html">queryController</prop>
                      </props>
                  </property>
              </bean>
              <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                  <property name="viewClass">
                     <value>org.springframework.web.servlet.view.JstlView</value>
                  </property>
                  <property name="prefix"><value>/WEB-INF/jsp/</value></property>
                  <property name="suffix"><value>.jsp</value></property>
              </bean>             
          </beans>
          SimpleFormController.onSubmit:

          Code:
          protected ModelAndView onSubmit&#40;Object object&#41; throws Exception &#123;
          		
          	QueryBuilder builder = &#40;QueryBuilder&#41; object;
          
          	// How can I get requester in this place?
          
          	requester.setParams&#40;builder&#41;;
          	requester.execute&#40;&#41;;
          		
          	Map model = new HashMap&#40;&#41;;
          	model.put&#40;"result", requester.getResult&#40;&#41;&#41;;
          		
          	return new ModelAndView&#40;getSuccessView&#40;&#41;, model&#41;;
          &#125;

          Comment


          • #6
            I'm not clear from your bean definition for the requester if it's a singleton or not. Looks like it is, in which case, just inject it as a normal property into your controller. If the requester needs to be a prototype, just do Lookup Method Injection as described in the manual (bean factory chapter) to inject a createRequester() method which will return a prototype instance from the appcontext.

            Comment

            Working...
            X