cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Fagerstrom <dani...@nada.kth.se>
Subject Re: Sprinifying CForms
Date Wed, 24 Jan 2007 21:47:16 GMT
Vadim Gritsenko skrev:
> Daniel Fagerstrom wrote:
>> Vadim Gritsenko skrev:
>>> Giacomo Pati wrote:
>>>> CFroms is utilizing lots of Avalon ServiceSelector and this hinders 
>>>> extensibility of it as adding new Widget types etc. is becomming a 
>>>> pain with config files in jars.
>>>>
>>>> I've thought about a Spring version of a ServiceSelector to allow a 
>>>> more flexible configuration and extensibility with a class like
>>>>
>>>> class SpringServiceSelector implements BeanFactoryAware, 
>>>> ServiceSelector
>>>
>>> Eww :) Why do you need SpringServiceSelector? IMHO forms should be 
>>> just modified to obtain necessary dependencies directly from manager:
>>>
>>>   manager.lookup("o.a.c.f.f.WidgetDefinitionBuilder/form")
>>
>> Eww ;) Why do you need lookup? IMHO we should use dependency injection:
>
> Hint: ServiceManager is injected, or it should be.
BeanFactoryAware was mentioned above. But of course can the 
ServiceManager be injected.

>>   void setWidgetDefinitionBuilders(Map wdbs) { this.wdbs=wdbs; }
>> ...
>>
>>     this.wdbs.get("form");
>
> Hint: this operation is "map lookup". So you have replaced one lookup 
> from injected object with another lookup on another injected object. 
> Net result: no change. :-P
The important change is that Map not is container specific. You can use 
the component by just filling a map and testing it. No container dependency.

But thinking further on it, it doesn't matter that much in the 
particular scenario of forms. It is only the various builder and manager 
classes that use selectors. And they are not useful by them self anyway. 
So DI and avoiding container dependencies makes much more sense for the 
widgets than for the builder infra structure.

>> And the map is provided by a factory bean that looks up all beans 
>> that implements an interface and get the selector role from a property:
>>
>>   <property name="widgetDefinitionBuilders">
>>     <bean class="o.a.c...BeansByIntefaceFactoryBean">
>>       <property name="inteface"
>>                 value="o.a.c.f.f.WidgetDefinitionBuilder"/>
>>       <property name="roleAttribute" value="role"/>
>>     </bean>
>>   </property>
>
> This is *exactly* what we have now: nested declaration. And this is 
> *exactly* what causes the problem: there is no way to easily extend 
> standard configuration.
>
> There should be a way to add declarations of new forms component as 
> stand alone spring beans, and forms should be able to pick them up. I 
> figure we just should re-use existing machinery used in the sitemap. 
> It certainly beats introduction of Yet Another Way To Lookup Components.
I guess my description was to terse. What I tried to describe is an 
adaption of the whiteboard pattern from OSGi, that is used precisely for 
allowing pluggable extensions.

The BeanByIntefaceFactoryBean above is not a nested dependency at all. 
It is a factory bean that searches for all components in the container 
that implements a certain interface. For each such component it looks up 
the value of a property and then create a map that contains associations 
between  property values and the components.

A more complete example would be that we define a number of components, 
that could be spread out in many independent blocks:

<bean id="o.a.c.f.validation.WidgetValidatorBuilderSelector/length"
      class="o.a.c.f.validation.impl.LengthValidatorBuilder">
  <property name="type" value="length"/>
</bean>

<bean id="o.a.c.f.validation.WidgetValidatorBuilderSelector/range"
      class="o.a.c.f.validation.impl.RangeValidatorBuilder">
  <property name="type" value="range"/>
</bean>
...

Then we have components like that use the widget components that 
currently depends on selectors, they could be configured like this:

<bean id="o.a.c.f.f.WidgetDefinitionBuilder/form"
      class="org.apache.cocoon.forms.formmodel.FormDefinitionBuilder">
  <property name="type" value="form"/>
  <property name="widgetValidatorBuilders">
    <bean class="o.a.c...BeansByIntefaceFactoryBean">
      <property name="inteface"
                value="o.a.c.f.f.WidgetValidatorBuilder"/>
    </bean>
  </property>
  ...
</bean>

Where the BeanByIntefaceFactoryBean looks up the beans fulfilling a 
certain interface as described above.

But, again, in this particular case it is probably not worthwhile to 
strive for complete DI. Implementing a Spring selector as Giacomo 
described in the original mail is probably the simplest way to create 
extendability. And yes, that is achievable by using the 
BeanFactoryUtil.beansOfTypeIncludingAncestor 
http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/beans/factory/BeanFactoryUtils.html.

/Daniel


Mime
View raw message