Announcement Announcement Module
Collapse
No announcement yet.
Scripting in Bean file: dynamic number of instances in List Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Scripting in Bean file: dynamic number of instances in List

    Hi everyone,
    I am looking for a possibility to configure the following in my bean definition file:

    Using the PropertyPlaceholder I have a placeholder for a number n.
    Now I need a bean which is a List containing objects that are also declared as beans.
    I would like to fill this list with n instances of that bean.
    I was checking some Spring book and also used the forum search, but so far I did not find any solution.

    Maybe one of you can help? If there is no possibility to do it directly in the bean file, what is the easiest way to do it? I would like to avoid creating a class that creates a new BeanFactory / AC and loads the bean n times.

    Thanks in Advance!
    authorscrash

  • #2
    Hi all,
    I have been checking websites again and tried several things, but so far I still do not see a solution.
    Any advice how to solve the problem in the best way is appreciated!
    Thanks in advance,
    authorscrash

    Comment


    • #3
      Hi,
      Please could you explain a little more your problem.
      Aside of that, in the following code:
      @Autowired
      private List<Employee> employeeList;

      Spring will set in "employeeList" all the beans of type "Employee"
      Regards

      Comment


      • #4
        Hi all,
        thanks for your answer, gmateo. It's been a while and I found a solution for the problem which I think is also interesting for future releases of the Spring Framework. So let me describe the problem and solution in more detail:

        Problem:
        We are developing a software for high performance processing of incoming requests. For this, we are using threads, the number of maximum threads our system can be configured in the bean XML file (externalized in property configurer). Now, we need to prepare a number of object instances at server startup, the creation takes a while, so we have to prepare the objects and keep them, ready for request processing. In some cases, we can inject the so called MagicInstanceNumber, but in some cases we need a list containing MagicInstanceNumber bean objects. If you want to change the configuration, you need to change the MagicInstanceNumber, and additionally all bean declarations that contain such a dependent list, like (simplified):
        Code:
        <bean id="xy">
         <list>
           <bean ref="a"/>
           <bean ref="a"/>
           <bean ref="a"/>
           <bean ref="a"/>
         </list>
        </bean>
        I was looking for a possibility of scripting in bean configuration files that allows me to define that a bean should be inserted MagicInstanceNumber times into the list.

        Solution:
        No scripting in bean files, but a helper class providing the ready-instantiated lists. This helper class can be included into future releases of the Spring Framework. First the example, then the description:

        Bean config file for helper class:
        Code:
        <bean class="java.lang.Integer" id="MagicInstanceNumberProviderBean" factory-method="parseInt">
            		<constructor-arg>
                 		<value>${magicInstanceNumber}</value>
             		</constructor-arg>  	
               	</bean>
               	
               	<bean class="org.project.common.configuration.MagicInstanceNumberFactory" id="org.project.common.configuration.MagicInstanceNumberFactory" />
        The helper class itself:
        Code:
        public class MagicInstanceNumberFactory {
        
        	// static
        	
        	private static final String LOCATIONS_XML_PATH 			 = "org/project/configuration/locations.xml";
        	private static final String LOCATIONS_XML_BEANNAME 		 = "configLocationList";
        	private static final String MAGICINSTANCENUMBER_BEANNAME = "MagicInstanceNumberProviderBean";
        	
        	// instance data
        	
        	private ApplicationContext mContext;
        	private int mMagicInstanceNumber;
        	
        	// constructor
        	
        	public MagicInstanceNumberFactory() {
        		ensureContextAvailability();
        	}
        	
        	// public
        	
        	public List<?> magicList(String... contentBeanNames) {
        		List<Object> result = new ArrayList<Object>();
        		for (String s : contentBeanNames)
        			for (int i = 0; i < mMagicInstanceNumber; i++)
        				result.add(mContext.getBean(s));
        		return result;
        	}
        	
        	// private
        	
        	private void ensureContextAvailability() {
        		if (mContext == null) {
        			ApplicationContext contextPreparer = new ClassPathXmlApplicationContext(LOCATIONS_XML_PATH); // A BeanFactory is sufficient here.
        			List<String> configLocations = (List<String>) contextPreparer.getBean(LOCATIONS_XML_BEANNAME);
        			mContext = new ClassPathXmlApplicationContext(configLocations.toArray(new String[0]));
        			mMagicInstanceNumber = (Integer) mContext.getBean(MAGICINSTANCENUMBER_BEANNAME);
        		}
        	}
        	
        }
        You see that two ApplicationContexts are created. This is because we have a special mechanism to handle several bean configuration files (to keep some order). At startup, one Context looks up a config file containing the paths to all relevant config files of the application. This mechanism is implemented here as well because the factory application context needs to access all bean config files as well.

        Now, here is what the new configuration looks like. You can replace all <list> beans containing MagicInstanceNumber bean references by this:

        Code:
        ...
        <property name="protocolReaders">
               		    <bean factory-bean="org.project.common.configuration.MagicInstanceNumberFactory" factory-method="magicList">
                        	<constructor-arg value="beanA,beanB" />
                        </bean>
               		</property>
        This solves our problem and works fine, no problems even if the lists that have to be injected as property or constructor-arg are typed. Now we really have a MagicInstanceNumber because there is only one switch that allows us to scale the application.

        Hope this helps anyone and makes its way into the Framework.
        Happy coding,
        authorscrash

        Comment

        Working...
        X