|
|
Help building multiple components based on Spring
Hi everybody,
I need some help to take a component based approach with spring. I need to share a Spring bean between 2 components but haven't succeeded yet.
I'll try to be as clear as possible (sorry for my poor english).
I have 2 components doing some database work : Label and Counter.
Internally Label and Counter use Spring JDBC to access the same database.
The clients of those components do not need to know that Spring is used internally (this is a requirement).
Counter component is a jar including a config file named pmx-main.xml :
Code:
lt;bean id=quot;pmxCounterApplicationContextquot; class=quot;org..context.support.ClassPathXmlApplicationContextquot;gt; lt;constructor-arggt; lt;listgt; lt;!-- pmx-counter-db-source.xml defines counterAccess bean --gt; lt;valuegt;pmx-counter-db-source.xmllt;/valuegt; lt;!-- defines data source used --gt; lt;valuegt;pmx-datasource.xmllt;/valuegt; lt;/listgt; lt;/constructor-arggt;
lt;/beangt;
A client of Counter component can get CounterAccess bean with a static call to CounterProvider.getCounterAccess(), so no need to do Spring stuff.
CounterProvider.getCounterAccess() uses a SingletonBeanFactoryLocator to load pmx-main.xml, get pmxCounterApplicationContext, then ask pmxCounterApplicationContext to return CounterAccess bean to the client.
CounterProvider sample code
Code:
// CounterProvider init
BeanFactoryLocator bfLocator = SingletonBeanFactoryLocator.getInstance(quot;pmx-main.xmlquot;);
BeanFactoryReference bfReference = bfLocator.useBeanFactory(quot;pmxCounterApplicationContextquot;);
springBeanFactory = bfReference.getFactory();
CounterProvider.getCounterAccess() just call springBeanFactory.getBean(quot;counterAccessquot;);
Label component follow the same pattern, it also has a config file named pmx-main.xml containing
Code:
lt;bean id=quot;pmxLabelApplicationContextquot; class=quot;org..context.support.ClassPathXmlApplicationContextquot;gt; lt;constructor-arggt; lt;listgt; lt;!-- pmx-label-db-source.xml defines LabelAccess bean --gt; lt;valuegt;pmx-label-db-source.xmllt;/valuegt; lt;!-- defines data source used --gt; lt;valuegt;pmx-local-datasource.xmllt;/valuegt; lt;/listgt; lt;/constructor-arggt;
lt;/beangt;
An approach similar to Counter component is used by Label to provide a LabelAccess to a client
Note that pmx-local-datasource.xml is not included in Label or Counter jar, it is available in a unique class path location.
This 2 components work fine in my standalone tests. I now want, in a third component, to do some transactionnal work involving both Label and Counter components.
I will use Spring to demarcate transactions declaratively in this third component which will retrieve Counter and Label access with the static code shown before.
In order to do this, I think Label and Counter need to share the same datasource (I'm not completely sure that it is mandatory).
Problem :
Although pmx-local-datasource.xml is not duplicated, Spring create 2 different datasource bean, on for each component.
I thought that using SingletonBeanFactoryLocator would load multiples config and shares beans but I certainly have misused it !
I have read the javadoc of SingletonBeanFactoryLocator multiple times but I must admit that everything is not crystal clear yet.
Can anynone give me advices to enable sharing the same datasource between Label and Counter components ?
What is the good way to have a component approach internally using Spring ?
Regards,
Joel
Hi,
me again ! with good news
After (re)reading SingletonBeanFactoryLocator javadoc, I found a solution using a parent application context where I have defined the datasource shared by my components.
Now Counter config looks like
Code:
lt;bean id=quot;pmxCounterApplicationContextquot; class=quot;org..context.support.ClassPathXmlApplicationContextquot; lazy-init=quot;truequot;gt; lt;constructor-arggt; lt;listgt; lt;valuegt;pmx-counter-db-source.xmllt;/valuegt; lt;/listgt; lt;/constructor-arggt; lt;constructor-arggt; lt;ref bean=quot;pmxCommonApplicationContextquot; /gt; lt;/constructor-arggt;
lt;/beangt;
pmxCommonApplicationContext is the parent application context defined as
Code:
lt;bean id=quot;pmxCommonApplicationContextquot; class=quot;org..context.support.ClassPathXmlApplicationContextquot; lazy-init=quot;truequot;gt; lt;constructor-arggt; lt;listgt; lt;valuegt;pmx-local-datasource.xmllt;/valuegt; lt;/listgt; lt;/constructor-arggt;
lt;/beangt;
I have done the same thing in Label component and now both use the same datasource instance (defined in pmx-local-datasource.xml)
Hope it will help someone else.
Regards,
Joel |
|