eXo Platform 3.5

## Chapter 53. Service Configuration for Beginners

Related documents

- Service Configuration in Detail

- Services Wiring

- Container Configuration

## Objective

We are going to talk about service configuration. You will learn about modes, services and containers, you will find out where the service configuration files have to be placed and you will also see the overriding mechanism of configurations. Finally you will understand how the container creates the services one after the other and what Inversion of Control really means.

## Requirements

By reading this article you are already glancing at the heart of eXo Kernel.

Even you will read in this article to open the directory "exo-tomcat", you may have installed eXo Portal on any application server, just replace "exo-tomcat" by your folder name.

### Note

If you only installed the all-in-one package for the eXo Portal, the folder paths are a slightly different. You have to replace exo-tomcat by exo-eXoPortal-2.5.1-tomcat (obviously depending on your version). Furthermore the webapps are delivered as war files.

You certainly already discovered eXo's fisheye URL (eXo is open source!) - https://anonsvn.jboss.org/repos/exo-jcr/ - which allows you to surf in the source code of all classes, if you wish to do so.

## Services

Nearly everything could be considered a service! To get a better idea, let's look into the exo-tomcat/lib folder where you find all deployed jar files.

For example you find services for databases, caching, ldap and ftp:

- exo.core.component.database-2.1.3.jar

- exo.kernel.component.cache-2.0.5.jar

- exo.core.component.organization.ldap-2.1.3.jar

- exo.jcr.component.ftp-1.10.1.jar

Of course, there are many more services, in fact a lot of these jar files are services. To find out you have to open the jar file and then look into its /conf or /conf/portal directory. Only if there is a file named configuration.xml, you are sure to have found a service.

### Note

Why are there 2 different places to look for the configuration.xml? Because the /conf directory is used by the `RootContainer` and the /conf/portal directory is used by the `PortalContainer`. Later you will see more details about these containers.

Interface - Implementation It's important to get the idea that you separate the interface and implementation for a service. That is a good concept to reduce dependencies on specific implementations. This concept is well known for JDBC. If you use standard JDBC (=interface), you can connect any database (=implementation) to your application. In a similar way any service in eXo is defined by a java interface and may have many different implementations. The service implementation is then injected by a container into the application.

Singleton Each service has to be implemented as a singleton, which means that each service is created only once - in one single instance.

Service = Component You always read about services, and you imagine a service as a large application which does big things, but that's not true, a service can be just a little component that reads or transforms a document, therefore the term component is often used instead of service - so bear in mind: a service and a component can safely be considered to be the same thing.

## Configuration File

The jar file of a service should contain a default configuration, you find this configuration in the configuration.xml file which comes with the jar. A configuration file can specify several services, as well as there can be several services in one jar file.

For example open the exo.kernel.component.cache-2.0.5.jar file and inside this jar open /conf/portal/configuration.xml. You will see:

    <component>

    <key>org.exoplatform.services.cache.CacheService</key>

    <type>org.exoplatform.services.cache.impl.CacheServiceImpl</type>

    ...

Here you will note that a service is specified between the `<component>` tags. Each service has got a key, which defines the kind of service. As you imagine the content of the `<key>` tag matches the qualified java interface name (`org.exoplatform.services.cache.CacheService`) of the service. The specific implementation class of the `CacheService` is defined in the `<type>` tag.

Parameters You have already opened some configuration files and seen that there are more than just `<key>` and `<type>` tags. You can provide your service with init parameters. The parameters can be simple parameters, properties, or object-params. There are also plugins and they are special because the container calls the setters of your service in order to inject your plugin in your service (called setter injection) see Service Configuration in Detail. In general your service is free to use init parameters, they are not required.

If you ever need to create your own service, the minimum is to create an empty interface, an empty class and a constructor for your class - that's all. Ok, you also should put your class and the interface in a jar file and add a default configuration file.

## Execution Modes

One important thing to understand concerns execution modes. There are only two modes:

- Portal mode: The service runs embedded in the eXo Portal. In this mode a `PortalContainer` is used.

- Standalone mode: The service runs without the portal. For example, the JCR service can run standalone, and also the eXo Portlet Container. This mode is used by eXo developers for unit tests. As the name suggests a `StandaloneContainer` is used.

## Containers

In order to access to a service you need to use a Container. Just open https://anonsvn.jboss.org/repos/exo-jcr/kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container.

Among the classes you see in this directory, you only will be interested in these three container types:

- RootContainer: This is a base container. This container plays an important role during startup, but you should not use it directly.

