The Fulcrum Spring Framework Service allows embedding a Spring container as Avalon service or the other way round, i.e. embedding YAAFI and Avalon services in a Spring container.
The main goal of the implementation was providing transparent service lookup and embedding across the two different containers.
<!-- Get a hold on an Avalon Service Manager -->
<bean id="avalonContainerBean"
class="org.apache.fulcrum.yaafi.service.servicemanager.ServiceManagerServiceImpl"
factory-method="getInstance"
/>
<!-- Expose an Avalon service using a Spring factory bean -->
<bean id="systemPropertyService"
class="org.apache.fulcrum.spring.AvalonServiceFactoryBean">
<property name="serviceManager" ref="avalonContainerBean"/>
<property name="serviceName" value="systemPropertyService"/>
</bean>
<!-- Create a Spring bean and inject the Avalon service -->
<bean id="customSpringService" class="org.apache.fulcrum.spring.CustomSpringServiceImpl">
<property name="greeting" value="Hello Avalon!!!"/>
<property name="serviceManager" ref="avalonContainerBean"/>
<property name="systemPropertyService" ref="systemPropertyService"/>
</bean>
public void service(ServiceManager serviceManager)
throws ServiceException
{
this.customSpringService = (CustomSpringService)
serviceManager.lookup("customSpringService");
}
Technically this is implemented by telling YAAFI about components managing their own services. This information is contained in the 'serviceManagers' section of the container configuration file.
<fulcrum-yaafi>
<serviceManagers>
<serviceManager>springFrameworkService</serviceManager>
</serviceManagers>
</fulcrum-yaafi>
In this scenario the YAAFI Avalon container is created as Spring bean and the Avalon services within YAAFI are exposed using a Spring FactoryBean. This approach is not overly elegant since it requires some boiler-plate XML code to export Avalon services but it is trivial and works for all Spring versions in the wild.
<!-- Instantiate YAAFI using a container configuration file -->
<bean id="avalonContainerBean"
class="org.apache.fulcrum.spring.YaafiContainerBean"
init-method="initialize"
destroy-method="dispose">
<property
name="containerConfigValue"
value="./src/test/avalonIntoSpringContainerConfiguration.xml"
/>
</bean>
<!-- Expose an Avalon service using a Spring factory bean -->
<bean id="systemPropertyService"
class="org.apache.fulcrum.spring.AvalonServiceFactoryBean">
<property name="serviceManager" ref="avalonContainerBean"/>
<property name="serviceName" value="systemPropertyService"/>
</bean>
<!-- Create a Spring bean and inject the Avalon service -->
<bean id="customSpringService"
class="org.apache.fulcrum.spring.CustomSpringServiceImpl">
<property name="greeting" value="Hello Avalon!!!"/>
<property name="serviceManager" ref="avalonContainerBean"/>
<property name="systemPropertyService" ref="systemPropertyService"/>
</bean>
Please note that Avalon services can use Spring beans as well relying on the standard service lookup mechanism. Technically this is implemented by wrapping the Spring container into a class exposing a Service Manager interface and using this wrapper as parent service lookp. If the YAAFI instance in question does not find a service it delegates the service lookup to its parent Service Manager - in this case the Spring Framework - which can successfully resolve the service.
public void service(ServiceManager serviceManager)
throws ServiceException
{
this.customSpringService = (CustomSpringService)
serviceManager.lookup("customSpringService");
}