Custom Value List Providers

Info: Custom value list providers are available starting from brXM 16.9.2 and 17.1.0.

By default, the Selections plugin retrieves its options from Value List documents stored in the repository. A custom value list provider allows you to supply these options from an alternative source, such as a REST service, a database, or a dynamically generated list.

Info: Starting in brXM 16.9.2 and 17.1.0, custom providers are resolved using a single registry shared by both the legacy CMS document editor and the Experience Manager (visual editor). You only need to register the provider once for both editors.

Select an Interface

InterfaceUse forNotes
org.onehippo.forge.selection.frontend.provider.ValueListProviderNew implementations (recommended)Does not depend on Wicket. Receives a JCR Session as a method argument.
org.onehippo.forge.selection.frontend.provider.IValueListProviderExisting implementationsExtends Wicket's IClusterable, which adds Wicket as a dependency. Retained for backward compatibility.

Below is a minimal implementation of a custom provider:

package com.example; import java.util.Locale; import javax.jcr.Session; import org.onehippo.forge.selection.frontend.model.ListItem; import org.onehippo.forge.selection.frontend.model.ValueList; import org.onehippo.forge.selection.frontend.provider.ValueListProvider; public class CountryValueListProvider implements ValueListProvider { @Override public ValueList getValueList(final String name, final Locale locale, final Session session) { final ValueList list = new ValueList(); list.add(new ListItem("nl", "Netherlands")); list.add(new ListItem("be", "Belgium")); return list; } }

Requirements for a custom provider:

  • Provide a public no-argument constructor. The platform instantiates the provider reflectively.
  • Do not use Wicket APIs or UserSession.get(). The provider is called outside a Wicket request cycle. Use the session argument for repository access.
  • The name argument receives the field's source property. It may be empty if the field does not specify a source.
  • Always return a ValueList instance. Do not return null; return an empty ValueList if no values are available.

The platform does not cache results from custom providers. If your provider accesses a slow external system, implement caching and invalidation as needed.

Optional: Provider Configuration

To read configuration from the provider's JCR node, implement the configure(Node) method. The platform calls this method once after instantiation and before registration.

@Override public void configure(final Node providerNode) throws RepositoryException { if (providerNode.hasProperty("endpoint")) { this.endpoint = providerNode.getProperty("endpoint").getString(); } }

Register the Provider

Register your provider by adding a child node under the value list service's module configuration. The providers node is included with the platform; you only need to add your specific provider node.

definitions: config: /hippo:configuration/hippo:modules/valuelist-service/hippo:moduleconfig/providers/service.valuelist.countries: jcr:primaryType: hipposys:moduleconfig class: com.example.CountryValueListProvider endpoint: https://example.com/api/countries # optional, read via configure(Node)
  • The node name is the provider's service name (e.g., service.valuelist.countries). Use this value for the field's valuelistProvider property.
  • The class property is required and must specify a class implementing ValueListProvider (or IValueListProvider).
  • service.valuelist.default is reserved for the built-in Value List document provider. Do not use this name for custom providers.
  • Adding, modifying, or removing a provider node takes effect immediately without restarting the repository. If you change the provider class, redeploy the project.

Assign the Provider to a Selection Field

In the Document Type Editor, set the valuelistProvider property of a Dynamic Dropdown, Radio Group, or multi-select field to the provider's service name. In the configuration, this property is set under the field's cluster.options node:

/hippo:namespaces/myproject/newsdocument/editor:templates/_default_/country: jcr:primaryType: frontend:plugin # ... field wiring omitted ... /cluster.options: jcr:primaryType: frontend:pluginconfig valuelistProvider: service.valuelist.countries

The source property is optional when using a custom provider. If present, its value is passed to the provider as the name argument.

The dotted key valuelist.provider is a deprecated alias for valuelistProvider. The platform still supports it (the canonical key takes precedence if both are present) and logs a deprecation warning. Update any usage to valuelistProvider.

