Chapter 5 - Services

Chapter 5 - Services

servicecontainer.png
Service container

The management of services is crucial for understanding how active components work. Each component can be seen as an autonomous service provider that offers services for other components. In case it needs services it can either use statically bound or dynamically searched services. Each component has a service container that should be used for all service management activities. It allows for fetching required services, explicitly searching for services at runtime and also for adding, removing or exchanging provided services. From within a component the service container can be fetched using getServiceContainer(). The interface of the container is jadex.bridge.service.IServiceContainer. The most important methods of the service container are shown in the following three code snippets:

public interface IServiceContainer
{
 public IFuture<Void> addService(IInternalService service, ProvidedServiceInfo info);
 public IFuture<Void> removeService(IServiceIdentifier sid);
 public IService getProvidedService(String name);
 public IService[] getProvidedServices(Class clazz);

 public <T> IFuture<T> getRequiredService(String name);
 public <T> IIntermediateFuture<T> getRequiredServices(String name);
 public <T> IFuture<T> getRequiredService(String name, boolean rebind);
 public <T> IIntermediateFuture<T> getRequiredServices(String name, boolean rebind);

 public <T> IFuture<T> getService(Class<T> type, IComponentIdentifier cid);
 public <T> IFuture<T> searchService(Class<T> type);
 public <T> IFuture<T> searchService(Class<T> type, String scope);
 public <T> IIntermediateFuture<T> searchServices(Class<T> type);
 public <T> IIntermediateFuture<T> searchServices(Class<T> type, String scope);
 
 public void addInterceptor(IServiceInvocationInterceptor interceptor, Object service, int pos);
 public void removeInterceptor(IServiceInvocationInterceptor interceptor, Object service);
 public IServiceInvocationInterceptor[] getInterceptors(Object service);
}

Provided Services

The first block of methods allows for adding and removing provided services. It has to be noted that, despite it is possible to use these methods at runtime, one should be aware that it is often better when components comply to their component type specifications and do not change their behavior later on.  

Required Services

 

The second block of methods shows how required services can be used. There is amethod to fetch a single service getRequiredService() and another one for fetching multiple services (those that have been defined with multiple=true) getRequiredServices(). Both methods come in two variants. The first variant only requires the name as argument. The second variant includes a rebind flag that allows for initiating a fresh binding by searching again the services according to the required service definition. This is only required if the service definition is static, i.e. dynamic=false which is the default. 

Search Services

The third block contains methods that can be used to dynamically locate methods at runtime. The first getService() methods is a convenience method to fetch a service of a given interface type from one exactly known other component. Hence the parameters are the interface type and the component identifier of the target component. The following two searchService() methods can be used to search for a service via its interface and an optional search scope. If no search scope is given, the default is application scope, i.e. all sub and super components within the application are included within the search. The same kinds of methods are available for multi services via the next two searchServices() methods.

The search scope defines the area of the search and is per default set to application. This means that only components within the started application are considered within the search. In the figure below a visual representation of the most relevant search scopes is given. Static constants for search scopes are available via the class RequiredServiceInfo.

Interceptor Handling

The fourth block is meant for runtime interceptor management of service. These methods can be used to add, remove and inspect interceptors for specific services. It has to be noted that interceptors are not supported for all required and for provided services which are not declared to have proxytype raw. Such provided services are directly invoked from the caller without running through the interceptor chain. The first method addInterceptor() can be used to add an interceptor at a specific position into the interceptor chain. If the interceptor should be placed at the end of the chain (before the real invocation occurs) the position can be set to -1. The second method removeInterceptor() can be used to remove a specific interceptor from the chain and the third method getInterceptors() deliver the interceptor chain for a service as array. These array can be inspected e.g. to decide at which position a new interceptor should be placed.

Tags:
Created by Lars Braubach on 2012/01/11 16:58
Last modified by Lars Braubach on 2012/03/07 11:00

Copyright (C) 2002-2012 Lars Braubach, Alexander Pokahr - University of Hamburg
XWiki Enterprise 2.1.1.25889 - Documentation