- PortalContainer: Created at the startup of the portal web application (in the init() method of the PortalController servlet)

- StandaloneContainer: A context independent eXo Container. The `StandaloneContainer` is also used for unit tests.

Use only one container Even if there are several container types you always use exactly one. The RootContainer is never directly used and it depends on the execution mode if you use the PortalContainer or the StandaloneContainer. You will ask how to find out the execution mode in my application and how to manage these two modes. It's easy, you don't have to worry about it because the ExoContainerContext class provides a static method that allows you to get the right container from anywhere (see info box).

PicoContainer All containers inherit from the ExoContainer class which itself inherits from a `PicoContainer`. PicoContainer is a framework which allows eXo to apply the IoC (Inversion of Control) principles. The precise implementations of any service is unknown at compile time. Various implementations can be used, eXo supplies different implementations but they also may be delivered by other vendors. The decision which service to use during runtime is made in configuration files.

These configuration files are read by the container, the container adds all services to a list or more exactly a java HashTable. It's completely correct to suppose that the configuration.xml you already saw plays an important role. But there are more places where a configuration for a service can be defined as you see in the next chapter.

### Note

"In your java code you have to use

    ExoContainer myContainer = ExoContainerContext.getCurrentContainer();

in order to access to the current container. It doesn't greatly matter to your application if the current container is a `PortalContainer` or a `StandaloneContainer`. Once you have your container you may access to any service registered in this container using

    MyService myService = (MyService) myContainer.getComponentInstance(MyService.class);

You easily realize that `MyService.class` is the name of the service interface.

## Configuration Retrieval

The configuration you find inside the jar file is considered as the default configuration. If you want to override this default configuration you can do it in different places outside the jar. When the container finds several configurations for the same service, the configuration which is found later replaces completely the one found previously. Let's call this the configuration override mechanism.

### RootContainer

As both containers, PortalContainer and StandaloneContainer, depend on the RootContainer, we will start by looking into this one.

The retrieval sequence in short:

1. Services default `RootContainer` configurations from JAR files /conf/configuration.xml

2. External `RootContainer` configuration, to be found at exo-tomcat/exo-conf/configuration.xml

### Note

Naturally you always have to replace `exo-tomcat` by your own folder name. In case of a Java Standalone application you have to use the `user.dir` JVM system property value.

HashTable The `RootContainer` creates a java `HashTable` which contains key-value pairs for the services. The qualified interface name of each service is used as key for the hashtable. Hopefully you still remember that the `<key>` tag of the configuration file contains the interface name? The value of each hashtable pair is an object that contains the service configuration (yes, this means the whole structure between the `<component>` tags of your `configuration.xml` file).

The `RootContainer` runs over all jar files you find in exo-tomcat/lib and looks if there is a configuration file at /conf/configuration.xml, the services configured in this file are added to the hashtable. That way - at the end of this process - the default configurations for all services are stored in the hashtable.

### Note

What happens if the same service - recognized by the same qualified interface name - is configured in different jars? As the service only can exist one time the configuration of the jar found later overrides the previous configuration. You know that the loading order of the jars is unpredictable you must not depend on this.

If you wish to provide your own configurations for one or several services, you can do it in a general configuration file that has to be placed at exo-tomcat/exo-conf/configuration.xml. Do not search for such a file on your computer - you won't find one, because this option is not used in the default installation. Here again the same rule applies: The posterior configuration replaces the previous one.

The further configuration retrieval depends on the container type.

### PortalContainer

The PortalContainer takes the hashtable filled by the RootContainer and continues to look in some more places. Here you get the opportunity to replace RootContainer configurations by those which are specific to your portal. Again, the configurations are overridden whenever necessary.

In short PortalContainer configurations are retrieved in the following lookup sequence :

1. Take over the configurations of the RootContainer

2. Default PortalContainer configurations from all JAR files (folder /conf/portal/configuration.xml)

3. Web application configurations from the portal.war file - or the portal weppapp (folder /WEB-INF/conf/configuration.xml)

4. External configuration for services of a named portal, it will be found at exo-tomcat/exo-conf/portal/$portal_name/configuration.xml (as of Portal 2.5)

You see, here the /conf/portal/configuration.xml file of each jar enters the game, they are searched at first. Next, there is nearly always a configuration.xml in the portal.war file (or in the portal webapp folder), you find this file at /WEB-INF/conf/configuration.xml. If you open it, you will find a lot of import statements that point to other configuration files in the same portal.war (or portal webapp).

