Component Module

The Component Module allows adding Java extensions to the XWiki Platform. The XWiki architecture is based on Component-oriented development and it is currently implementing its own lightweight ComponentManager.

Component Module Features

The Component Module defines the following features:

  • Supports JSR330 annotations for declaring Component Requirements: Component interfaces, Component implementations and Component dependencies.
  • The ability to have Singleton Components and Per-lookup Components which means that a new instance is created when the component is retrieved.
  • The ability to define a Hint in order to separate different Components implementations that are implementing the same Component interface.
  • Automatic Field-based injection of Component Dependencies and support for List and Map injections.
  • Ability for Components to perform some initialization when they are instantiated.
  • Component logging.
  • Notification of Component Events when a new Component is registered or unregistered in the system.
  • Ability to define Component Realms which means isolating groups of components.
  • Ability to define JSR330 Providers as Components and to have them injected automatically.

Register a Component

A Component can be registered:

  • By setting Java Annotations on the Component Interface and the Component implementation, then declaring the Component implementation in a META-INF/components.txt file.
  • By programmatically registering the Component against the Component Manager instance.

Component Annotations

The available Component Annotations are:

  • Role is used for declaring an Interface as a Component Role.
  • Component is used for declaring a class implementing a Component Interface as a Component implementation.
  • ComponentRole is now marked as deprecated and replaced by @Role.
  • InstantiationStrategy is used for declaring a Component implementation as being a Singleton or not. As seen in the ComponentInstantiationStrategy source page, the available strategies are:
    • Singleton - The same component implementation instance is returned for all lookups. When specifying a Singleton component, the @Singleton annotation should be used instead. 
    • PER_LOOKUP - A new component implementation instance is created at a each lookup. In this case, you should still use the @InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) annotation. If not specified, the default is currently a Singleton.
  • Inject is used for declaring a field which requires a Component implementation to be injected at runtime.
  • Named is used to give a Hint to the Role to specify which implementation should be injected.


Simple Registration

Define the Macro interface as the Component Interface:

public interface Macro
    List<Block> execute();

Define the MessageMacro class as a Macro with a message Hint in order to differentiate it from other implementations:

public class MessageMacro implements Macro
  private Execution execution;

  private Macro boxMacro;

  public List<Block> execute()

If you want to use the default hint, you can leave it empty. The MessageMacro has 2 components injected:

  • An Execution implementation with a default Hint
  • A Macro implementation with the box Hint

The implementation injected will be found at runtime by the Component Manager. In order for the MessageMacro component to be available at runtime, you need to list it with its fully-qualified name in a META-INF/components.txt file as follows: org.xwiki.rendering.internal.macro.message.MessageMacro

Registration Using a Provider

Providers are registered as standard components with the following annotations:

  • @Component
  • @Named
  • @Singleton 

The main difference, is that in this case there is no more need for the @Role annotation because implementing the javax.inject.Provider interface should suffice. In the below example, the ConfiguredQueryExecutorProvider Provider returns instances of QueryExecutor:

public class ConfiguredQueryExecutorProvider implements Provider<QueryExecutor>
  public QueryExecutor get()
      // return instance

To use this provider, you need to get it injected as follows:

private Provider<QueryExecutor> queryExecutorProvider;

The main advantages of using Providers include:

  • the ability to break a cyclic dependency.
  • the ability to get a component instance without having it injected when the Component is looked up for the first time; this allows your code to easily react to the registration of new Components at runtime.
  • the ability to control how to return the instance you are providing for.
A custom Provider doesn't need to be registered in order to be able to get it injected. If no registered Provider is found, the Component Manager injects a default Provider which does a lookup of the Component Role it provides, using the Component Manager. 

Registration Using Multiple Hints

It is possible to register a Component multiple times, using different Hints. One use case would be to register the MessageMacro presented above for the Hints: info, warning and error:

@Component(hints = {"info", "warning", "error" })
public class MessageMacro implements Macro {



Registration Using Multiple Roles

A component can be registered with multiple Roles, each one implementing another interface and producing a different instance. However, it is recommended to separate roles implementations in different classes as much as possible.

public class MessageMacro implements Macro, EventListener {



List and Map Injections

In order to have all the Component implementations of a given Component Interface injected, you need to have a field of type List 

private List<Macro> macros;

or Map defined, where Map keys are Hint values:

private Map<String, Macro> macros;

Access the Component Manager

For the cases when you don't know at compile time what you want injected, you cannot use automatic dependency injection anymore. However, you can inject the ComponentManager in which the component is registered:

private ComponentManager componentManager;

You can also access the root ComponentManager

private ComponentManager componentManager;

or even the context ComponentManager:

private Provider<ComponentManager> componentManagerProvider;

The Context Component Manager is a proxy Component Manager allowing to access a different Component Manager depending on the context.

The Component Manager

The Component Manager class allows to lookup components and register new components programmatically. Also, there is only one instance of the root Component Manager in the system, the default hint.

The Component Manager initialization is done automatically by the Container Module. However, if you are using XWiki as a library in your own application and you need to initialize the Component Manager in order to be able to perform lookups of other Components, you can use the below code:

EmbeddableComponentManager componentManager = new EmbeddableComponentManager();

To free all resources that components of this manager might hold, use the dispose() method:componentManager.dispose();

Initialize a Component

In case the Component implementation needs to perform an initialization, it has to implement the org.xwiki.component.phase.Initializable interface. This way, when the component is instantiated, the initialize() method will be called:

public class DefaultObservationManager implements ObservationManager, Initializable
  public void initialize() throws InitializationException
      // Initialization code

Log a Component

To enable the Component logging, you can automatically inject a SLF4J Logger:

import org.slf4j.Logger;
public class DefaultObservationManager implements ObservationManager
  private Logger logger;

  public void myMethod()
  {"Info message");
      // ...


Related Pages

Trying to decide between Cloud and On Premise? See the comparison on the XWiki Help Center.

Search this space