Announcement Announcement Module
Collapse
No announcement yet.
singleton, unique, ... subtree-visible? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • singleton, unique, ... subtree-visible?

    Hello. I've got a problem.
    I have a structure of beans like this:

    Code:
    topBean
      subBean1
        handler1
        handler2
        ...
        handlerN
      subBean2
        handler1
        ...
        handlerM
      subBean3
        handler1
        ...
        handlerK
    Each of subBeanN contains a list of handlers. Each topBean instance has unique instances of subBeanN, and each of subBeanN contains unique instances of handlers, i.e. there are no singletons.

    Now for some of the beans I have to set the same instance of object Foo into some properties. I naively tried this:

    Code:
    <bean id="topBean" ... >
      <property name="subBean1" ref="subBean1"/>
      <property name="foo">
        <bean id="uniqueFoo" class="someFactory"/>
      </property>
      ...
    </bean>
    
    <bean id="subBean1" ... >
      <property name="handlers">
        <list>
          <bean id="handler1" class="...">
            <property name="foo" ref="uniqueFoo"/>
          </bean>
          ...
    Spring complains that uniqueFoo is not found in handler1. Yeah. Sure.
    But if I move bean uniqueFoo out of the topBean, then handler1 will get a different instance than topBean (factory is not singleton one).

    I cannot make the factory singleton since there are more than one topBean are created at the same time, and those must have unique instances of foo.

    Is there a way to achive what I want through the pure configuration?

    May be, there should be one more instance type: unique inside a given bean tree (i.e. from topBean and down)?

  • #2
    Hiya

    Short of configuring a distinct bean to complement each topBean and related subBeans (example below), I don't see a nice lean and mean configuration way round this (this is pretty verbose and it is only 8 beans).

    Code:
    <beans>
    	<bean id="baseFor1Beans" abstract="true">
    	  <property name="foo">
    		<bean id="uniqueFoo" class="someFactory"/>
    	  </property> 
    	</bean>
    	
    	<bean id="topBean1" parent="baseFor1Beans" ... >
    	  <property name="subBean1" ref="subBean1"/>
    	</bean>
    	
    	<bean id="subBean1" ... >
    	  <property name="handlers">
    		<list>
    		  <bean class="..." parent="baseFor1Beans"/>
    		  ...
    		</list>
    	  </property>
    	</bean>
    	
    	<bean id="baseFor2Beans" abstract="true">
    	  <property name="foo">
    		<bean id="uniqueFoo" class="someFactory"/>
    	  </property> 
    	</bean>
    	
    	<bean id="topBean2" parent="baseFor1Beans" ... >
    	  <property name="subBean2" ref="subBean2"/>
    	</bean>
    	
    	<bean id="subBean2" ... >
    	  <property name="handlers">
    		<list>
    		  <bean class="..." parent="baseFor2Beans"/>
    		  ...
    		</list>
    	  </property>
    	</bean>
    </beans>
    Ciao
    Rick

    Comment


    • #3
      I think I'm missing something. First of all, when talking about unique instances, if a bean with a unique name is only referenced once, then it effectively doesn't matter at all if it's marked as singleton or non-singleton, only one instance will ever end up being created. On the other hand, if it's referenced multiple times, then it needs to be marked as singleton to be shared. What is stopping you from doing this?

      Code:
      <bean id="uniqueFoo" class="someFactory"/>
      <bean id="uniqueFoo2" class="someFactory"/>
      <bean id="uniqueFoo3" class="someFactory"/>
      
      <bean id="topBean" ... >
        <property name="subBean1" ref="subBean1"/>
        <property name="foo" ref="uniqueFoo"/>
        ...
      </bean>
      
      <bean id="subBean1" ... >
        <property name="handlers">
          <list>
            <bean id="handler1" class="...">
              <property name="foo" ref="uniqueFoo"/>
            </bean>
            ...
      and then in any other place you want to use the same uniqueFoo, you just refer to the same named bean.

      Comment


      • #4
        well, I realized that my whole model was wrong.

        each transaction requires an unique set of beans, thus I had almost all beans as singleton=false. at the same time some beans inside the same transaction are set to different properties of top-level beans (i.e. shared), i.e. it must be singleton=true for them.

        to avoid the mess and cleanup the things I splitted the configuration into a few smaller configuration -- one per transaction. each time transaction starts I load the new ApplicationContext. each bean is a singleton now. thus the sharing problem is solved. I have to pay for that with a bit (0.15s) increased transaction time, but since the average time of transaction is about 10s, it's not a problem.

        it would be nice to know though if there any way to cache parsed Xml context definition and to create an unique ApplicationContext from that cached values...

        Comment


        • #5
          No, there's no way right now to cache the parsing step. You do have full programmatic control over the whole process via the BeanDefinitionReader and BeanDefinitionParser interfaces, and the hard implementations of those (such as XmlBeanDefinitionREader and XmlBeanDefinitionParser), but essentially the building of the app context for the XML case for exmaple happens as the document is parsed; as soon as the DOM tree is available it's used...

          It's somewhat of an interesting idea, although the reality is that for about 99% of the use-cases for Spring, people are not instantiating contexts over and over again. For the type of stuff (services as opposd to domain objects) that typically go into a context, even prototype objects are not incredibly common, although of course there's still a decent amount of usage of them.

          Regards,

          Comment


          • #6
            I have to disagree.

            In a typical business application there are one+ transaction happening at the same time. Beans inside of that transaction are "local" to that transaction, i.e. not supposed to be visible to other -- outside -- transactions. At the same time those beans are shared between other beans inside the same transactions (datasource, logger, ... ).

            So it's natural to match transaction boundaries with application context ones, simply because the application context posses all the properties I described above. The only problem is that you have to reload the context each time you use it.

            Basically, I use application context as a ... Statuful EJB? Yeah, something like that. It would be a real benefit for business applications to have an ability to cache context -- or to speed up it's loading in any other way.

            As I said, average time of loading Application context via ClassPathXmlApplicationContext takes 0.15 on my machine. It remains to be seen what takes most of this: search in classpath or parsing the XML...

            Comment


            • #7
              Well that's the whole point. In a typical web-app, what people put in the content is almost all stateless services which can and should be shared, and all the stateful stuff ends up as threadlocals and the like (current transaction, current datasource, etc.).

              Now this fits the typical request driven web architecture pretty well. When talking about a fat or or something else, the optimal setup may well be different.

              Regards,

              Comment

              Working...
              X