# OPC-UA Device - Replacement for ConfigurationUILink

**URL:** <https://forum.inductiveautomation.com/t/opc-ua-device-replacement-for-configurationuilink/22775>\
**Category:** Ignition Early Access\
**Created:** [February 21, 2019, 6:26pm UTC](https://forum.inductiveautomation.com/t/opc-ua-device-replacement-for-configurationuilink/22775 "2019-02-21T18:26:11Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![chi](https://avatars.discourse-cdn.com/v4/letter/c/0ea827/32.png) [@chi](https://forum.inductiveautomation.com/u/chi)\
**Post date:** [February 21, 2019, 6:26pm UTC](https://forum.inductiveautomation.com/t/opc-ua-device-replacement-for-configurationuilink/22775/1 "2019-02-21T18:26:11Z")

</div>

In my driver module i used the deprecated? `xopc.driver` api. For Ignition 8 i am now converting to the new `opcua.server` api, but i can’t find a replacement for the configuration links (`com.inductiveautomation.xopc.driver.api.configuration.links.ConfigurationUILink`).

Can a developer please give me a hint how to implement custom settings pages with the new api?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [February 21, 2019, 6:30pm UTC](https://forum.inductiveautomation.com/t/opc-ua-device-replacement-for-configurationuilink/22775/2 "2019-02-21T18:30:14Z")

</div>

There’s no replacement right now.

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [February 21, 2019, 6:33pm UTC](https://forum.inductiveautomation.com/t/opc-ua-device-replacement-for-configurationuilink/22775/3 "2019-02-21T18:33:01Z")

</div>

It does look like the `DeviceType` can override `addRecordInstanceActions`, which is what the previous API used under the hood, but there’s no direct replacement yet.

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [February 21, 2019, 6:44pm UTC](https://forum.inductiveautomation.com/t/opc-ua-device-replacement-for-configurationuilink/22775/4 "2019-02-21T18:44:52Z")

</div>

Here’s a replacement:

```auto

private static class ConfigurationUIAction extends AbstractRecordInstanceAction<DeviceSettingsRecord> {

    private final ConfigurationUILink link;
    private final RecordModel<PersistentRecord> recordModel;

    private ConfigurationUIAction(
        String id,
        IConfigPage configPage,
        ConfigPanel parentPanel,
        DeviceSettingsRecord record,
        PersistentRecord subRecord,
        ConfigurationUILink link) {

        super(id, configPage, parentPanel, record);

        this.link = link;

        recordModel = new RecordModel<>(subRecord);
    }

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

        recordModel.detach();
    }

    @Override
    protected ConfigPanel createPanel(DeviceSettingsRecord record) {
        PersistentRecord subRecord = recordModel.getObject();
        return link.getConfigurationUI(getConfigPage(), getParentPanel(), subRecord, new ConfigCallback(record));
    }

    @Override
    public IModel getLabel() {
        return Model.of(link.getLinkText(getLocale()));
    }

    @Override
    protected String getCssClass() {
        return "";
    }
}

```

Then override in DeviceType:

```auto
@Override
public void addRecordInstanceActions(
    RepeatingView view,
    IConfigPage configPage,
    ConfigPanel parentPanel,
    PersistentRecord mainRecord,
    PersistentRecord subRecord) {

    driverType.getLinks().stream()
        .filter(link -> link instanceof ConfigurationUILink)
        .forEach(link -> {
            ConfigurationUIAction action = new ConfigurationUIAction(
                view.newChildId(),
                configPage,
                parentPanel,
                (DeviceSettingsRecord) mainRecord,
                subRecord,
                (ConfigurationUILink) link);

            view.add(action);
        });
}

```

---

<div class="post-metadata">

**Author:** ![chi](https://avatars.discourse-cdn.com/v4/letter/c/0ea827/32.png) [@chi](https://forum.inductiveautomation.com/u/chi)\
**Post date:** [February 21, 2019, 7:26pm UTC](https://forum.inductiveautomation.com/t/opc-ua-device-replacement-for-configurationuilink/22775/5 "2019-02-21T19:26:39Z")

</div>

Wow, you are fast!

Where do you import `ConfigCallback` from?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [February 21, 2019, 7:30pm UTC](https://forum.inductiveautomation.com/t/opc-ua-device-replacement-for-configurationuilink/22775/6 "2019-02-21T19:30:08Z")

</div>

> [@chi](#):
>
> Wow, you are fast!

I'm cheating and just copying old code 😉

> [@chi](#):
>
> Where do you import `ConfigCallback` from?

Oops, left that out:

```auto
private static class ConfigCallback implements ConfigurationUILink.Callback {

    private final String tableName;
    private final KeyValue key;

    private ConfigCallback(DeviceSettingsRecord parentRecord) {
        tableName = parentRecord.getMeta().getTableName();
        key = new KeyValue(parentRecord);
    }

    @Override
    public void save(PersistentRecord record) {
        GatewayContext context = <somehow get this>;

        context.getPersistenceInterface().save(record);

        if (tableName != null) {
            try {
                RecordMeta meta = (RecordMeta) context.getSchemaUpdater().findRecordMeta(tableName);
                PersistentRecord parentRecord = context.getPersistenceInterface().find(meta, key.getKeyValues());

                context.getPersistenceInterface().notifyRecordUpdated(parentRecord);
            } catch (Throwable t) {
                Logger.getLogger("ConfigCallback").warn("Error during notifyRecordUpdated().", t);
            }
        }
    }

}

```
