|
From: Colin S. <col...@ex...> - 2005-02-23 03:12:07
|
Andy Depue wrote: >I'm going to add my 2c and just throw in what we do. Our rich client is >modular, in the sense that if a customer pays for a certain module, then they >get that functionality. To easily support this we split each module into its >own .jar. Our goal is that if a module's .jar is on the classpath, then its >"contributions" automatically becomes a part of the application. Our server >creates a WebStart .jnlp for each customer with their particular set of >module .jars setup for their classpath. Yes, this is basically nothing more >than a plugin architecture we are talking about. >So, how do we approach this from a configuration standpoint, seeing that we've >decided to use Spring and Spring-richclient? Basically how Rob has >described. Each module can specify its own Spring configuration file. We >can automatically detect these by requiring all module .jars to have their >Spring config in the same location and with the same name >(META-INF/context.xml). We then pass this into >FileSystemXmlApplicationContext: "classpath*:/META-INF/context.xml" >At this point we have one big ApplicationContext containing all the beans for >all modules. We now need some way to meaningfully and dynamically connect >the various beans together. Modules do not directly reference beans from >each other, because there is no guarantee that a module is going to be >present - meaning I can't do something like this: > ><bean id="modelManager" class="..."> > <property name="modelSources"> > <list> > <ref bean="fooModuleModel"/> > <ref bean="barModuleModel"/> > ... > </list> > </property> ></bean> > >because fooModuleModel and/or barModuleModel might not be present in the >ApplicationContext. So, we implement an idea that is similar in spirit to >"extension points". For each "extension point" we define a simple Java >interface, and then the extension point "stakeholder" will query the >ApplicationContext for beans implementing that interface: > Map modelSources = >BeanFactoryUtils.beansOfTypeIncludingAncestors(getApplicationContext(), >ModelSource.class, false, false); >Which will rake in all beans implementing ModelSource. The interface also >defines a contract that an extension point contributor must implement in >order to meaningfully "contribute" to the extension point. Granted, it would >be nice if Spring provided some automated way to perform this so I wouldn't >have to create dependencies on Spring in my classes (ApplicationContext, >getBeansOfType, etc). >If Spring wanted to automate this "extension point" mechanism such as it >exists in our project, it could provide something like this: > ><bean id="modelManager" class="..."> > <property name="modelSources" extension-point="com.mypackage.ModelSource"/> ></bean> > >Which would automatically build a collection by gathering all beans that >implement the specified interface and injecting the collection into the >"modelSources" property. > > - Andy > >PS In Spring, this whole idea is currently implemented in "recipe" fashion. >IoC containers like HiveMind make the idea a first class citizen. Actually, >we considered HiveMind, but it is not as mature as Spring and doesn't offer >many of the advanced integration constructs of Spring. > > This is an interesting topic (to me anyway). I'm onsite at a client this week so can't really think too much about it, but it'd be nice if this discussion leads to something... |