Chapter 3. eXo Architecture Primer

Architecture overview
Kernel
Containers
Services
Service configuration
Plugins
Configuration Loading Sequence
Gatein Extensions
The Default Portal Container
Registering Your Extension
Java Content Repository
Repositories and workspaces
3.2. Tree structure: working with nodes and attributes

All eXo services are built around the eXo Kernel, or the service management layer, which manages the configuration and the execution of all the components. The main kernel object is the eXo Container, a micro-container that glues services together through dependency injection. The container is responsible for loading services/components.

This chapter will introduce the concepts of Container and Services, and will give you a starting point for the basic configuration of Services.

A container is always required in order to access a service, because the eXo Kernel relies on dependency injection. This means that the life-cycle of a service (instantiating, opening and closing streams, disposing, etc.) is handled by a dependency provider (i.e. the eXo Container) rather than the consumer. The consumer only needs a reference to an implementation of the requested service, which is provided in the configuration.xml file that comes with every service. You can read more about dependency injection here http://en.wikipedia.org/wiki/Dependency_injection.

eXo has two several kinds of container, the RootContainer and the PortalContainer. The RootContainer holds the lower level components. It is automatically started before the PortalContainer. You will rarely interact directly with it except to activate your own extension (more on this further). The PortalContainer is created at the startup of the portal web application (portal.war). All services started by this container will run embedded in the portal. It also gives access to the components of its parent RootContainer

In your code, if you need to invoke a service of a container, you can use the ExoContainerContext helper from any location. The code below shows you a utility method that you can use to invoke any eXo service.


public class ExoUtils {

  /**
   * Get a service from the portal container
   * @param type : component type
   * @return the concrete instance retrieved in the container using the type as key
   */
  public <T>T getService(Class<T> type) {
    return (T)ExoContainerContext.getCurrentContainer().getComponentInstanceOfType(type);
  }
  
}

Then, invoking becomes as easy as :

  OrganizationService orgService = ExoUtils.getService(OrganizationService.class)

To declare a service, you must add an xml configuration file in a specific your classpath. A configuration file can specify several services, so there can be several services in one jar file.

For the object-param component, we can look at the LDAP service:

An object-param is being used to create an object (which is actually a Java Bean) passed as a parameter to the service. This object-param is defined by a name, a description and exactly one object. The object tag defines the type of the object, while the field tags define parameters for that object.

Let's see how the service accesses the object:

The passed object is LDAPConnectionConfig, which is a classic Java Bean. It contains all fields defined in the configuration files and also the appropriate getters and setters (not listed here). You also can provide default values. The container creates a new instance of your bean and calls all setters whose values are configured in the configuration file.

Gatein extensions are special war files that are recognized by eXo Platform and contribute to custom configurations to the PortalContainer. In order to create your own portal, you will effectively create a Gatein extension.

The extension mechanism makes it possible to extend or even override portal resources in an almost plug-and-play fashion, by simply dropping in a .war archive with the resources and configuring its location in the portal's classpath. Customizing a portal do not involve unpacking and repacking the original portal .war archives. Instead, you create your own .war archive with your own configurations, and eventually modified resources that override the resources in the original archive.

First, you will want eXo to load the WEB-INF/conf/configuration.xml of your extension. For this, declare it as a PortalConfigOwner in web.xml :

Then you need to register your extension by appending it to the list of dependencies that already contribute to the portal container. This is done by an xml configuration liek this :

We define a PortalContainerDefinitionChange$AddDependencies plugin to the PortalContainerConfig. The plugin declares a list of dependencies that are webapps. The apply.default=true indicates that your extension is acutally extending portal.war.

All data in eXo Platform is stored in a Java Content Repository (JCR). JCR is a Java specification (JSR-170 ) for a type of Document database. It is particularly useful for content management systems, which require storage of objects associated with metadata. A JCR also provides versioning, transactions, observations of changes in data, and import and export of data in XML. The data in a JCR is stored hierarchically in a tree of Nodes with associated Properties.

Also, the JCR is primarily used as an internal storage engine, eXo Content let's you manipulate JCR data directly in several places. This quick intro will tell you how to quickly get your hands on it.