Announcement Announcement Module
Collapse
No announcement yet.
Either the documentation is wrong, or I'm missing something... Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Either the documentation is wrong, or I'm missing something...

    In 3.3.1.2. Constructor Injection, it says (last para)

    Finally, ... when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being passed (via one of the DI flavors) to the dependent bean. ... you can read 'totally configure' to mean that the bean will be instantiated (if not a pre-instantiated singleton), all of its dependencies will be set, and the relevant lifecycle methods (such as a configured init method or the IntializingBean callback method) will all be invoked.

    But, a simple test seens to show that isn't actually true. Given the following config:

    <bean id="A" class="Bean" init-method="init">
    <property name="other" ref="B"/>
    </bean>


    <bean id="B" class="Bean" init-method="init">
    <constructor-arg>
    <ref bean="A"/>
    </constructor-arg>
    </bean>

    And the java class for Bean:

    public class Bean
    {
    Bean other;
    boolean initialized = false;

    public Bean()
    {}

    public Bean(Bean other)
    {
    if( !other.initialized )
    throw new RuntimeException("Not Initialized!");
    }

    public Bean getOther()
    {
    return this.other;
    }

    public void setOther(Bean other)
    {
    this.other = other;
    }

    public void init()
    {
    this.initialized = true;
    }
    }

    The context startup fails, with the constructor throwing an exception because the passed bean is NOT "totally configured" because init hasn't been called...

  • #2
    Hmm Bug

    An earlier thread says
    Is it guaranteed that when the Spring container calls the property setters or the constructor, then the objects passed in as arguments are already initialized? For example, if I have setFoo(Bar foo), then can setFoo be sure that foo is an initialized object, i.e. its afterPropertiesSet or custom init-method was already called? (The documentation only says that "the dependency is properly initialized before the dependent bean".)
    To which the reply was

    I can absolutely, 100% satisfaction guaranteed, indubitably confirm that the answer to your question is in the affirmative.
    So - I think it's a bug.

    Comment


    • #3
      Originally posted by Plastics View Post
      In 3.3.1.2. Constructor Injection, it says (last para)

      Finally, ... when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being passed (via one of the DI flavors) to the dependent bean. ... you can read 'totally configure' to mean that the bean will be instantiated (if not a pre-instantiated singleton), all of its dependencies will be set, and the relevant lifecycle methods (such as a configured init method or the IntializingBean callback method) will all be invoked.

      But, a simple test seens to show that isn't actually true. Given the following config:

      <bean id="A" class="Bean" init-method="init">
      <property name="other" ref="B"/>
      </bean>


      <bean id="B" class="Bean" init-method="init">
      <constructor-arg>
      <ref bean="A"/>
      </constructor-arg>
      </bean>

      And the java class for Bean:

      public class Bean
      {
      Bean other;
      boolean initialized = false;

      public Bean()
      {}

      public Bean(Bean other)
      {
      if( !other.initialized )
      throw new RuntimeException("Not Initialized!");
      }

      public Bean getOther()
      {
      return this.other;
      }

      public void setOther(Bean other)
      {
      this.other = other;
      }

      public void init()
      {
      this.initialized = true;
      }
      }

      The context startup fails, with the constructor throwing an exception because the passed bean is NOT "totally configured" because init hasn't been called...
      It's not a bug, your configuration contains a cyclic dependency which Spring tries to resolve by injecting B. So B is created before the property injection in A is completed. Hence the init method has not yet been called when A is injected into the B constructor.

      Are you sure you need this cyclic dependency?

      Comment


      • #4
        Originally posted by devijvers View Post
        It's not a bug, your configuration contains a cyclic dependency which Spring tries to resolve by injecting B. So B is created before the property injection in A is completed. Hence the init method has not yet been called when A is injected into the B constructor.

        Are you sure you need this cyclic dependency?
        I guess it is anyway a bug - instead of such "semi-resolution" of cycling dependency it is much safer to throw exception, and Spring (IMHO) shall do so.

        Regards,
        Oleksandr

        Comment


        • #5
          Originally posted by al0 View Post
          I guess it is anyway a bug - instead of such "semi-resolution" of cycling dependency it is much safer to throw exception, and Spring (IMHO) shall do so.
          It's not a bug in as much as it's intended behavior. Spring used to be throw exceptions in case of cyclic dependencies. This behavior has been reversed since it was deemed too strict.

          Dealing with cyclic dependencies from the point of view of Spring is walking a fine line. The current version of Spring don't throw exceptions anymore. Both approaches have their advantages and disadvantages.

          Comment


          • #6
            It rather walking on a thin ice. At least warning message shall be logged (have not checked if it is logged now).

            Comment

            Working...
            X