Broadleaf Microservices

Displaying a New Field with Broadleaf Metadata

In this tutorial, we will cover how to add a new field to an exiting entity’s metadata. Let’s add a preferredCommunicationMethod enum field to Customer.

For a more in-depth look at Broadleaf metadata, Check out the Unified Admin docs.
Custom metadata should go in MicroservicesDemo/services/metadata. You should make a different package for each service’s custom metadata such as com.broadleafdemo.metadata.customer or com.broadleafdemo.metadata.catalog.

Adding an Enum

First, let’s define our enum values. We’ll be implementing SelectOption.SelectOptionEnum to help us set the metadata up correctly. This will have a method to convert each Java enum value into a SelectOption representing an option used by a SelectField component in the Admin.

import com.broadleafcommerce.metadata.dsl.core.extension.fields.SelectOption;

import java.util.List;

public enum PreferredCommunicationMethodOptionEnum implements SelectOption.SelectOptionEnum {

    PHONE("", "primary"),
    TEXT("custom.customer.preferredCommunicationMethod.text", "primary"),
    EMAIL("", "primary");

    PreferredCommunicationMethodOptionEnum(String label, String color) {
        this.label = label;
        this.color = color;

     * This is displayed to the user and can be a message property key to support localized
     * translations.
    private String label;

     * Options can be differentiated by color as well. This should reference a color that the Admin
     * client understands such as {@code primary}, {@code gray}, {@code green}, etc. It defaults to
     * {@code default}, which means the default text color.
    private String color;

    public String label() {
        return label;

    public String color() {
        return color;

     * Factory method to generate a set of {@link SelectOption} from this enumeration. This will be
     * referenced in the metadata DSL for the related field to let the Admin know what values a
     * user can choose from.
     * @return the set of options
    public static List<SelectOption> toOptions() {
        return SelectOption.fromEnums(values());


Adding Localized Messages

Next, let’s look at adding the localized text in Sprint message properties files. We’ll place these in resources/messages/customer/

We’ll be adding just English text as the default. For translations, create property files in the same place but with the appropriate locale code as the suffix such as for Spanish translations and for French.
# enum value labels

# field label
custom.customer.preferredCommunicationMethod=Preferred Communication Method

To load these, we’ll add a MetadataMessagesBasename configuration class. This can be used to reference all custom messages files not just for customer, so we’ll move it out of the customer package into metadata.i18n.

package com.broadleafdemo.metadata.i18n;

import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull;

import com.broadleafcommerce.metadata.i18n.MetadataMessagesBasename;

import java.util.Arrays;

public class CustomMetadataMessages implements MetadataMessagesBasename {

    public String getBasename() {
        return StringUtils.join(Arrays.asList("messages/customer/custom-customer"), ",");

Then we add this to resources/META-INF/spring.factories in metadata.


Adding the new field using the DSL

Finally, let’s actually add the new field definition to the base metadata use the DSL. All components are registered with the application using ComponentSource beans. This is a functional interface that takes the registry of components as the input, which can be searched for already registered components or updated to include new ones.
package com.broadleafdemo.metadata.customer;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.broadleafcommerce.metadata.dsl.core.extension.views.details.CreateEntityView;
import com.broadleafcommerce.metadata.dsl.core.extension.views.details.EntityFormView;
import com.broadleafcommerce.metadata.dsl.core.extension.views.details.UpdateEntityView;
import com.broadleafcommerce.metadata.dsl.core.utils.Fields;
import com.broadleafcommerce.metadata.dsl.registry.ComponentSource;

public class CustomerMetadataConfig {

    static class CustomProps {
        public static final String PREFERRED_COMMUNICATION_METHOD = "preferredCommunicationMethod";

    public ComponentSource customCustomerMetadataComponents() {
        return registry -> {
            // find the create form
            CreateEntityView<?> customerCreate =
                    (CreateEntityView<?>) registry.get(CustomerIds.CREATE);
            // apply the updates

            // find the update form
            UpdateEntityView<?> customerUpdate =
                    (UpdateEntityView<?>) registry.get(CustomerIds.UPDATE);
            // apply the updates

    protected EntityFormView<?> modifyGeneralForm(EntityFormView<?> form) {
        return form
                        // refer back to our enum and call `#toOptions()`
                        // and we'll go ahead and set the default value