Announcement Announcement Module
No announcement yet.
Use run-time value to load concrete spring class (managed by trans manager) Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Use run-time value to load concrete spring class (managed by trans manager)

    Problem: I want to be able to use a run-time value to tell Spring which of my concrete classes (beans) to load for a given interface. I also need the bean to be managed by Spring's transaction manager (which includes being able to specify the transaction properties in the spring config file).


    I have something like the following for business logic interface and concrete classes:

    public interface IVehicleProcessor { ... }
    public class VehicleCarProcessor implements IVehicleProcessor { ... }
    public class VehicleTruckProcessor implements IVehicleProcessor { ... }

    I want to be able to have the specific concrete class (VehicleCarProcessor, VehicleTruckProcessor) specified outside of my code (via Spring) and to be able to have these classes managed by Spring's transaction manager. The issue, though, is I want to be able to use a run-time value to select which concrete class to load - something I don't know how to do

    Without using a run-time value, I have something like the following in my spring bean configuration file which hard-codes the concrete class (note the transaction manager support):

    <bean id="VehicleProcessorTarget"
    class="" > <-- here's where the concrete class for IVehicleProcessor is specified
    <property name="dataSource" ref="DataSource" />

    <bean id="VehicleProcessor" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="target" ref="VehicleProcessorTarget"/>
    <property name="proxyTargetClass" value="true"/>
    <property name="transactionAttributes">
    <prop key="update*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED, -Exception</prop>

    And I get the bean via something like the following:
    public IVehicleProcessor getVehicleProcessor()
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config/spring/myspringbeans.xml");
    IVehicleProcessor vehicleProcessor = (IVehicleProcessor) this.context.getBean("VehicleProcessor");
    return vehicleProcessor;

    The problem, again, is that I need to be able to specify the concrete class for my bean based on a run-time value and not have the selection 'hard-coded' in the config file, and I want to be able to still be able to have it managed by spring's transaction manager.

    Logically, something like:
    public IVehicleProcessor getVehicleProcessor(String vehicleType)
    if (vehicleType.equals("Car"))
    // For VehicleProcessorTarget, load
    else if (vehicleType.equals("Truck"))
    // For VehicleProcessorTarget, load

    Of course, if the above if-else can be instead be put into the spring config (with the vehicleType passed to spring), that would be optimal.

    Any help?

    Last edited by metazoan; Sep 5th, 2012, 10:51 AM.

  • #2
    Ok - I think I solved it - will post in another reply once I finish testing. Had to use BeanFactoryPostProcessor's postProcessBeanFactory to get the bean factory, created a GenericBeanDefinition object w/ the class name (based on some run-time criteria), casted the factory to BeanDefinitionRegistry, and then added the GenericBeanDefinition to Spring via registerBeanDefinition(). I replaced the class for the bean named, VehicleProcessorTarget, and the transaction manager proxy that wraps it (bean name = VehicleProcessor) got the new one instead (I tested the transaction stuff and it worked). I'm now adding an XML file to replace my hard-coded stuff (e.g. if vehicleType.equals("Car")) ... else if vehicleType.equals("Truck") ...). I was hoping Spring could provide me with that but I'll just do my own for now. Again, will post when finished.


    • #3
      I think, you want to use only one of the implementation at a time. Therefore you may want to use environment profiles if you're using spring 3.1 and above. you'll need to create two different bean definition files for your car and truck beans with different profiles and enable one of the profile during execution. If you want to be able to use both simultaneously, you need to set a list containing the two beans in your transaction manager declaration.