Announcement Announcement Module
Collapse
No announcement yet.
PropertyPlaceholderConfigurer for bean class Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • PropertyPlaceholderConfigurer for bean class

    I have just started to use Spring in a Tapestry web application. I'm currently making heavy use of Tapestry "extensions" which are managed objects just like Spring beans upon which properties can be set.

    I am planning on using the Spring stack to eliminate these Tapestry extensions, making the service objects into Spring beans. The initial target use of Spring then is as a simple service manager / locator.

    The application is heavily customized - a common idiom we use is to have an interface with a different concrete implementation for each client.

    So what I really wanted to do was:
    Code:
    	<bean id="serviceBean" class="$&#123;client.service.class&#125;" />
    ... and use the PropertyPlaceholderConfigurer to replace the token with the actual name of the concrete service class for a client.

    However, it seems that the PropertyPlaceholderConfigurer is useful only for replacing <property> values, which makes sense given its name.

    Is there a better way to accomplish this using Spring?

    An additional note: I would like to have a single applicationContext.xml file - each client would have their own client.properties with customized values.

  • #2
    try the following:
    Code:
      <bean id="serviceBean" class="java.lang.Class" factory-method="forName"> 
        <constructor-arg> 
          <value>$&#123;client.service.class&#125;</value>
        </constructor-arg> 
      </bean>
    HTH

    Comment


    • #3
      Thanks for the suggestion. That does almost what I'm looking for, except that the service bean ends up being a java.lang.Class instead of an instance of that class. Using that idea, I found that something like this works:

      Code:
      	<bean id="serviceFactory" class="java.lang.Class" factory-method="forName" singleton="false">
      		<constructor-arg><value>$&#123;client.service.class&#125;</value></constructor-arg>
      	</bean>
      	<bean id="serviceBean" factory-bean="serviceFactory" factory-method="newInstance" />
      Is there a way to accomplish this with a single <bean> declaration?

      Comment


      • #4
        The most direct route is not possible. I don't think Spring allows migration of bean attributes to elements so that an inline bean definitions could be used here, but maybe that would be useful in many other situations. [not implying this is what you are looking for, of course].


        Code:
        Not possible?
        
           <bean id="serviceBean" factory-method="newInstance"> 
                <property name="factory-bean">
                        <bean class="java.lang.Class" factory-method="forName" singleton="false"> 
                                <constructor-arg><value>$&#123;client.service.class&#125;</value></constructor-arg> 
                        </bean> 
                </property>
           </bean>



        Originally posted by bpryor
        Thanks for the suggestion. That does almost what I'm looking for, except that the service bean ends up being a java.lang.Class instead of an instance of that class. Using that idea, I found that something like this works:

        Code:
        	<bean id="serviceFactory" class="java.lang.Class" factory-method="forName" singleton="false">
        		<constructor-arg><value>$&#123;client.service.class&#125;</value></constructor-arg>
        	</bean>
        	<bean id="serviceBean" factory-bean="serviceFactory" factory-method="newInstance" />
        Is there a way to accomplish this with a single <bean> declaration?

        Comment


        • #5
          You could write your own factory bean class, e.g. ClassInstantiatingFactoryBean, implementing FactoryBean and having the class name as a property.

          Then you'd get your instance with
          Code:
          <bean id="serviceBean" class="foo.bar.ClassInstantiatingFactoryBean">
                  <property name="className"><value>$&#123;client.service.class&#125;</value></property>
          </bean>

          Comment


          • #6
            Use a factory bean

            How about this approach? It does mean writing some code though :?

            Code:
            public class Activator &#123;
            
                public static object createInstance &#40;string clazz&#41; &#123;
                      return Activator.createInstance &#40;Class.forName &#40;clazz&#41;&#41;;
                &#125;
            
                public static object createInstance &#40;Class clazz&#41; &#123;
                      return clazz.newInstance &#40;&#41;;
                &#125;
            &#125;
            Code:
             
            <bean id="serviceBean" class="Activator" factory-method="createInstance">
                <constructor-arg>
                  <value>$&#123;client.service.class&#125;</value>
                </constructor-arg>
              </bean>
            I have (obviously) left out all error checking, etc :wink:

            Comment


            • #7
              Thanks for all the suggestions. I ended up writing a simple class instantiator factory that does a Class.forName and a newInstance() based off a className argument. I used a single bean declaration with factory-method, passing in the className as a constructor-arg.

              This approach allows me to set properties on the created beans as well as specify their class.

              Comment

              Working...
              X