> For the complete documentation index, see [llms.txt](https://help.smallbuilder.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.smallbuilder.com/smallbuilder-lists/setup/datasource-setup/external.md).

# External data sources

**External data sources should be used when you want to retrieve data from an external server and present it alongside data from a standard or custom Salesforce object. Since the datasource is accessed using a user-defined Apex class, you can retrieve data more flexibly compared to an internal datasource.**

For example, if you want to retrieve real-time inventory numbers from an external system and display them on-screen alongside your product information, you can write REST API code in an Apex Class to do this.

* [**Properties**](#properties)

  Describes the properties to be configured when using an external datasource.
* [**Creating an Apex class**](#creating-an-apex-class)

  Before you can use an external datasource, you must write an Apex class. Your class must implement the `SBLD.DataSourceService.Fetchable` interface provided in the package.
* [**Example**](#example)

***

### Properties

There are several properties to be configured when using an external datasource.

<figure><img src="/files/0E4Bu945Zqqf7BmDfD3K" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Vj9s1aozZAm6hA9nXMxP" alt=""><figcaption><p>Apex class for an external datasource</p></figcaption></figure>

<figure><img src="/files/S6aMhroRkO1JQiWiW9lt" alt=""><figcaption><p>Flow for an external datasource</p></figcaption></figure>

<table><thead><tr><th width="163">Field name or area</th><th width="385">Description</th><th>Req.</th></tr></thead><tbody><tr><td>Select the type of external connection.</td><td><p>There are two ways to connect to external datasources.</p><ul><li>Apex - use an Apex class that <code>implements</code> the <code>SBLD.DataSourceService.Fetchable</code> interface.</li><li>Flow - use an automatically executing Flow.</li></ul></td><td><mark style="color:red;">✔️</mark></td></tr><tr><td>Enable</td><td>Enables the datasource. A disabled datasource will not be available when building custom lists.</td><td></td></tr><tr><td>Description</td><td>Provide a description of your datasource.</td><td></td></tr><tr><td>Key Field</td><td>Specifies which fields from the List object should be matched with fields from the datasource.</td><td><mark style="color:red;">✔️</mark></td></tr><tr><td>Parameters</td><td>If your datasource needs to be passed values from fields in the List object, select those fields here.</td><td></td></tr><tr><td>Input Variable</td><td>Select the parameter variables to pass to the Flow. If no parameters are required, leave unchecked.<br>💡 The displayed options are those marked "Available for input" in the Flow.<br><img src="/files/keUSl5nKubbz1pP25Ogf" alt=""></td><td></td></tr><tr><td>Output Variable</td><td>Select the variables to receive the results from the Flow.<br>💡 The displayed options are those marked "Available for output" in the Flow.<br><img src="/files/kN7muuWhPYUOh8fim8ZK" alt=""></td><td><mark style="color:red;">✔️</mark></td></tr></tbody></table>

### Creating an Apex class

Before you can use an external datasource, you must write an Apex class. Your class must implement the `SBLD.DataSourceService.Fetchable` interface provided in the package.

You must also implement the `execute()` method in your class.

{% code title="DataSourceServiceMock.cls" lineNumbers="true" fullWidth="false" %}

```java
global with sharing class DataSourceServiceMock implements SBLD.DataSourceService.Fetchable {
    /***
     * @description SBLD.DataSourceService.Fetchable execute() definition
     * @param param SBLD.DataSourceService.Parameter parameter type
     *              set by the datasource 
     * @return Map<Object, SObject>
     ****/
    global SBLD.DataSourceService.Result execute(SBLD.DataSourceService.Parameter param) {
        SBLD.DataSourceService.Result results = new SBLD.DataSourceService.Result();
        /**
         *  @method DataSourceService.Parameter gets()
         *  @param  String Parent, choose from Lookups (case insensitive)
         *  @return List<SObject>
         **/
        SObject parentRecord = null;
        List<SObject> lookupRecords = new List<SObject>();
        // Gets Parent-specific parameters.
        if(param.gets('parent')<>null && !param.gets('parent').isEmpty()) {
            parentRecord = param.gets('parent')[0];
        }
        // Gets Lookup-specific parameters.
        if(param.gets('lookup')<>null && !param.gets('lookup').isEmpty()) {
            listLookupParameters = param.gets('lookup');
        }
        /**
         * On success, sets the result to send back to SmallBuilder.
         **/
        for(SObject sobj : lookupRecords) {
            /**
             * Similarly to internal datasources, the Action maps a 
             * value from a datasource to a field in the List's underlying object.
             **/
            SBLD.DataSourceServiceAction action = new SBLD.DataSourceServiceAction();
            // 1. Set the value of the key from the External datasource
            action.setKeyValue(sobj.get('Id')); // Product Code
            // 2. Maps fields from the external datasource to fields in the List's underlying object.
            Map<String, Object> mapPopulatedField = sobj.getPopulatedFieldsAsMap();
            for(String fieldName : mapPopulatedField.keySet()) {
                action.putSourceToTargetField(mapPopulatedField.get(fieldName), fieldName);
            }
            // 3. Add an Action to DataSourceService.Result.
            results.addAction(action);
        }
        return results;
    }
}
```

{% endcode %}

You can get information from the Parent or Lookup objects through the `gets()` method in `SBLD.DataSourceService.Parameter`

{% code lineNumbers="true" %}

```apex
global SBLD.DataSourceService.Result execute(SBLD.DataSourceService.Parameter param) {
    SObject parentRecord = null;
    List<SObject> lookupRecords = new List<SObject>();
    // Gets Parent-specific parameters.
    if(param.gets('parent')<>null && !param.gets('parent').isEmpty()) {
        parentRecord = param.gets('parent')[0];
    }
    // Gets Lookup-specific parameters.
    if(param.gets('lookup')<>null && !param.gets('lookup').isEmpty()) {
        listLookupParameters = param.gets('lookup');
    }
    ...
}
```

{% endcode %}

To pass the result to the Line-Item Configurator, we use the class below.

### **SBLD.DataSourceServiceAction Class**

Specifies an Action for each line in the target (Lookup or Line-item). An Action is an operation that maps a DataSource value to a Lookup or Line-item field.

* **setKeyValue(Object keyValue)**\
  Sets the Key value to find the target record for the Lookup or Line-item.
* **putSourceToTargetField(Object sourceValue, String targetField)**\
  Assigns a data source value to a Lookup or Line-item field.

### **SBLD.DataSourceService.Result Class**

Adds the mapped Action to the return value.

* **addAction(SBLD.DataSourceServiceAction action)**\
  Adds an Action to the `SBLD.DataSourceService.Result` instance.

{% code lineNumbers="true" %}

```apex
...
SBLD.DataSourceService.Result result = new SBLD.DataSourceService.Result();
for(Object objResponse : listResponses) {
    Map<String, Object> mapResponse = (Map<String, Object>)objResponse;

    SBLD.DataSourceServiceAction action = new SBLD.DataSourceServiceAction();
    /**
     *  A value that matches the Key field in the DataSource
     *  External Server Key: itemCode,
     *  Lookup Key: ProductCode
     **/    action.setKeyValue(mapResponse.get('Id')); // Product Code
    // Populating a Lookup or Line-item field with a value from the External DataSoure
    action.putSourceToTargetField(mapResponse.get('inventory'), 'Inventory__c');
    // Add an Action to SBLD.DataSourceService.Result.
    result.addAction(action);
}
return result;
```

{% endcode %}

### Example

Under construction! Contact us if you need further help.
