Jul 8th, 2008, 12:54 AM
Dynamically injecting a bean
I am new to Spring and I need some help/ideas about how should I address an object injection problem I have. To me it looks like very basic stuff and I cannot imagine there is not a GOOD & SIMPLE solution to this and for someone with a better than mine Spring experience should be a simple answer.
What is the problem in general:
You have an abstract class and a given number of concrete extensions. The abstract class has a field which is shared by all concrete implementations. This field is injected at a run time when you run one concrete class or another. Depending on which concrete class I am running I need the shared property to be an instance of a different thing. How can this be easily be achieved?
The concrete problem:
We have a number of test classes derived from org.springframework.test.AbstractTransactionalData SourceSpringContextTests
The AbstractTransactionalDataSourceSpringContextTests has a field called transactionManager.
Each concrete test works with a different database and has its own session factory and transaction manager. At run time a different transactionManager is needed depending on which concrete test I am running.
The XML look something like this.
<property name="sessionFactory" ref="sessionFactory1" />
<property name="sessionFactory" ref="sessionFactory2" />
<property name="sessionFactory" ref="sessionFactory3" />
The question is what is an easy way to load one of the above transactions managers into the transactionManager property.
Thank you in advance for your support.
Jul 8th, 2008, 10:24 AM
Hi Julian. I'm a little confused about the problem you describe--if the TransactionManagers have nothing in common beyond their class, then I would expect to have to provide three different definitions. Are you thinking that you'd like to be able to iterate over a list of SessionFactories and stamp out TransactionManagers accordingly, or something along those lines? (That way you could at least avoid repeating the classname?)
You can define parent/child relationships between beans using the bean/@parent attribute, though this addresses a problem that is different than--the exact opposite of, reallly--what you're describing. The problem @parent solves is factoring out what's *common* to a set of beans. So if you had three beans that had some fields in common but some differences as well, you would define an abstract bean (using bean/@abstract) for the parent and then define the three children using @parent to define the different values.
Last edited by wwheeler; Jul 8th, 2008 at 10:30 AM.
Jul 8th, 2008, 02:41 PM
Thanks for your comment. Unfortunately it looks like I did not make my problem clear. I will try to add more clarification.
First of all forget about the parent/abstract beans. This is something I know and it is not my case. Think about my problem as wanting to inject an instance of different objects into a given field depending on something.
The abstract class expects an object of a given type to be working with (programming on interface is a good practice isn’t it )
The abstract class has multiple concrete extensions (in my case they are test cases) that run independent one of each other. These concrete extensions are not beans. They are runable entry points.
When it comes to run time you need an instance of an object of that type (concrete implementation) to be injected.
Hope this is clearer now.
Lets give a concrete example:
1. You have a booking class that is able to book something ( a bookable thing)
2. Your booking class is abstract and all it knows when booking is to:
- check availability
- negotiate the price
- communicate terms and conditions
- mark as booked,
- cancel booking,
3. You have some concrete implementations of the booking class. They are BookingHotelRoom, BookingFlight, BookingMusicConcert etc
4. As the above names suggest each booking concrete implementation knows to work with a bookable thing: a hotel room, a flight, a music concert. All this things are bookable extensions.
5. When I want to book a hotel room I am running the book method of the concrete implementation BookingHotelRoom class. That obviously will reach code from the abstract booking class which doesn’t care what I want to book as long it is bookable.
6. The questions is how do I inject the HotelRoom bookable object into my booking class.
Hope I was able to make myself clear. This problem should not be an out of common one. That is the basis of inheritance and polymorphism (OOP in the end). It is just that I don’t know how to physically address it in Spring and I am sure the Spring guys could not skip this.
Jul 9th, 2008, 03:16 AM
Hey Julian. I *think* I understand better now what you are trying to do though not positive. Here's an idea for you and tell me if it's closer to the mark.
So I assume that your various booking classes and your various bookable classes are all non-singletons. Any time somebody wants to book a reservation, a new booking instance should appear, and similarly a new bookable instance should appear. And you just want to make sure that the right sort of bookable object appears in any given booking object. (E.g., you don't want a concert to appear in a BookingHotelRoom.) Moreover you want Spring to handle the injection here. Am I understanding correctly?
Here's the approach that comes to my mind. Say you have three concrete booking classes (let's use the ones you mentioned--BookingHotelRoom, BookingFlight, BookingMusicConcert) and three corresponding bookable classes. Then you can define all six as beans with scope="prototype". Then inject the three bookable beans into their booking counterparts. When you grab one of the booking objects, it will be a new instance. And when it grabs its bookable object, it will again be new, and of the right type.
Not sure that's what you're trying to do but hope that moves you forward a little at least. :-)
Jul 10th, 2008, 06:50 AM
Thank you for the reply.
Yes it is better now but not really what I meant. You missed the abstract bit. Think about it in terms of a strategy pattern. An abstract class (Booking) doesn’t know and doesn’t care, and it should not, which concrete implementation of the Bookable interface it is manipulating. It just deals with it as being a Bookable.
Please let me know whether some Java code is required to better expose the problem.
Jul 11th, 2008, 12:53 AM
Right, but I thought that you were saying that you've extended that abstract class such that each specific type of Bookable has a corresponding concrete Booking, no? So if you have a HotelRoom (which is Bookable) then you would have a corresponding BookingHotelRoom, as per your #3 above. So while I agree that the abstract Booking class doesn't know about the concrete implementation (meaning I agree with you that it deals with Bookables), that wasn't what I was suggesting. I was suggesting that you inject a HotelRoom prototype into a BookingHotelRoom prototype, a Flight prototype into a BookingFlight prototype, etc. That suggestion doesn't imply in any way that the abstract Booking class knows about specific Bookables.
Tags for this Thread