Announcement Announcement Module
Collapse
No announcement yet.
bean reinstanciation upon request Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • bean reinstanciation upon request

    Am I correct to assume that using scope prototype will only create a new instance of the bean when fetching it with getBean()?

    I have a bean that is depended on a bean which is depended on another bean.
    Like this.
    Code:
    <bean id="bean1"...>
      <property name="bean2" ref="bean2"/>
    </bean>
    
    <bean id="bean2"...>
      <property name="bean3" ref="bean3"/>
    </bean>
    
    <bean id="bean3".../>
    bean 3 maintains a list which is different on each datasource I use. I need to have bean2 to update this value(a new instance of bean3) when I switch datasource with AbstractRoutingDataSource.

    I have tried scope="prototype", but it did not work. I assume it is because of what I stated above.

    I have two versions of my application. One with Spring MVC and one withouth(The one with was an experimentation of MVC). The one withouth MVC is getting the Servicebeans with applicationContext.getBean("bean1"). I guess I could try scope="request" in the MVC version of my application, but then the XML editor in eclipse is complaining about "the content of element type bean must match ..." when I add <aop:scoped-proxy/>

  • #2
    Originally posted by DJViking View Post
    Am I correct to assume that using scope prototype will only create a new instance of the bean when fetching it with getBean()? ...
    More or less.

    If you have bean1 and bean2 scoped to prototype and bean1 is injected in the bean2 as property, then each time as you fetch bean2 it would refer to the new copy of bean1 (while bean1 was not directly fetched by your code).

    Regards,
    Oleksandr

    Comment


    • #3
      Originally posted by al0 View Post
      More or less.

      If you have bean1 and bean2 scoped to prototype and bean1 is injected in the bean2 as property, then each time as you fetch bean2 it would refer to the new copy of bean1 (while bean1 was not directly fetched by your code).

      Regards,
      Oleksandr
      I have tried having scope protoype on bean1,bean2 and bean3, but still no effect on new instance of bean3 when I getBean("bean1").

      I wonder if I am doing something wrong. I am now using scope="prototype" in bean. Spring version is 2.0.5. I call getBean("bean1") two times and compare them and they are equal! That tells me that prototype scoping does not work.
      ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext .xml");
      Bean1 b1 = applicationContext.getBean("bean1");
      Bean1 b2 = applicationContext.getBean("bean1");
      System.out.println((b1 == b2)); gives true
      Last edited by DJViking; Jul 25th, 2007, 08:38 AM.

      Comment


      • #4
        Originally posted by DJViking View Post
        I have tried having scope protoype on bean1,bean2 and bean3, but still no effect on new instance of bean3 when I getBean("bean1").

        Sound weird. I use this quite regularly w/o troubles.

        How you have proved that it was not new instance?
        Have you tried something like this
        Code:
        System.out.println(System.identityHashCode(this);
        in the constructor of bean3

        Code:
        System.out.println(System.identityHashCode(bean3);
        in the setBean3() setter of bean1?

        Regards,
        Oleksandr

        Comment


        • #5
          Originally posted by al0 View Post
          Sound weird. I use this quite regularly w/o troubles.

          How you have proved that it was not new instance?
          Have you tried something like this
          Code:
          System.out.println(System.identityHashCode(this);
          in the constructor of bean3

          Code:
          System.out.println(System.identityHashCode(bean3);
          in the setBean3() setter of bean1?

          Regards,
          Oleksandr
          I don't have access to the code for bean1, bean2 and bean3 as they come from an external API I include in my application. I merly use them in my application when defined in the application context.

          System.identityHashCode gives my two equal values for two getBean with scope="prototype"

          Comment


          • #6
            Originally posted by DJViking View Post
            I don't have access to the code for bean1, bean2 and bean3 as they come from an external API I include in my application. I merly use them in my application when defined in the application context.

            System.identityHashCode gives my two equal values for two getBean with scope="prototype"

            That you have no access to source code of the bean1, bean2, bean3 does nothing, as you always can create a test case that uses your oun beans.

            Concerning your second statement - do I undestand properly that in the
            following code fragment
            Code:
            Object o1= ac.getBean("bean1");
            System.out.println(Ste.identityHashCode(o1);
            Object o2= ac.getBean("bean1");
            System.out.println(Ste.identityHashCode(o2);
            both println() statements produces the same output while bean1 has prototype scope?
            Sorry, but I do not believe it. Can you post your code snippet, output and configuration?

            Regards,
            Oleksandr

            Comment


            • #7
              Originally posted by al0 View Post
              That you have no access to source code of the bean1, bean2, bean3 does nothing, as you always can create a test case that uses your oun beans.

              Concerning your second statement - do I undestand properly that in the
              following code fragment
              Code:
              Object o1= ac.getBean("bean1");
              System.out.println(Ste.identityHashCode(o1);
              Object o2= ac.getBean("bean1");
              System.out.println(Ste.identityHashCode(o2);
              both println() statements produces the same output while bean1 has prototype scope?
              Sorry, but I do not believe it. Can you post your code snippet, output and configuration?

              Regards,
              Oleksandr
              Yes both println() gives the same output
              Last edited by DJViking; Jul 25th, 2007, 10:19 AM.

              Comment


              • #8
                Just small but complete test to prove my disbelief

                Main class (A.java)
                Code:
                import org.springframework.beans.*;
                import org.springframework.context.*;
                import org.springframework.context.support.*;
                
                public class A {
                    public static void main(String[] args) {
                        ApplicationContext ac= new ClassPathXmlApplicationContext("myContext.xml");
                        System.out.println("First fetch of B1 ["+ac.getBean("B1")+"]");
                        System.out.println("Second fetch of B1 ["+ac.getBean("B1")+"]");
                    }
                }
                Class for bean1 (B1.java)
                Code:
                public class B1  {
                   Object fBean2;
                   public void setBean2(Object bean2) {
                      fBean2= bean2;
                      System.out.println("Bean2 ["+System.identityHashCode(bean2)+"]");
                   }
                }
                Class for bean2 (B2.java)
                Code:
                public class B2  {
                   Object fBean3;
                   public void setBean3(Object bean3) {
                      fBean3= bean3;
                      System.out.println("Bean3 ["+System.identityHashCode(bean3)+"]");
                   }
                }
                and for bean3 (B3.java)
                Code:
                public class B3  {
                }
                and now context (myContext.xml)
                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.xsd">
                
                    <bean id="B1"  class="B1" scope="prototype">
                        <property name="bean2" ref="B2"/>
                    </bean>
                
                    <bean id="B2"  class="B2" scope="prototype">
                        <property name="bean3" ref="B3"/>
                    </bean>
                
                    <bean id="B3"  class="B3" scope="prototype"/>
                    
                </beans>
                and, just for completness, log4j.properties
                Code:
                log4j.rootLogger=INFO, console
                
                #Console
                log4j.appender.console=org.apache.log4j.ConsoleAppender
                log4j.appender.console.layout=org.apache.log4j.PatternLayout
                log4j.appender.console.layout.ConversionPattern=%d %p [%c] - <%m>%n
                and now output
                Code:
                2007-07-25 15:25:03,453 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@dd5b: display name [org.springframework.context.support.ClassPathXmlApplicationContext@dd5b]; startup date [Wed Jul 25 15:25:03 CEST 2007]; root of context hierarchy>
                2007-07-25 15:25:03,594 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [myContext.xml]>
                2007-07-25 15:25:03,923 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@dd5b]: org.springframework.beans.factory.support.DefaultListableBeanFactory@a37368>
                2007-07-25 15:25:03,954 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@a37368: defining beans [B1,B2,B3]; root of factory hierarchy>
                Bean3 [4116479]
                Bean2 [29987161]
                First fetch of B1 [B1@65a77f]
                Bean3 [30911772]
                Bean2 [10883428]
                Second fetch of B1 [B1@bfc8e0]
                So you see that all bean instances are different. So check your code and configuration once more - somewhere there is error.

                Regards,
                Oleksandr

                Comment


                • #9
                  My code goes something like this.

                  Code:
                  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
                  
                      SomeService someService = (SomeService) applicationContext.getBean("someService");
                      SomeService someService2 = (SomeService) applicationContext.getBean("someService");
                      
                      System.out.println("Equal?: " + (someService == someService2));
                      System.out.println(System.identityHashCode("Bean1 Hash: " + someService));
                      System.out.println(System.identityHashCode("Bean2 Hash: " + someService2));
                  Code:
                        <bean id="someService" class="SomeServiceImpl" scope="prototype">
                              <property name="someUtilities" ref="someUtilities" />
                        </bean>
                  
                        <bean id="someUtilities" class="SomeUtilities" scope="prototype">
                              <property name="someUtilities" ref="someUtilities" />
                        </bean>
                  
                        <bean id="someTypeUtilities" class="SomeTypeUtilities" scope="prototype">
                              <constructor-arg ref="jdbcTemplate" />
                        </bean>
                  And the output is the same for both instances.
                  Last edited by DJViking; Jul 25th, 2007, 10:23 AM.

                  Comment


                  • #10
                    I can't seem to figure it out. Previous successes was an error. It seems that even though SomeService is defined as prototype it is not getting a new instance with getBean
                    Last edited by DJViking; Jul 25th, 2007, 10:14 AM.

                    Comment


                    • #11
                      Originally posted by al0 View Post
                      Just small but complete test to prove my disbelief
                      and now context (myContext.xml)
                      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.xsd">
                      
                          <bean id="B1"  class="B1" scope="prototype">
                              <property name="bean2" ref="B2"/>
                          </bean>
                      
                          <bean id="B2"  class="B2" scope="prototype">
                              <property name="bean3" ref="B3"/>
                          </bean>
                      
                          <bean id="B3"  class="B3" scope="prototype"/>
                          
                      </beans>
                      and, just for completness, log4j.properties
                      My applicationContext.xml has a different signature that yours.

                      <?xml version="1.0" encoding="UTF-8"?>
                      <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

                      Comment


                      • #12
                        Can you try sample that I have posted in the previous mail?
                        If it works as well for you, then check once more your configuration.

                        And concerning final local variable - it has nothing to do with it. I (wild) guess that you do more then one change per try, so it may be not clear which change caused this ot that effect.

                        Regards,

                        Oleksandr

                        Originally posted by DJViking View Post
                        I have discovered my error. Because an earlier version of my program containted a final variable.

                        final SomeService someService;
                        ...
                        someService = applicationContext.getBean("someService");

                        But when I removed the final statement the output was not the same for two getBean instances.

                        I don't completely understand it. Declaring my local variable as final should not give any trouble. Or?

                        Edit: I rejoiced to soon. Problem sill ocour

                        Comment


                        • #13
                          Originally posted by DJViking View Post
                          My applicationContext.xml has a different signature that yours.

                          <?xml version="1.0" encoding="UTF-8"?>
                          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
                          It is highly recommended to switch from DTD-based context to schema-based (look into the Spring reference), but, if for some reasons you can not do it, then some advanced capabilities of the Spring are not availbale, but it has absolutely no impact on discussed behavior.

                          I just changed signature to your here is new output:
                          Code:
                          2007-07-25 16:30:15,916 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@dd5b: display name [org.springframework.context.support.ClassPathXmlApplicationContext@dd5b]; startup date [Wed Jul 25 16:30:15 CEST 2007]; root of context hierarchy>
                          2007-07-25 16:30:16,057 INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - <Loading XML bean definitions from class path resource [myContext.xml]>
                          2007-07-25 16:30:16,277 INFO [org.springframework.context.support.ClassPathXmlApplicationContext] - <Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@dd5b]: org.springframework.beans.factory.support.DefaultListableBeanFactory@337d0f>
                          2007-07-25 16:30:16,308 INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@337d0f: defining beans [B1,B2,B3]; root of factory hierarchy>
                          Bean3 [2544881]
                          Bean2 [23473608]
                          First fetch of B1 [B1@147c5fc]
                          Bean3 [18303751]
                          Bean2 [4115088]
                          Second fetch of B1 [B1@64dc11]
                          As you can see nothing is changed - all bean instances are still different.

                          Regards,
                          Oleksandr

                          Comment


                          • #14
                            I just created a simple example with one class and defined it in application context as prototype. Output was different for each time..


                            However. I can not see any difference from my other application in the definition of my prototype bean.

                            Comment


                            • #15
                              Originally posted by DJViking View Post
                              My code goes something like this.

                              Code:
                              ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
                              
                                  SomeService someService = (SomeService) applicationContext.getBean("someService");
                                  SomeService someService2 = (SomeService) applicationContext.getBean("someService");
                                  
                                  System.out.println("Equal?: " + (someService == someService2));
                                  System.out.println(System.identityHashCode("Bean1 Hash: " + someService));
                                  System.out.println(System.identityHashCode("Bean2 Hash: " + someService2));
                              Red lines are incorrect, they should be
                              Code:
                              System.out.println("Bean1 Hash: " + System.identityHashCode(someService));
                                  System.out.println("Bean2 Hash: " + System.identityHashCode(someService2));
                              Code:
                                    <bean id="someService" class="SomeServiceImpl" scope="prototype">
                                          <property name="someUtilities" ref="someUtilities" />
                                    </bean>
                              
                                    <bean id="someUtilities" class="SomeUtilities" scope="prototype">
                                          <property name="someUtilities" ref="someUtilities" />
                                    </bean>
                              
                                    <bean id="someTypeUtilities" class="SomeTypeUtilities" scope="prototype">
                                          <constructor-arg ref="jdbcTemplate" />
                                    </bean>
                              And the output is the same for both instances.
                              And here someUtilities refrers to itself (circular reference, which is not allowed).

                              Comment

                              Working...
                              X