Legacy Registration with cms-services

Providers registered using the legacy cms-services approach continue to work:

/hippo:configuration/hippo:frontend/cms/cms-services/countryValueListProvider: jcr:primaryType: frontend:plugin plugin.class: com.example.CountryValueListProvider valuelist.provider: service.valuelist.countries

In this context, valuelist.provider refers to the service name under which the provider is registered, not the deprecated field property. The platform automatically detects these entries if the class has a public no-argument constructor. If a service name exists in both locations, the moduleconfig/providers entry takes precedence.

Providers that extend org.hippoecm.frontend.plugin.Plugin (including subclasses of DocumentValueListProvider) cannot provide a no-argument constructor and cannot be instantiated this way. These providers continue to work in the legacy CMS document editor. In the Experience Manager, the field displays an empty list. To support both editors, migrate the provider as described below.

Editor Compatibility

RegistrationProvider typeLegacy CMS document editorExperience Manager
moduleconfig/providersPOJO (ValueListProvider / IValueListProvider)YesYes
cms-servicesPOJO with public no-arg constructorYesYes
cms-servicesextends Plugin (legacy)YesNo (renders empty list)
none (default)built-in Value List documentYesYes

Upgrading an Existing Provider

Before — Wicket Plugin provider (works only in the legacy editor):

public class CountryValueListProvider extends Plugin implements IValueListProvider { public CountryValueListProvider(final IPluginContext context, final IPluginConfig config) { super(context, config); context.registerService(this, config.getString(IValueListProvider.SERVICE)); } @Override public ValueList getValueList(final String name, final Locale locale) { final Session session = UserSession.get().getJcrSession(); return buildList(session); } @Override public List<String> getValueListNames() { return Collections.singletonList("countries"); } }

After — POJO provider (works in both editors):

public class CountryValueListProvider implements ValueListProvider { @Override public ValueList getValueList(final String name, final Locale locale, final Session session) { return buildList(session); } }

Update the provider as follows:

  1. Remove extends Plugin and the constructor with IPluginContext and IPluginConfig. Registration is now handled by the configuration node.
  2. Use the session argument from the method signature instead of UserSession.get().
  3. Move any plugin configuration reads into the configure(Node) method.

The getValueListNames() method is not required for ValueListProvider and can be removed.

Bootstrap — update the registration from cms-services to providers:

# remove /hippo:configuration/hippo:frontend/cms/cms-services/countryValueListProvider: jcr:primaryType: frontend:plugin plugin.class: com.example.CountryValueListProvider valuelist.provider: service.valuelist.countries # add /hippo:configuration/hippo:modules/valuelist-service/hippo:moduleconfig/providers/service.valuelist.countries: jcr:primaryType: hipposys:moduleconfig class: com.example.CountryValueListProvider

The service name remains unchanged, so you do not need to update document type configurations. While updating, rename any valuelist.provider field property to valuelistProvider.

Troubleshooting

Log messageCause
Provider '' class '' is not Experience Manager compatibleThe provider does not have a public no-argument constructor (often because it extends Plugin), or the class failed to load. The provider is skipped.
Provider '' class '' does not implement ValueListProviderThe class specified in the configuration does not implement the required interface.
Skipping provider '': missing 'class' propertyThe provider node is missing the class property.
No ValueListProvider registered under name ''; returning empty listThe field references a service name that is not registered. Check for typos or review skipped providers in the logs.
Plugin config uses deprecated key 'valuelist.provider'; rename it to 'valuelistProvider'.The field uses the deprecated property name. Update it to valuelistProvider.

If a dropdown in the Experience Manager is empty while the legacy editor displays values, the provider is likely a Plugin subclass registered under cms-services. See the Upgrading an Existing Provider section above for migration steps.

Share Feedback
Page: /build/document-types/document-types/custom-value-list-providers
Section: Build
Category *
Custom Value List Providers | Bloomreach Content Documentation