Multiple Portals Be aware that you might set up several different portals ("admin", "mexico", etc.), and each of these portals will use a different PortalContainer. And each of these PortalContainers can be configured separately. As of eXo Portal 2.5 you also will be able to provide configurations from outside the jars and wars or webapps. Put a configuration file in exo-tomcat/exo-conf/portal/$portal_name/configuration.xml where `$portal_name` is the name of the portal you want to configure for . But normally you only have one portal which is called "portal" so you use exo-tomcat/exo-conf/portal/portal/configuration.xml.

### Note

As of eXo Portal 2.5 you can override the external configuration location with the system property exo.conf.dir. If the property exists its value will be used as path to the eXo configuration directory, that means this is an alternative to exo-tomcat/exo-conf. Just put this property in the command line: java -Dexo.conf.dir=/path/to/exo/conf or use eXo.bat or eXo.sh. In this particular use case, you have no need to use any prefixes in your configuration file to import other files. For example, if your configuration file is exo-tomcat/exo-conf/portal/PORTAL_NAME/configuration.xml and you want to import the configuration file exo-tomcat/exo-conf/portal/PORTAL_NAME/mySubConfDir/myConfig.xml, you can do it by adding <import>mySubConfDir/myConfig.xml</import> to your configuration file.

### Note

Under JBoss application server exo-conf will be looked up in directory described by JBoss System property jboss.server.config.url. If the property is not found or empty exo-jboss/exo-conf will be asked (since kernel 2.0.4).

### StandaloneContainer

In the same way as the PortalContainer the StandaloneContainer takes over the configuration of the RootContainer. After that our configuration gets a little bit more tricky because standalone containers can be initialized using an URL. This URL contains a link to an external configuration. As you probably never need a standalone configuration you can safely jump over the remaining confusing words of this chapter.

After taking over RootContainer's configuration, there are three cases which depend on the URL initialization, :

- Independent configuration by URL No other configuration file is taken in consideration. The configuration provided by the URL is used without any default configs. That means that the container creates a new empty hashtable and not any bit of previous configuration is used. Apply the following code to do this:

      StandaloneContainer.setConfigurationURL(containerConf);

- Additional configuration by URL The StandaloneContainer is initialized very similar to the PortalContainer, but the last step is slightly different. A configuration file that is provided by the URL is used to replace some of the service configurations.The code looks like this:

      StandaloneContainer.addConfigurationURL(containerConf);

  1. Take over the configurations of the RootContainer

  2. Default StandaloneContainer configurations from JAR files (folder /conf/portal/configuration.xml)

  3. Web application configurations from WAR files (folder /WEB-INF/conf/configuration.xml)

  4. Configuration from added URL containerConf overrides only services configured in the file

- File based configuration No URL is involved, in this case the sequence is:

  1. Take over the configurations of the RootContainer

  2. Default StandaloneContainer configurations from JAR files (folder /conf/portal/configuration.xml)

  3. Web applications configurations from WAR files (folder /WEB-INF/conf/configuration.xml)

  4. External configuration for StandaloneContainer services, it will be found at $user_home/exo-configuration.xml. If $user_home/exo-configuration.xml doesn't exist and the StandaloneContainer instance obtained with the dedicated configuration classloader the container will try to retrieve the resource conf/exo-configuration.xml within the given classloader (user_home is your home directory like "C:/Documents and Settings/Smith").

## Service instantiation

As you have already learned the services are all singletons, so that the container creates only one single instance of each container. The services are created by calling the constructors (called constructor injection). If there are only zero-arguments constructors (`Foo public Foo(){}`) there are no problems to be expected. That's easy.

But now look at https://anonsvn.jboss.org/repos/exo-jcr/core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/OrganizationServiceImpl.java

This JDBC implementation of BaseOrganizationService interface has only one constructor:

    public OrganizationServiceImpl(ListenerService listenerService, DatabaseService dbService);

You see this service depends on two other services. In order to be able to call this constructor the container first needs a `ListenerService` and a `DatabaseService`. Therefore these services must be instantiated before `BaseOrganizationService`, because `BaseOrganizationService` depends on them.

For this purpose the container first looks at the constructors of all services and creates a matrix of service dependencies in order to call the services in a proper order. If for any reason there are interdependencies or circular dependencies you will get a java `Exception`. In this way the dependencies are injected by the container.

### Note

What happens if one service has more than one constructor? The container always tries first to use the constructor with a maximum of arguments, if this is not possible the container continues step by step with constructors that have less arguments until arriving at the zero-argument constructor (if there is one).

