I have a library that provides access to many databases, all with the same table structure. The library has its own application-context.xml, and is exposed through a service bean in that context. Other applications use an import statement in their contexts and set a reference to the service bean.
The service bean's purpose is to retrieve data from one of the databases, based on a key value that determines the database to use. So, I have a DAO that relies on a RoutingDataSource, and the service bean calls a method in the DAO to set the key before making a call to retrieve data.
Here comes the problem:
- The application and even the service bean may use default Spring behavior and instantiate as singletons. That is optimal since it conserves memory and still remains threadsafe.
- But... if I load the DAO as a property into the service bean (as shown below), even if I set the DAO and RoutingDataSource with "prototype" scope (also shown below), I would be getting a single instance of the DAO in the service and lose thread safety (one thread could set the key to "1", a second thread set it to "2" and then the first thread could be accessing the wrong database!)
The cleanest solution I can think of (not a very good one) is:
- Not to define a myDao property in the myServiceImpl class
- Store the context in a static variable of myServiceImpl
- Get a fresh instance of the DAO in every method call by calling context.getBean().
Still, this "feels" wrong. Is there a better way?
Service bean, with a singleton instance of myDao:
DAO bean:Code:<bean id="myService" class="my.domain.MyServiceImpl"> <property name="myDao" ref="myDao" /> </bean>
RoutingDataSource:Code:<bean id="myDao" class="my.domain.MyDaoImpl" scope="prototype"> <property name="dataSource" ref="myRoutingDataSource" /> </bean>
Code:<bean id="myRoutingDataSource" class="my.domain.MyRoutingDataSourceImpl" scope="prototype"> <property name="targetDataSources"> <map key-type="java.lang.Long"> <entry key="1" value-ref="myDataSource1" /> ... <entry key="3" value-ref="myDataSource10" /> </map> </property> </bean>


Reply With Quote