Announcement Announcement Module
Collapse
No announcement yet.
How to extend spring-beans XML-Context Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to extend spring-beans XML-Context

    Hello,

    I would like to add and remove elements from the standard spring-beans and publish a proprietary xsd for my project.

    I currently use standard XML-Context-Files to create and wire beans that are used in an instrument control system.

    The following simple context wires three motors with a graphical user interface that automatically provides widgets for visualization and control of the motors.

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans        
           http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
           default-init-method="initComponent"
           default-destroy-method="shutdownComponent">
        
        <bean id="motorX" class="org.openinspire.tutorial.sampleMotor.SampleMotor">
            <property name="name" value="X-Axis" />
            <property name="minimum" value="-200.0" />
            <property name="maximum" value="200.0" />
        </bean>
        
        <bean id="motorY" class="org.openinspire.tutorial.sampleMotor.SampleMotor">
            <property name="name" value="Y-Axis" />
            <property name="minimum" value="-200.0" />
            <property name="maximum" value="200.0" />
        </bean>
        
        <bean id="motorZ" class="org.openinspire.tutorial.sampleMotor.SampleMotor">
            <property name="name" value="Z-Axis" />
            <property name="minimum" value="-200.0" />
            <property name="maximum" value="200.0" />
        </bean>
        
        <bean id="gui" class="inspire.ui.managementGUI.ManagementGUI">
            <property name="components">
                <list>
                    <ref local="motorX" />
                    <ref local="motorY" />
                    <ref local="motorZ" />
                </list>    
            </property>
        </bean>
        
    </beans>
    Users are able to build their experiment configuration from prebuilt modules and share them. The problem of the standard context is that it has many options that I do not want to provide to the users and that some parts would be more intuitive.

    The following context shows how I would like to build the context:
    Code:
    <beans default-init-method="initComponent"
           default-destroy-method="shutdownComponent">
        
        <bean id="motorX" oim="org-openinspire-oim-demo-demomotor" version="0.1">
            <property name="name" value="X-Axis" />
            <property name="minimum" value="-200.0" />
            <property name="maximum" value="200.0" />
        </bean>
        
        <bean id="motorY" oim="org-openinspire-oim-demo-demomotor" version="0.1">
            <property name="name" value="Y-Axis" />
            <property name="minimum" value="-200.0" />
            <property name="maximum" value="200.0" />
        </bean>
        
        <bean id="motorZ" oim="org-openinspire-oim-demo-demomotor" version="0.1">
            <property name="name" value="Z-Axis" />
            <property name="minimum" value="-200.0" />
            <property name="maximum" value="200.0" />
        </bean>
        
        <bean id="gui" oim="org-openinspire-oim-debug-widgettestcenter" version="0.63">
            <property name="components">
                <list>
                    <ref local="motorX" />
                    <ref local="motorY" />
                    <ref local="motorZ" />
                </list>    
            </property>
        </bean>
        
    </beans>
    I do not want to provide the class but the name of the module via oim-attribute. The modules still exist and contain meta information as the class that should be instantiated. All missing modules with the specified version will be downloaded automatically, when missing.

    Additionally I need further checks for properties.


    Until now I was unable to find the right point where I can start implementing this. I started to reproduce it while analyzing the sources in org.springframework.context and implemented an AbstractInspireApplicationContext.

    I look forward to all hints you can give me, solving the problem.

    Thank you, Prato

  • #2
    Perhaps it might be easier to solve this via an own namespace.

    That way you can provide predefined tags which do not allow unwanted configurations.

    Regards,
    Andreas

    Comment


    • #3
      Thank you for your fast response. This sound really promising. I just printed the document and will try to implement it in this way.

      Regards, Stefan

      Comment


      • #4
        I read the Appendix A and B and tried to implement it in this way but I currently have trouble with a few things that are not described in the manual.

        I would like to use the standard <bean> element and replace the class attribute by a mod attribute that is a unique name of a module and a version.

        How is it possible to integrate a required attribute mod as described in B.7.2, parse it and set the correct class property of the bean?
        Code:
        <bean id="Test" mod="org.openinspire.oim.Module1">
        ...
        </bean>
        This will lookup the correct class of Module1 by property-file and should now set the class attribute internally.

        I tried to find the place where all the standard elements are parsed.
        It seems to be the BeanDefinitionParserDelegate and the class attribute is set by CLASS_ATTRIBUTE but I do not really understand where I can enter my few lines that will translate the mod attribute and version value to the internal class value.

        Where is the place where the classloader will load the specific class that is normally given with the class attribute.

        Internally I will call something like this to get the corresponding class that should be created by the module:

        Code:
        Class modClass = moduleMap.getClass(String moduleName, String version);
        modClass.loadClass();
        I look forward to an idea.

        Regards, Prato

        Comment


        • #5
          I'm not sure about replacing these core elements.
          May I alternatively suggest to create your own tags that internally use the standard beans?

          E.g.
          Code:
            <mod:element id="Test" module="org.openinspire.oim.Module1"/>
          That could internally create "normal" beans, but would provide a layer of abstraction for the configuration itself.

          Regards,
          Andreas

          Comment


          • #6
            I tried this. I created such an element as in B.6. but I'm unsure how to allow all elements like <property> that are allowed for standard beans.
            When I follow the B.6. example the tag may not nest elements.

            When I try to realize like in B.7. it is only written how to nest custom elements and use it by a factory.

            What I really need is to load a class with my custom ClassLoader and having a way to inject properties as in normal <bean>-Elements. I think redefining everything again is not really the clean way to do this.

            Regards, Prato

            Comment


            • #7
              Originally posted by Prato View Post
              IWhere is the place where the classloader will load the specific class that is normally given with the class attribute.
              I _guess_ a good starting point might be AbstractBeanDefinition#resolveBeanClass() invoked by AbstractFactory#resolveBeanClass().

              The classloader is configured in AbstractBeanFactory.

              Hope that helps a bit.

              Regards,
              Andreas

              Comment


              • #8
                Hello,

                I tried to understand the internal Bean Definition during the last weeks and read several sources but I have to admit that I do not really understand or find the way how collections are handled that I pass to a property.

                I defined my own BeanDefinitionParser by extending the AbstractSingleBeanDefinitionParser and implemented getBeanClass() and doParse().

                I now get my properties list by
                NodeList propertyNodeList = element.getElementsByTagName("property"); and look if a value or ref attribute is given.

                Depending on the attribute I use bean.addPropertyReference(...) or bean.addPropertyValue(...) .

                Now i can inject a value or a property but I want to be able to use all other types as collections (Set,List, Map) that I can give to a normal spring bean property.

                For example:

                Code:
                <oi:mod id="test" oim="org.openinspire.tst" version="1.0">
                        <property name="sampleIntValue" value="27"/>
                        <property name="testMod" ref="tempA"/>
                        <property name="testList">
                            <list>
                                <value>A</value>
                                <value>B</value>
                                <value>C</value>
                                <value>D</value>
                            </list>    
                        </property>
                 </oi:mod>
                Do you have an advice? I currently run into trouble with my project because I search for a solutions since several months.
                If you have a simpler way for me how to replace class by my oim and version tag this would be welcome, too.


                Thank you for your help,
                Prato

                Comment


                • #9
                  I haven't had a deeper look inside that part of the implementation myself. However, you might have a look at UtilNamespaceHandler. There are inner classes (derived from AbstractSingleBeanDefinitionParser) for handling lists sets and maps.

                  Hope that helps,
                  Andreas

                  Comment

                  Working...
                  X