Announcement Announcement Module
Collapse
No announcement yet.
Creation of Beans and recognition of problems Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Creation of Beans and recognition of problems

    Hello,

    Ive maybe got a stupid question, but it would be great if someone could answer. In the spring reference documention I read this:

    The Spring container validates the configuration of each bean as the container is created, including the validation of whether bean reference properties refer to valid beans. It detects configuration problems, such as references to non-existent beans and circular dependencies, at container load-time.
    and also this:
    Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container which has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies. For example, the bean throws an exception as a result of a missing or invalid property.
    Now I somehow wonder: If Spring detects configuration problems and invalid beans at container load-time, why would it later generate an exception? How can there be missing or invalid propertys if Spring checks them at load-time? I mean, the xml configuration wont change while the project is running. It would be nice if someone could give me an explanation or/and a concrete example. Thank you very much :-)

  • #2
    There is a difference (subtle but there is one). At load time it simply checks if all beans referenced are available...

    Code:
    <bean id="b1" class="SomeBean" />
    <bean id="b2" class="SomeBean">
      <property name="foo" ref="b3" />
    </bean>
    The code above would blow up at load time because bean named b3 is not there. Now if b3 would be there but the property foo is not accesible (because there is no setFoo on the class SomeBean) it would blow up at the moment the bean is constructed, which is happening wheb BeanFactory.getBean is called.

    Comment


    • #3
      ah - thank you, I guess I understand the difference...

      but, just that I understand correctly:
      - at container load-time, the beans are checked ( => are they configured correctly?)
      - the exceptions, for example when a property is not accesible, are thrown, when the bean is actually created

      you said, this happens when BeanFactory.getBean is called. But I also read this

      By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the configuration or surrounding environment are discovered immediately, as opposed to hours or even days later. When this behavior is not desirable, you can prevent pre-instantiation of a singleton bean by marking the bean definition as lazy-initialized. A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup.
      so I thought beans which shall not be lazy-instantiated are created when the container starts up. so, looking at your example, the exception for the property foo must be thrown when the container starts up, musnt it?
      Last edited by jeeper; May 10th, 2011, 05:14 AM.

      Comment


      • #4
        Ive got one additional question: what about @Required?

        I read this:
        This annotation simply indicates that the affected bean property must be populated at configuration time, through an explicit property value in a bean definition or through autowiring. The container throws an exception if the affected bean property has not been populated;
        I thought this means, if the property which setter-method is annotated with @Required, is not set at container load-time, an exception is thrown. I wrote a simple test:

        Code:
        import org.springframework.beans.factory.annotation.Required;
        
        public class ReqTest {
        
            private String s;
        
            public String getS() {
                return s;
            }
        
            @Required
            public void setS(String s) {
                this.s = s;
            }
        }
        Code:
            <bean id="reqtest" class="ReqTest">
              <!--  <property name="s" value="AString"/> -->
            </bean>
        Code:
        import org.springframework.beans.factory.BeanFactory;
        import org.springframework.context.*;
        import org.springframework.context.support.*;
        
        public class Start {
        
        	public static void main(String[] args) {
        
        		ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"startconfig.xml"});
        		BeanFactory factory = context;
        		
                        ReqTest r = (ReqTest) factory.getBean("reqtest");
                        System.out.println(r.getS());
        	}
        
        }
        well, the output is:

        Code:
        run:
        10.05.2011 11:58:42 org.springframework.context.support.AbstractApplicationContext prepareRefresh
        INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@437f1ba3: startup date [Tue May 10 11:58:42 CEST 2011]; root of context hierarchy
        10.05.2011 11:58:42 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
        INFO: Loading XML bean definitions from class path resource [startconfig.xml]
        10.05.2011 11:58:42 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
        INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1f8b81e3: defining beans [reqtest]; root of factory hierarchy
        null
        BUILD SUCCESSFUL (total time: 0 seconds)
        it returns null, because the property is not set, but I can not see any exception at all? what did I do wrong and when should the exception be thrown?

        thank you!

        Comment


        • #5
          I suggest a read of the reference guide. Simply slapping a @Required in there is going to do exactly nothing... You well need to register a BeanPostProcessor which checks this property and if it has been called, next to that it is called/check at configuration/creation and not loading! So if you would have made the bean lazy and not getting it from the context the exception would not be thrown...

          Comment


          • #6
            stupid me, I simply forgot the BeanPostProcessor. Sorry! I think I might reread the documentation again, since there seem to be differences when the beans are actually created, depending on the kind of application (web application or not) I use. But I guess, in web applications, the beans are created during the container load-time and in other applications, they are created when they are actually requested by BeanFactory.getBean. I hope, this is correct now. Sorry, it is confusing me a little bit!

            Comment


            • #7
              Hello,

              again one question to your example above. I tried to reproduce what you said and to test it. I used a simple application for it.
              Here is what you said:
              Default

              There is a difference (subtle but there is one). At load time it simply checks if all beans referenced are available...

              Code:

              <bean id="b1" class="SomeBean" />
              <bean id="b2" class="SomeBean">
              <property name="foo" ref="b3" />
              </bean>

              The code above would blow up at load time because bean named b3 is not there. Now if b3 would be there but the property foo is not accesible (because there is no setFoo on the class SomeBean) it would blow up at the moment the bean is constructed, which is happening wheb BeanFactory.getBean is called.
              Code:
              public class Start {
              
              	public static void main(String[] args) {
              
              		ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"startconfig.xml"});
              		BeanFactory factory = context;
              	}
              
              }
              I only created the container, but I didnt call a bean with factory.getBean. According to what you said, when I run the application, there would be a error when I had a reference to a bean which doesnt exist. This is correct.
              Further on you said, that a error like a non existing setter-Method would throw an exception when someone would try to access the bean. (factory.getBean) this didnt happen. the error was also thrown as I ran the project.
              I used a really simple bean with just one variable and setter-getter for testing this.

              Code:
              <bean id="bean" class="Bean">
                      <property name="abc" ref="existingBean"/>
                  </bean>
              class Bean did not have a setter for abc. did I misunderstand something?

              According to this (see below) beans with scope singleton which are set to be pre-instantiated (default) are created when the container is created.
              The Spring container validates the configuration of each bean as the container is created, including the validation of whether bean reference properties refer to valid beans. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Scopes are defined in Section 3.5, “Bean scopes” Otherwise, the bean is created only when it is requested.
              so maybe I misunderstood your example? the error-message is thrown when the bean is created, correct - but its not only happening when BeanFactory.getBean is called but (when the properties mentioned above are set) when the container is created
              Last edited by jeeper; May 24th, 2011, 07:00 AM.

              Comment


              • #8
                For starters I was talking about a BeanFactory not an ApplicationContext. But that aside I was wrong, when I use an XmlBeanFactory nothing happens, that is because the singletons aren't instantiated and the BeanDefinitions aren't validated (which is what is happening inside an ApplicationContext next to other things). So I was a slightly off here, I was expecting BeanDefinition validation for references at least... Well learned something here ....

                Comment


                • #9
                  ok :-)

                  thank you for answering!

                  Comment

                  Working...
                  X