Tutorial: Programmatically creating a GraphQL endpoint for an admin team

20 minutes
Estimated Time

In this tutorial, you will programmatically create a GraphQL endpoint so that an administrator can manage it later in Brightspot. The endpoint requirements are as follows:

  • The endpoint should be able to fetch data from a content type that you define.
  • When the endpoint is deployed, it should be immediately available to the administrator.
  • The administrator should be able to control whether or not an API key is required.
  • The administrator should be able to control whether or not introspective queries are allowed in certain environments.

Because your admin team includes individuals of varying technical expertise, you will limit the number of configurable fields to only the two listed above—Access Option and Allow Introspection Queries—helping prevent mis-configuration of the endpoint. For a look into the administrator's role in this process, see Tutorial: Creating and expanding access for an endpoint in Brightspot.

In this tutorial, you will:

  1. Create a data model and view model.
  2. Create a Java class that will contain the endpoint configuration.
  3. Add a URL path from which the endpoint can be accessed.
  4. Configure the endpoint to fetch data from the data model.
  5. Allow an administrator to control whether or not an API key is required.
  6. Allow an administrator to control whether or not to allow introspective queries.

Assumptions

This tutorial assumes the following:

  • Familiarity with Brightspot's Java APIs
  • Familiarity with GraphQL

As a prerequisite for this tutorial, you will create two Java classes for your data model and view model, respectively.

For the data model, you will create a Java class named Product that extends Content.

public class Product extends Content {
    
    private String name;
    
    private String description;
    
    private String color;

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public String getColor() {
        return color;
    }
}


For the view model, you will create a Java class named ProductViewModel that extends ViewModel<Product>.

@ViewInterface
public class ProductViewModel extends ViewModel<Product> {

    public String getColor() {
        return model.getColor();
    }

    public String getName() {
        return model.getName();
    }

    public String getMessage() {
        return String.format("%s: %s: %s", getName(), getColor(), model.getDescription());
    }
}


In this step, you will be creating a single instance of a Java class named ProductDeliveryEndpoint that extends ContentDeliveryApiEndpoint. Because you will implement Singleton, the endpoint will be immediately available to the administrator when you deploy the code.

Note
This tutorial outlines the creation of a delivery API endpoint. For more information on management API endpoints, see Hello Content Management API.

@DisplayName("Product Delivery API")
public class ProductDeliveryEndpoint extends ContentDeliveryApiEndpoint implements Singleton {


In this step, you will specify a URL path with which to hit the endpoint. Endpoint URL paths are tied to Brightspot's permalink system, which automatically validates a given URL path for uniqueness.

@Override
public Set<String> getPaths() {
    return Collections.singleton("/product-delivery-api");
}
  • This API allows you to specify multiple URL paths from which the endpoint can be accessed; however, for the purposes of this tutorial, you will create only one.
Note
To hit the endpoint, append the URL path above onto the domain of your Brightspot instance (for example: https://cms.example.com/product-delivery-api-endpoint).


In this step, you will configure the endpoint so that it can fetch data. You will do this by creating a query entry field—a top-level field on the Query type—for use with your endpoint.

    @Override
    public List<ContentDeliveryEntryPointField> getQueryEntryFields() {
        return Collections.singletonList(
            new ContentDeliveryEntryPointField(ProductViewModel.class));
    }
  • References the view model you created in step 2 of this tutorial.


In this step, you will make the endpoint's access level configurable for an administrator. Over the course of the exercise, you will expand the code to control the future use of the field and prevent a validation error from occurring upon save.

  1. Define the editorial field.
    @Embedded
    private GraphQLApiAccessOption accessOption;
  2. Override the getApiAccessOption method, returning the editorially-specified value of the newly added field.
    @Override
    public GraphQLApiAccessOption getApiAccessOption() {
        return accessOption;
    }
  3. Make the field required.

    We add the @Required annotation here which has the effect of an error message displaying in the Brightspot UI if a user attempts to submit the form with a blank value for the field.

    @Embedded
    @Required
    private GraphQLApiAccessOption accessOption;

  4. Prevent a validation exception on save.

    Because it is a Singleton, Brightspot will attempt to save the instance of the endpoint the first time you deploy the code. Since the Access Option field has no value yet, the save would fail with a validation error (because of the aforementioned @Required annotation). The following beforeSave() implementation mitigates this problem by defaulting the value to an option that requires an API key.

    @Override
    protected void beforeSave() {
        super.beforeSave();
        
        if (accessOption == null) {
            accessOption = new GraphQLApiAccessOptionExplicit();
        }
    }

Your code should now look similar to the following:

@Embedded
@Required
private GraphQLApiAccessOption accessOption;

@Override
public GraphQLApiAccessOption getApiAccessOption() {
    return accessOption;
}

@Override
protected void beforeSave() {
    super.beforeSave();
    
    if (accessOption == null) {
        accessOption = new GraphQLApiAccessOptionExplicit();
    }
}


For the purposes of this tutorial, the company that gave you these endpoint requirements has three environments: QA, UAT, and Production. An administrator may want to configure whether introspection queries are allowed on a per-environment basis; to facilitate that, in this step you will add a Allow Introspection Queries toggle field to Brightspot.

private Boolean allowIntrospectionQueries;

@Override
public IntrospectionQueryRule getIntrospectionQueryRule() {
    return () -> Boolean.TRUE.equals(allowIntrospectionQueries);
}


All together, your data model, view model, and endpoint now resemble the following code snippets:

Product.java

public class Product extends Content {
    
    private String name;
    
    private String description;
    
    private String color;

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public String getColor() {
        return color;
    }
}

ProductViewModel.java

@ViewInterface
public class ProductViewModel extends ViewModel<Product> {

    public String getColor() {
        return model.getColor();
    }

    public String getName() {
        return model.getName();
    }

    public String getMessage() {
        return String.format("%s: %s: %s", getName(), getColor(), model.getDescription());
    }
}

ProductDeliveryEndpoint.java

@Recordable.DisplayName("Product Delivery API")
public class ProductDeliveryEndpoint extends ContentDeliveryApiEndpoint implements Singleton {

    @Embedded
    @Required
    private GraphQLApiAccessOption accessOption;

    private Boolean allowIntrospectionQueries;

    @Override
    public List<ContentDeliveryEntryPointField> getQueryEntryFields() {
        return Collections.singletonList(
            new ContentDeliveryEntryPointField(ProductViewModel.class));
    }

    @Override
    public Set<String> getPaths() {
        return Collections.singleton("/product-delivery-api");
    }

    @Override
    public GraphQLApiAccessOption getApiAccessOption() {
        return accessOption;
    }

    @Override
    public IntrospectionQueryRule getIntrospectionQueryRule() {
        return () -> Boolean.TRUE.equals(allowIntrospectionQueries);
    }

    @Override
    protected void beforeSave() {
        super.beforeSave();

        if (accessOption == null) {
            accessOption = new GraphQLApiAccessOptionExplicit();
        }
    }
}

The Brightspot UI now looks similar to the following image.

Note
After adding the following method and deploying the code, it will be the responsibility of the administrator to generate the API key and associate it with the endpoint. For a look into an administrator's role, see Tutorial: Creating and expanding access for an endpoint in Brightspot.

Our robust, flexible Design System provides hundreds of pre-built components you can use to build the presentation layer of your dreams.

Asset types
Module types
Page types
Brightspot is packaged with content types that get you up and running in a matter of days, including assets, modules and landing pages.

Content types
Modules
Landing pages
Everything you need to know when creating, managing, and administering content within Brightspot CMS.

Dashboards
Publishing
Workflows
Admin configurations
A guide for installing, supporting, extending, modifying and administering code on the Brightspot platform.

Field types
Content modeling
Rich-text elements
Images
A guide to configuring Brightspot's library of integrations, including pre-built options and developer-configured extensions.

Google Analytics
Shopify
Apple News