Configuration API

Last modified by Admin on 2024/12/12 00:27

cogProvides the infrastructure for components needing configuration data
TypeJAR
CategoryAPI
Developed by

XWiki Development Team

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1
Bundled With

XWiki Standard

Installable with the Extension Manager

Description

If you're looking on how to configure XWiki check the Configuration page in the Platform Admin Guide.

The way to use this module is simple:

  • Each module creates an interface named <optional prefix><module name>Configuration (e.g. RenderingConfiguration, IconTransformationConfiguration, etc)
  • Each module creates an implementation of that interface, named Default<optional prefix><module name>Configuration (e.g. DefaultRenderingConfiguration)
  • The interface implementation then uses a ConfigurationSource components. These ConfigurationSource implementations are bound to sources where to get configuration data from: properties file, xwiki documents, etc.
  • Each module needs to respect the naming conventions for configuration properties.

Technically we use Apache Commons Configuration under the hood to perform the heavy lifting. This means we have the possibility to create lots of different Configuration Sources, to get the configuration data from JNDI, Database, etc. We also benefit from Commons Configuration's ability to define Lists and Maps in properties file and the support of variable interpolation.

In addition, there are also some extra Configuration APIs using platform concepts.

Configuration Source API

@Role
public interface ConfigurationSource
{
   /**
     * @param <T> the value type
     * @param key the property key for which we want the value
     * @param defaultValue the value to use if the key isn't found
     * @return the property value is found or the default value if the key wasn't found
     * @since 2.0M1
     */

   <T> T getProperty(String key, T defaultValue);

   /**
     * @param <T> the value type
     * @param key the property key for which we want the value
     * @param valueClass the type of object that should be returned. The value is converted to the passed type.
     * @return the property value is found. If the key wasn't found, null is returned except for the following special
     *         cases:
     *         <ul>
     *           <li>List: empty List</li>
     *           <li>Properties: empty Properties</li>
     *         </ul>
     * @since 2.0M1
     */

   <T> T getProperty(String key, Class<T> valueClass);

   /**
     * @param <T> the value type
     * @param key the property key for which we want the value
     * @param valueClass the type of object that should be returned. The value is converted to the passed type.
     * @param defaultValue the value to use if the key isn't found
     * @return the property value is found or the default value if the key wasn't found.
     * @since 12.0RC1
     */

   @Unstable
   default <T> T getProperty(String key, Class<T> valueClass, T defaultValue)
   {
       if (containsKey(key)) {
           return getProperty(key, valueClass);
       } else {
           return getProperty(key, defaultValue);
       }
   }

   /**
     * @param <T> the value type
     * @param key the property key for which we want the value
     * @return the property as an untyped Object or null if the key wasn't found. In general you should prefer
     *         {@link #getProperty(String, Class)} or {@link #getProperty(String, Object)}
     */

   <T> T getProperty(String key);

   /**
     * @return the list of available keys in the configuration source
     */

    List<String> getKeys();

   /**
     * @param key the key to check
     * @return true if the key is present in the configuration source or false otherwise
     */

   boolean containsKey(String key);

   /**
     * @return true if the configuration source doesn't have any key or false otherwise
     */

   boolean isEmpty();

   /**
     * Set a property, this will replace any previously set values.
     *
     * @param key The key of the property to change
     * @param value The new value
     * @throws ConfigurationSaveException when an error occurs during persistence
     * @since 15.9
     * @since 15.5.4
     * @since 14.10.19
     */

   default void setProperty(String key, Object value) throws ConfigurationSaveException
   {
       throw new UnsupportedOperationException("Modifying a property of this configuration source is not allowed");
   }

   /**
     * @param properties the set of properties to persist
     * @throws ConfigurationSaveException when an error occurs during persistence
     * @since 12.4RC1
     */

   @Unstable
   default void setProperties(Map<String, Object> properties) throws ConfigurationSaveException
   {
       throw new UnsupportedOperationException("Set operation not supported");
   }
}

Example

Interface:

@ComponentRole
public interface RenderingConfiguration
{
    String getLinkLabelFormat();
    Properties getMacroCategories();
    Properties getInterWikiDefinitions();

Implementation:

@Component
public class DefaultRenderingConfiguration implements RenderingConfiguration
{
   /**
     * Prefix for configuration keys for the Rendering module.
     */

   private static final String PREFIX = "rendering.";

   /**
     * @see #getLinkLabelFormat()
     */

   private static final String DEFAULT_LINK_LABEL_FORMAT = "%p";

   /**
     * Defines from where to read the rendering configuration data.
     */

   @Inject
   private ConfigurationSource configuration;

   /**
     * {@inheritDoc}
     *
     * @see XWikiRenderingConfiguration#getLinkLabelFormat()
     */

   public String getLinkLabelFormat()
   {
       return this.configuration.getProperty(PREFIX + "linkLabelFormat", DEFAULT_LINK_LABEL_FORMAT);
   }

   /**
     * {@inheritDoc}
     *
     * @see XWikiRenderingConfiguration#getMacroCategories()
     */

   public Properties getMacroCategories()
   {
       return this.configuration.getProperty(PREFIX + "macroCategories", Properties.class);
   }

   /**
     * {@inheritDoc}
     *
     * @see org.xwiki.rendering.internal.configuration.XWikiRenderingConfiguration#getInterWikiDefinitions()
     */

   public Properties getInterWikiDefinitions()
   {
       return this.configuration.getProperty(PREFIX + "interWikiDefinitions", Properties.class);
   }
}

Default Configuration Sources

The following configuration sources are provided in the configuration modules/extension. Other modules/extensions can provide other implementations.

"xwikiproperties"

You get access to this configuration source by using:

@Inject
@Named("xwikiproperties")
private ConfigurationSource configuration;

It reads configuration properties from the xwiki.properties file located in your webapp's WEB-INF directory.

"wiki"

You get access to this configuration source by using:

@Inject
@Named("wiki")
private ConfigurationSource configuration;

It reads configuration properties from the running XWiki instance, by reading properties from the XWiki.XWikiPreferences object in the XWiki.XWikiPreferences document.

"spaces"

XWiki 7.4+ You get access to this configuration source by using:

@Inject
@Named("spaces")
private ConfigurationSource configuration;

It reads configuration properties from the running XWiki instance, by reading properties from the XWiki.XWikiPreferences object in the current space's WebPreferences document and also all the space's parent spaces.

A "space" version exist too, which does not follow space's parents, but using it very rarely make sense. It's kept for retro compatibility reasons.

"user"

You get access to this configuration source by using:

@Inject
@Named("user")
private ConfigurationSource configuration;

Reads configuration properties from the running XWiki instance, by reading them from the XWiki.XWikiUsers# object found in the current logged in user's profile document.

"default"

You get access to this configuration source by using:

@Inject
private ConfigurationSource configuration;

Configuration properties are first looked for in the "space" source, if not found then in the "wiki" source and if not found in the "xwikiproperties" source. This is the recommended configuration source for most usages since it allows to define configuration properties in the xwiki.properties file and to override them in the running wiki (globally or per space).

"all"

You get access to this configuration source by using:

@Inject
@Named("all")
private ConfigurationSource configuration;

Configuration properties are first looked for in the "user" source, if not found then in the "space" source, if not found then in the "wiki" source and if not found in the "xwikiproperties" source.

"documents"

XWiki 6.1+ You get access to this configuration source by using:

@Inject
@Named("documents")
private ConfigurationSource configuration;

Configuration properties are first looked for in the "spaces" source and if not found then in the "wiki" source. Should be used when you need to look for configuration properties only in Documents (wiki pages).

"xwikicfg"

XWiki 6.1+ You get access to this configuration source by using:

@Inject
@Named("xwikicfg")
private ConfigurationSource configuration;

It reads configuration properties from the xwiki.cfg file located in your webapp's WEB-INF directory.

Properties Naming Rules

  • For configuration keys in xwiki.properties:
    • The first element after the package prefix (org.xwiki.contrib in Contrib projects or org.xwiki in XWiki Standard modules) is used as property name prefix (so properties related to org.xwiki.rendering.* code will use rendering)
    • Use <module>.<propertyName> (e.g. rendering.linkLabelFormat, oidc.claims)
    • For submodules, use <module>.<submodule>.<propertyName> (e.g. rendering.macro.velocity.filter, oidc.provider.subFormat)
    • Use camelcase for the property name itself (.e.g linkLabelFormat)
  • For configuration keys implemented as xproperties in wiki pages:
    • Use <propertyName (e.g. linkLabelFormat). The rationale is that the wiki page reference acts as the namespace.
    • For submodules, also use <propertyName for the same reason. 

List and Map definition in properties files

To define a List in a property file use one of the following methods:

propertyName = item1
propertyName = item2
propertyName = item3
propertyName = item1, item2, item3

In the code you'll get access to the List by doing:

List values = this.configuration.getProperty("propertyName", List.class);

To define a Map in a property file use the following:

propertyName = item1 = value1
propertyName = item2 = value2
propertyName = item3 = value3

In the code you'll get access to the Map by doing:

Properties values = this.configuration.getProperty("propertyName", Properties.class);

Variable interpolation in properties files

Example:

property1 = value1
property2 = ${property1}

Prerequisites & Installation Instructions

We recommend using the Extension Manager to install this extension (Make sure that the text "Installable with the Extension Manager" is displayed at the top right location on this page to know if this extension can be installed with the Extension Manager).

You can also use the manual method which involves dropping the JAR file and all its dependencies into the WEB-INF/lib folder and restarting XWiki.

Dependencies

Dependencies for this extension (org.xwiki.commons:xwiki-commons-configuration-api 16.10.1):

Get Connected