What is it ?
The Lucy back-end (
ILcyLucyEnv) provides a mechanism for sharing objects between different parts of Lucy without creating a hard dependency between those
This mechanism is called the service mechanism.
You can see it as a giant bag: you can put objects in the bag with
ILcyLucyEnv.addService(Object), and remove them from the bag with
It is also possible to request from the bag all objects that extend or implement a certain class or interface.
An example use case of why it is important to have such a mechanism involves the Lucy map add-on: the map add-on has an action to load data on the map, which needs to support a lot of data formats. Loading data on the map requires model decoders and layer factories. You can make those model decoders and layer factories available as services. By letting the loading action delegate to the model decoder and layer factory services, the action can support all data formats. You can add support for an extra data format without changing any action code, by adding new model decoders and layer factories to the services.
In this scenario, the data format add-ons are the suppliers of the services, and the open action of the map add-on a consumer of those services.
ILcyLucyEnv.getServices(Class) for more information, and for an overview of all types of objects which are available as service.
Summary: the service mechanism allows add-ons to register objects with a central registry, which can be queried and used by other add-ons. Doing so prevents hard dependencies between the different add-ons.
Example use case of the service mechanism
An example use case of the service mechanism is an action that creates an
ILcdGXYLayer for an
The action needs to find an
ILcdGXYLayerFactory that accepts the
ILcdModel and can create an
ILcdGXYLayer for it.
Typically, the available
ILcdGXYLayerFactory instances are not created in the action, but in separate
There are two options that let the action use those
ILcdGXYLayerFactory instances: either the add-ons set the factory instances on the action,
or there is a mechanism that allows the action to find those
The first option would introduce a hard dependency between the different add-ons and the action. Each add-on that adds support for a new data format needs to register its factory with that action. If a new action is introduced that also needs those factories, each format add-on needs to be adjusted to register its factory with that new action as well. This is not very scalable, and would make adding new functionality to Lucy very hard.
However, if those add-ons register their
ILcdGXYLayerFactory instances as service objects with the backend, as demonstrated by Program: Register an object as a service with the back-end,
the action can request them from the back-end later on, thereby preventing the dependency.
See Program: Retrieve the registered service objects from the back-end for an illustration.
ILcyLucyEnv aLucyEnv; ILcdGXYLayerFactory aLayerFactory; aLucyEnv.addService(aLayerFactory); //register the factory
ILcyLucyEnv aLucyEnv; //retrieve all registered ILcdGXYLayerFactory instances List<ILcdGXYLayerFactory> factories = aLucyEnv.getServices(ILcdGXYLayerFactory.class);
The Javadoc of the
ILcyLucyEnv.addService(Object, int) includes a list of all objects that are registered by default.