## Miscellaneous

### Startable interface

Your service can implement the startable interface which defines a start() and a stop() method. These methods are called by the container at the beginning and the end of the container's lifecycle. This way the lifecycle of your service is managed by the container.

### Inversion of Control

Retrospection Do you remember your last project where you had some small components and several larger services? How was this organized? Some services had their own configuration files, others had static values in the source code. Most components were probably tightly coupled to the main application, or you called static methods whenever you needed a service in your java class. Presumably you even copied the source code of an earlier project in order to adapt the implementation to your needs. In short:

- Each of your service had a proprietary configuration mechanism.

- The service lifecycles were managed inside of each service or were arbitrary.

- The dependencies between your services were implementation-dependent and tightly coupled in your source code.

New Approach You have seen that eXo uses the Inversion of Control (IoC) pattern which means that the control of the services is given to an independent outside entity, in this case a container. Now the container takes care of everything:

- The configuration is injected by external configuration files.

- The lifecycle is managed from outside, because the constructors are called by the container. You can achieve an even finer lifecycle management if you use the startable interface.

- The dependencies are injected by the service instantiation process.

Dependency Injection You also saw two types of dependency injections:

- Constructor injection: The constructor is called by the container.

- Setter injection: Whenever you use external-plugins to provide your service with plugins (see Service Configuration in Detail.

### More Containers

There are two more Containers called `RepositoryContainer` and `WorkspaceContainer`. These are specificities of eXo JCR, for the sake of simplicity. You don't need them.

### Single Implementation Services

In some case the developer of a service does not expect that there will be several implementations for his service. Therefore he does not create an interface. In this case the configuration looks like this:

    <key>org.exoplatform.services.database.jdbc.DBSchemaCreator</key>

    <type>org.exoplatform.services.database.jdbc.DBSchemaCreator</type>

The key and type tags contain equally the qualified class name.

### Configuration properties

Since kernel 2.0.7 and 2.1, it is possible to use system properties in literal values of component configuration meta data. Thus it is possible to resolve properties at runtime instead of providing a value at packaging time.

    <component>

      ...

      <init-params>

        <value-param>

          <name>simple_param</name>

          <value>${simple_param_value}</value>

        </value-param>

        <properties-param>

          <name>properties_param</name>

          <property name="value_1" value="properties_param_value_1"/>

          <property name="value_2" value="${properties_param_value_2}"/>

        </properties-param>

        <object-param>

          <name>object_param</name>

          <object type="org.exoplatform.xml.test.Person">

            <field name="address"><string>${person_address}</string></field>

            <field name="male"><boolean>${person_male}</boolean></field>

            <field name="age"><int>${age_value}</int></field>

            <field name="size"><double>${size_value}</double></field>

          </object>

        </object-param>

      </init-params>

    </component>

### Configuration Logging

In case you need to solve problems with your service configuration, you have to know from which JAR/WAR causes your troubles. Add the JVM system property `org.exoplatform.container.configuration.debug` to your eXo.bat or eXo.sh file (exo-tomcat/bin/).

    set EXO_CONFIG_OPTS="-Dorg.exoplatform.container.configuration.debug"

If this property is set the container configuration manager reports during startup the configuration retrieval process to the standard output (System.out).

    ......
    Add configuration jar:file:/D:/Projects/eXo/dev/exo-working/exo-tomcat/lib/exo.kernel.container-trunk.jar!/conf/portal/configuration.xml
    Add configuration jar:file:/D:/Projects/eXo/dev/exo-working/exo-tomcat/lib/exo.kernel.component.cache-trunk.jar!/conf/portal/configuration.xml
    Add configuration jndi:/localhost/portal/WEB-INF/conf/configuration.xml import jndi:/localhost/portal/WEB-INF/conf/common/common-configuration.xml
    import jndi:/localhost/portal/WEB-INF/conf/database/database-configuration.xml import jndi:/localhost/portal/WEB-INF/conf/ecm/jcr-component-plugins-configuration.xml
    import jndi:/localhost/portal/WEB-INF/conf/jcr/jcr-configuration.xml
    ......

## Further Reading

Do you feel an expert now? Not yet. Get a deeper look and read this Services Wiring article. You read so much about configuration, that you should wonder what the XML Schema of the configuration file looks like.

If you wish to see a examples of service configurations you should study the Core. Where you find descriptions of some eXo's core services. Finally you might wish to read more about PicoContainer.