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

  • registerCustomEditors for Controller

    I'm trying to translate values of an enum class (Civility) with Webflow.
    Civility class contains MR, MRS, etc.
    My aim is to bind those keys to their translated value in the database (MR = Monsieur)
    It was working perfectly with Spring MVC. But after a switch for Spring Webflow, this isn't working anymore.

    With Spring MVC
    In the following JSP, I used the civilities field from the command.
    Code:
    <div>
    	<form:label path="person.civility"><fmt:message key="civility"/></form:label>
    	<form:select path="person.civility" items="${registerCommand.civilities}" multiple="false"/>
    </div>
    Code:
    public class RegisterCommand implements Serializable {
        public Civility[] getCivilities() {
            return Civility.values();
        }    
    ...
    }
    This civilities field is translated thank to my CivilityBinder called by the initBinder method.

    CivilityBinder
    Code:
    public class CivilityBinder extends PropertyEditorSupport {
        private PortalService portalService;
    
        public CivilityBinder(PortalService portalService) {
            this.portalService = portalService;
        }
    
        public String getAsText() {
            Civility civility;
            civility = (Civility) getValue();
            if (civility != null)
                return portalService.getMessageSource().getMessage(civility.toString(), null, LocaleContextHolder.getLocale());
            else
                return null;
        }
    
        public void setAsText(final String text) throws IllegalArgumentException {
            if (text != null && text.trim().length() > 0) {
                for (Civility civility : Civility.values()) {
                    if (portalService.getMessageSource().getMessage(civility.toString(), null, LocaleContextHolder.getLocale()).compareTo(text) == 0) {
                        setValue(civility);
                    }
                }
            }
        }
    }
    and the annotated method @InitBinder in the Controller.

    RegisterController
    Code:
    @SuppressWarnings({"unchecked"})
    @Controller("registerController")
    public class RegisterController extends FormAction {
    ...
        @InitBinder
        protected void registerPropertyEditors(final PropertyEditorRegistry registry) {
            registry.registerCustomEditor(String.class, new StringTrimmerEditor(true));
            registry.registerCustomEditor(Civility.class, new CivilityBinder(portalService));
        }
    ...
    }
    With Spring WebFlow
    I tryed with a custom class PropertyEditors passed as a propertyEditorRegistrar parameter for the controller and with the
    @Override
    protected void registerPropertyEditors(final PropertyEditorRegistry registry)

    If I don't do a bind myself, both registerPropertyEditors and propertyEditorRegistrar are ignored.

    webmvc-config.xml
    Code:
        <!--<context:component-scan base-package="mypackage.web.controller"/>-->
        <bean id="registerController" class="mypackage.web.controller.RegisterController">
            <property name="formObjectClass" value="mypackage.web.command.RegisterCommand"/>
            <property name="propertyEditorRegistrar">
                <bean class="mypackage.web.binder.PropertyEditors"/>
            </property>
        </bean>
        <context:component-scan base-package="mypackage.web.binder"/>
        <context:component-scan base-package="mypackage.web.service"/>
        <context:component-scan base-package="mypackage.web.validator"/>
    
        <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
            <property name="webBindingInitializer">
                <bean class="mypackage.web.binder.BindingInitializer"/>
            </property>
        </bean>
    
        <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
            <property name="interceptors" ref="localeChangeInterceptor"/>
        </bean>
    
        <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
            <property name="defaultLocale" value="en"/>
        </bean>
        <bean id="localeChangeInterceptor" class="mypackage.web.i18n.LocaleChangeInterceptor">
            <property name="paramName" value="l"/>
        </bean>    
    
        <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="interceptors" ref="localeChangeInterceptor"/>
            <property name="mappings">
                <value>
                    /registration/register.html=flowController
                </value>
            </property>
            <property name="alwaysUseFullPath" value="true"/>
        </bean>
    
        <bean id="messageSource" class="mypackage.core.i18n.DataBaseMessageSource"/>
    
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">
        </bean>
    
        <bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
            <property name="flowExecutor" ref="flowExecutor"/>
        </bean>
        ...
    </beans>

    The flow state definition
    register.xml
    Code:
     <action-state id="setup">
            <evaluate expression="registerController.bind"/>
            <evaluate expression="registerController.setup"/>
            <transition on="register_startnew" to="step1"/>
            <transition on="register_continue" to="step2"/>
            <transition on="register_unknownuuid" to="step1"/>
            <transition on="register_done" to="step4"/>
        </action-state>
        
        <view-state id="step1" view="register-step1" model="registerCommand">
            <transition on="next" to="step2" validate="true"/>
            <on-exit>
                <evaluate expression="registerController.bind"/>
                <evaluate expression="registerController.step1"/>
            </on-exit>
        </view-state>
    
        <view-state id="step2" view="register-step2" model="registerCommand">
            <transition on="next" to="step3" validate="true"/>
            <on-exit>
                <evaluate expression="registerController.step2"/>
            </on-exit>
        </view-state>
    
        <view-state id="step3" view="register-step3" model="registerCommand">
            <transition on="next" to="step4" validate="true"/>
            <on-exit>
                <evaluate expression="registerController.step3"/>
            </on-exit>
        </view-state>
    
        <end-state id="step4" view="register-step4"/>
    
        <action-state id="mail">
            <evaluate expression="registerController.setupForm"/>
            <transition on="success" to="step2"/>
            <transition on="failure" to="mail-error"/>
        </action-state>
    
        <end-state id="mail-error" view="mail-error"/>
    </flow>
    and the configuration of Webflow :

    Code:
      <!-- Executes flows: the entry point into the Spring Web Flow system -->
        <webflow:flow-executor id="flowExecutor">
            <webflow:flow-execution-listeners>
                <webflow:listener ref="hibernateFlowExecutionListener"/>
            </webflow:flow-execution-listeners>
        </webflow:flow-executor>
    
        <!-- The registry of executable flow definitions -->
        <webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" >
            <webflow:flow-location path="/WEB-INF/flows/register.xml"/>
        </webflow:flow-registry>
    
        <!-- Plugs in a custom creator for Web Flow views -->
        <webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator" conversion-service="conversionService" development="true"/>
    
        <!-- Configures Web Flow to use Tiles to create views for rendering; Tiles allows for applying consistent layouts to your views -->
        <bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
            <property name="viewResolvers" ref="viewResolver"/>
        </bean>
    
        <!-- Installs a listener that manages Hibernate persistence contexts for flows that require them -->
        <bean id="hibernateFlowExecutionListener" class="org.springframework.webflow.persistence.HibernateFlowExecutionListener">
            <constructor-arg ref="sessionFactory"/>
            <constructor-arg ref="transactionManager"/>
        </bean>
    
        <!--<bean id="registerCommand" class="mypackage.web.command.RegisterCommand" scope="session"/>-->
    </beans>
    Code:
    public class PropertyEditors implements PropertyEditorRegistrar {
        @Resource
        private PortalService portalService;
    
        public void registerCustomEditors(PropertyEditorRegistry registry) {                
            registry.registerCustomEditor(String.class, new StringTrimmerEditor(true));
            registry.registerCustomEditor(Civility.class, new CivilityBinder(portalService));
        }
    }
    RegisterController
    Code:
    @SuppressWarnings({"unchecked"})
    @Controller("registerController")
    public class RegisterController extends FormAction {
        @Resource
        private PortalService portalService;
    
        @Override
        public String getFormObjectName() {
            return "registerCommand";
        }
    
        @Override
        protected Object createFormObject(final RequestContext context) throws Exception {
            return new RegisterCommand();
        }
    
        @Override
        protected void registerPropertyEditors(final PropertyEditorRegistry registry) {
            registry.registerCustomEditor(String.class, new StringTrimmerEditor(true));
            registry.registerCustomEditor(Civility.class, new CivilityBinder(portalService));
        }
    
        public void step1(final RequestContext context) throws Exception {
    	RegisterCommand cmd = (RegisterCommand) getFormObject(context);
        }
        public void step2(final RequestContext context) throws Exception {        
    	RegisterCommand cmd = (RegisterCommand) getFormObject(context);
            cmd.getPerson().getWebData().setStep(3);
            cmd.setPerson(portalService.mergePerson(cmd.getPerson())); ...
        } 
    }
    What am I doing wrong ? Do you see another way to get through ?
    How would you manage the bind ? At every step ? Only once in the setup ? ThX

  • #2
    AFAIK, Spring web flow does not use PropertyEditor for binding at all.

    See the documentation chapter 4.7, conversion:

    http://static.springsource.org/sprin...reference.html

    Comment

    Working...
    X