AgE 2.4 : Components and a component instance provider

Introduction

A component provides an implementation of any Java interface. The component is registered in a component instance provider (i.e. component registry) and than become available for other objects through the provider.

Components are Java classes which realize at least one interface. The component class has no restrictions and in fact can be any Java class (there is no need to implement any specific interface, extend some framework's class or any other). The example service and component class is shown at the below diagram:

Component instances are created at the first client request and are held until the platform stops (it is similar to the singleton design pattern).

On this page:

TODO: constructor and properties

Stateful components

Some of the components need to perform some operations before they are ready to use and also to make a cleanup before they are stop. Such components should implement the IStatefullComponent interface which contains the following two methods:

  • public void init() - called just after the component instance is created and before the instance is returned to the client (note: this method is called only once while creating a component instance)
  • public boolean finish() - called just before the component instance is unregistered; this is usually performed when the platform is going to shutdown. The method should be used to perform a cleanup, for instance closing network connections, removing temporary files.

Component instance provider

Service-locator design pattern

A service which requires other services to perform its tasks, needs to acquire a reference to a needed service through IComponentRegistry interface. The registry is in fact implementation of service-locator design pattern. There is a few ways to get a reference to a required service:

  • by service type - explain what does this method return if there is many IMyService implementations registered
    IMyService myService = instanceProvider.getInstance(IMyService.class);
    
  • by a parametrized service type — if a service require a component with specific type parameters; for example:
    IMyService<Number, MyClass> myService = (IMyService<Number, MyClass>)instanceProvider.getParametrizedInstance(IMyService.class, new Type[]{Number.class, MyClass.class});
  • by String ID - explain where the String ID is taken from
    IMyService myService = (IMyService)instanceProvider.getInstance("MY_SERVICE");
    

As service implementation can be registered by various modules, there is a very likely possibility to register many implementations of one interface. You can get all instances using getComponentInstances(Class<?>) method. For example you can use this method to get all stateful components:

Collection<IStatefulComponent> statefulComponents = instanceProvider.getInstances(IStatefulComponent.class)

Caching component instances

The component instances are created only during the first request. In all further requests, the same instance of the component is returned - this behaviour resembles the singleton design pattern.

Types of component instance providers

How to get access to the instance provider?

We already know how to acquire instance of a required service via the component registry, but how to get access to the registry?
By default components does not have an access to component registry. If they need to, they must declare this fact by implementing IComponentRegistryAware interface. The following code illustrates a sample service which has access to the component registry

public class MyInterfaceImplementation implements MyInterface, IComponentInstanceProviderAware {

     private IComponentInstanceProvider instanceProvider;

     public void setInstanceProvider(IComponentInstanceProvider instanceProvider) {
          this.instanceProvider = instanceProvider;
     }
}

Method setComponentRegistry is called automatically by the component framework while creating instance of MyInterfaceImplementation. This assures that the component registry available before the first use of the component. However, note that the registry cannot be used in the component's constructor as it is injected via a setter method.

Mutable component registry

Sometimes an access to component instances is not enough for services. Let us assume we have a configuration service which reads system configuration from the XML file and registers new components based on the configuration data. Our service needs to access MutableComponentRegistry which allows for registering new component instances providing a couple of methods:

Read API of these methods to get more details.

If a component instance wants to have access to the mutable registry it must implement IMutableComponentRegistryAware:

public class MyInterfaceImplementation implements MyInterface, IMutableComponentInstanceProviderAware {

     private IMutableComponentInstanceProvider instanceProvider ;

     public void setMutableComponentInstanceProvider(IMutableComponentRegistry instanceProvider ) {
          this.instanceProvider = instanceProvider ;
     }
}

Note: because IMutableComponentInstanceProvider extends IComponentInstanceProvider, having access to the mutable provider allows also for getting other component instances from the registry.

TODO: self aware component instance provider

Attachments: