SeamFramework.orgCommunity Documentation

Chapter 14. Default Beans

Suppose you have a situation where you want to provide a default implementation of a particular service and allow the user to override it as needed. Although this may sound like a job for an alternative, they have some restrictions that may make them undesirable in this situation. If you were to use an alternative it would require an entry in every beans.xml file in an application.

Developers consuming the extension will have to open up the any jar file which references the default bean, and edit the beans.xml file within, in order to override the service. This is where default beans come in.

Default beans allow you to create a default bean with a specified type and set of qualifiers. If no other bean is installed that has the same type and qualifiers, then the default bean will be installed.

Let's take a real world example - a module that allows you to evaluate EL (something that Solder provides!). If JSF is available we want to use the FunctionMapper provided by the JSF implementation to resolve functions, otherwise we just want to use a a default FunctionMapper implementation that does nothing. We can achieve this as follows:

@DefaultBean(FunctionMapper.class)

@Mapper
class FunctionMapperImpl extends FunctionMapper {
   @Override
   public Method resolveFunction(String prefix, String localName) {
      return null;
   }
}

And in the JSF module:

class FunctionMapperProvider {

   
   @Produces
   @Mapper
   FunctionMapper produceFunctionMapper() {
      return FacesContext.getCurrentInstance().getELContext().getFunctionMapper();
   }
}

If FunctionMapperProvider is present then it will be used by default, otherwise the default FunctionMapperImpl is used.

A producer method or producer field may be defined to be a default producer by placing the @DefaultBean annotation on the producer. For example:

class CacheManager {

   
   @DefaultBean(Cache.class)
   Cache getCache() {
      ...
   }
     
}

Any producer methods or producer fields declared on a default managed bean are automatically registered as default producers, with Method.getGenericReturnType() or Field.getGenericType() determining the type of the default producer. The default producer type can be overridden by specifying @DefaultBean on the producer method or field.