Announcement Announcement Module
Collapse
No announcement yet.
How To create my own PropertyEditor Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How To create my own PropertyEditor

    Hi again,

    I'm still trying out all the features of the Spring Core and there is something I just failed to understand.

    If i get it right with PropertyEditor I can do this :

    <bean id="myBean" class="MyBean">
    <property name="UserInfo"><value>belaran/mypassword/admin</value></property>
    </bean>
    With these classes :
    Code:
    public class UserInfo &#123;
    
    	private String login;
    	private String password;
    	private String status;
    ...&#125;
    and
    Code:
    public class MyBean &#123;
    	public MyBean&#40;UserInfo usr&#41;&#123;...&#125;
    ...&#125;

    Now all i have to do is write a class that will translate login/password/status into an objet,
    but how i do so ? Wich interface do i have to implements... ?

    <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.Cu stomEditorConfigurer">
    <property name="customEditors">
    <map>
    <entry key="UserInfo">
    <bean class="MyBeanEditor">
    <!-- what do I put there ? -->
    </bean>
    </entry>
    </map>
    </property>
    </bean>

  • #2
    Hiya

    You want to extend the java.beans.PropertyEditorSupport class (this is not provided by Spring but comes as a part of the standard Java APIs).

    If you need some examples of such custom java.beans.PropertyEditorSupport implementations, you can look at the classes in the org.springframework.beans.propertyeditors package of the Spring.Java source. The CustomDateEditor should give you a head start.

    Once you have coded such a class (called perhaps UserInfoEditor in say, the com.reallygoodbooks.propertyeditors package), you can register it with a Spring ApplicationContext like so...

    Code:
    <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
       <property name="customEditors">
         <map>
           <entry key="com.reallygoodbooks.domain.UserInfo">
             <bean id="myEditor" class="com.reallygoodbooks.propertyeditors.UserInfoEditor">
             </bean>
           </entry>
         </map>
       </property>
    </bean>
    The CustomEditorConfigurer class will be automagically 'picked up' by an ApplicationContext (this is not the case if you are using a plain vanilla BeanFactory though).

    Ciao
    .NET Guy

    Comment


    • #3
      Okay, so i should have something like :


      Code:
      public class UserInfoEditor extends PropertyEditorSupport
      &#123;
      	private String userInfoStr;
      
      	public UserInfoEditor&#40;String value&#41; 	// in your case value ="belaran/psswd/status"
      	public UserInfo setAsUserInfo&#40;&#41;
      	&#123;
      		// here we cut the string value into piece and fill UserInfo with it...
      	&#125;
      &#125;
      But how Spring will know it has to call setAsUserInfo() to translate "belaran/psswd/admin" to an UserInfo ?

      Or am I missing something else here ?

      Comment


      • #4
        Hiya

        Almost there... you need to override the existing methods of the PropertyEditorSupport class (namely setAsText()).

        Code:
        package com.reallygoodbooks.propertyeditors;
        
        import ...
        
        public final class UserInfoEditor extends PropertyEditorSupport &#123;
        
        	public void setAsText&#40;String text&#41; throws IllegalArgumentException &#123;
        		// text contains the value "belaran/psswd/status"
        		
        		// do some checking on the text &#40;for null, stuff like that&#41;...
        		
        		// split the text value into an array of strings on the '/' character...
        		string&#91;&#93; bits = ...
        		// do some checking on the bits &#40;must be length = 3, etc&#41;...
        
        		// populate a new UserInfo instance using the bits...
        		UserInfo user = new UserInfo&#40;&#41;;
        		user.setLogin&#40;bits&#91;0&#93;&#41;;
        		user.setPassword&#40;bits&#91;1&#93;&#41;;
        		user.setStatus&#40;bits&#91;2&#93;&#41;;
        		
        		setValue&#40;user&#41;;
        	&#125;
        &#125;
        Mmm, this guide really does blow chunks, but I can't find anything else on the web :shock: . I'm not a Java programmer, but I think this class will do the splitting of the text string for you... StringTokenizer. FInally, apologies if am am doing that whole grandmother and eggs thing

        Ciao
        .NET Guy

        Comment


        • #5
          Ok ! Thanks a lot !

          In fact i was looking somehting like
          Code:
          public Object TranslateMethod&#40;String str&#41;;
          but it's, in fact :

          Code:
          public void setAsText&#40;String flatObject&#41;;
          public void setValue&#40;Object obj&#41;;
          ...
          Now i get it ... thanks a lot !

          Comment


          • #6
            Hiya

            No worries man... Bruce Springsteen was born to rock and roll; I was born to serve. Merry Christmas.

            Ciao
            .NET Guy

            Comment


            • #7
              Hi again,

              it seems that i have a last pb :

              I don't understand what arguments I have to pass to the 'registerCustomEditor'... I know the AppContext will do all for me , but i really want to test Spring core alone...

              The register await for a class and a property editor should i do this :

              Code:
              MyBeanFacto.registerCustomEditor&#40;DAOpropertyEditor.class, new DAOpropertyEditor&#40;&#41;&#41;;

              Comment


              • #8
                Hiya

                Your code needs to pass the class that needs to be cnvrted as the first argument (and not the class that is going to do the conversion)... whenever the factory needs to convert a string value into an instance of the DAO class, it will use the DAOpropertyEditor instance that you have registered.

                To wit... (amended post to include this snippet)

                Code:
                MyBeanFacto.registerCustomEditor&#40;DAO.class, new DAOpropertyEditor&#40;&#41;&#41;;
                You can use the following unit test from the source as a reference...

                Code:
                public void testCustomEditor&#40;&#41; &#123;
                	DefaultListableBeanFactory lbf = new DefaultListableBeanFactory&#40;&#41;;
                	NumberFormat nf = NumberFormat.getInstance&#40;Locale.UK&#41;;
                	lbf.registerCustomEditor&#40;Float.class, new CustomNumberEditor&#40;Float.class, nf, true&#41;&#41;;
                	MutablePropertyValues pvs = new MutablePropertyValues&#40;&#41;;
                	pvs.addPropertyValue&#40;"myFloat", "1.1"&#41;;
                	lbf.registerBeanDefinition&#40;"testBean", new RootBeanDefinition&#40;TestBean.class, pvs&#41;&#41;;
                	TestBean testBean = &#40;TestBean&#41; lbf.getBean&#40;"testBean"&#41;;
                	//System.out.println&#40;testBean.getMyFloat&#40;&#41;.floatValue&#40;&#41;&#41;;
                	assertTrue&#40;testBean.getMyFloat&#40;&#41;.floatValue&#40;&#41; == 1.1f&#41;;
                &#125;
                Ciao
                .NET Guy

                Comment


                • #9
                  Code:
                  lbf.registerCustomEditor&#40;Float.class, new CustomNumberEditor&#40;Float.class, nf, true&#41;&#41;;
                  Okay, so if i create an editor for Bob, named BobEditor, i'll pass Bob.class and an new BobEditor()...

                  But in my case i got a problem : My editor translate a String into BobImpl object, but the the bean that needs this translatation for a property await ... IBob, interface implemented by BobImpl... ?

                  Here's my config.xml.
                  Code:
                  <beans>
                  	<bean id="DataSource" class="com.AO.DAO.DAOImpl" autowire="byType" init-method="connect">
                  			<lookup-method name="createResource" bean="File" />
                  			<property name="options"><value>jdbc&#58;url/bob/mike</value></property>
                  	</bean>
                  	<!-- Property "options" is an OptionsDAOImpl -->
                  	<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
                  	   <property name="customEditors">
                  		 <map>
                  		   <entry key="com.AO.DAO.OptionsDAOImpl">
                  			 <bean id="DAOpropertyEditor" class="com.AO.DAO.DAOpropertyEditor">
                  			 </bean>
                  		   </entry>
                  		 </map>
                  	   </property>
                  	</bean>
                  	
                  	<bean id="DAOoptions" class="com.AO.DAO.OptionsDAOImpl">
                  		<property name="url"><value>jdbc&#58;//localhost/SpringCoreDemodb</value></property>
                  		<property name="login"><value>root</value></property>
                  		<property name="password"><value>mike</value></property>
                  	</bean>
                  	...
                  </beans>
                  What i'm trying to do is translate from the string from the DAO Bean "jdbc:url/bob/mike" into an OptionsDAOImpl... See ?

                  Comment


                  • #10
                    Hiya

                    You should be okay... Spring will just 'do the right thing'.

                    I just wrote this test and added it to the Spring source; the classes are of course different to your own, but they exhibit the same mix of interfaces and classes, so I'm hoping this will see you right.

                    Code:
                    public void testCustomEditorWithInterfaceType&#40;&#41; &#123;
                    	DefaultListableBeanFactory lbf = new DefaultListableBeanFactory&#40;&#41;;
                    	lbf.registerCustomEditor&#40;ITestBean.class, new AbstractBeanFactoryTests.TestBeanEditor&#40;&#41;&#41;;
                    	MutablePropertyValues pvs = new MutablePropertyValues&#40;&#41;;
                    	pvs.addPropertyValue&#40;"spouse", "jenny_23"&#41;;
                    	lbf.registerBeanDefinition&#40;"testBean", new RootBeanDefinition&#40;TestBean.class, pvs&#41;&#41;;
                    	ITestBean testBean = &#40;TestBean&#41; lbf.getBean&#40;"testBean"&#41;;
                    	System.out.println&#40;testBean.getSpouse&#40;&#41;&#41;;
                    &#125;
                    The TestBean class (heavily compressed) looks like this...

                    Code:
                    public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOther, Comparable &#123;
                    	private String name;
                    	private int age;
                    	private ITestBean spouse;
                    
                    	// with appropriate getters and setters for the above fields...
                    &#125;
                    As you can see from the TestBean class definition, it exposes a property of type ITestBean... in the unit test though, we actually set this property to the value of the TestBean class (which implements the ITestBean interface). The property editor that converts the string value 'jenny_23' to a TestBean instance is actually registered using the ITestBean interface class.

                    So in your case, you will be able to do the following...

                    Code:
                    <bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
                      <property name="customEditors">
                       <map>
                    	 <entry key="com.AO.DAO.OptionsDAO">
                    	  <bean id="DAOpropertyEditor" class="com.AO.DAO.DAOpropertyEditor">
                    	  </bean>
                    	 </entry>
                       </map>
                      </property>
                    </bean>
                    So in your case, you have a classes that look (roughly) like the stubs below, in which case your current configuration will work just fine... if it ain't clear, you can just hit 'Post Reply'

                    Code:
                    public interface OptionsDao &#123;
                    	// setters and getters for the url, name and password...
                    &#125;
                    
                    public class OptionsDaoImpl implements OptionsDao &#123;
                        // setters and getters for the url, name and password...
                    &#125;
                    
                    public class DAOImpl &#123;
                    	private OptionsDaoImpl _options;
                    	
                    	public void setOptions&#40;OptionsDaoImpl options&#41; &#123;
                    		_options = options;
                    	&#125;
                    	
                    	public OptionsDaoImpl getOptions&#40;&#41; &#123;
                    		return _options;
                    	&#125;
                    &#125;
                    
                    public class DAOpropertyEditor extends PropertyEditorSupport &#123;
                        public void setAsText&#40;string text&#41; &#123;
                    		OptionsDaoImpl option = new OptionsDaoImpl&#40;&#41;;
                    		// do conversion...
                    		setValue&#40;option&#41;;
                        &#125;
                    &#125;
                    Ciao
                    .NET Guy

                    Comment


                    • #11
                      Perfect !


                      Now it's working just fine !

                      Thanks a lot !

                      Comment

                      Working...
                      X