Adding custom fields to application.yml

I am currently working on an application that requires me to add custom fields to application.yml.

As a simple example, suppose I wanted to alter the default shinyproxy config file to include a category field for each spec entry, like this:

specs:
  - id: 01_hello
    category: cat1
    display-name: Hello Application
    description: Application which demonstrates the basics of a Shiny app
    container-cmd: ["R", "-e", "shinyproxy::run_01_hello()"]
    container-image: openanalytics/shinyproxy-demo
    access-groups: [scientists, mathematicians]
  - id: 06_tabsets
    category: cat2
    container-cmd: ["R", "-e", "shinyproxy::run_06_tabsets()"]
    container-image: openanalytics/shinyproxy-demo
    access-groups: scientists

I have edited the ProxySpec.java model in the containerproxy dependency by adding

private String category;

...

public String getCategory() {
    return category;
}

public void setCategory(String category) {
    this.category = category;
}

...

public void copy(ProxySpec target) {
    ...
    target.setCategory(category);
    ...
}

and rebuilt the shinyproxy.jar file with the edited dependency. If I change getCategory() so that it returns one of the original data fields, i.e., id, then I can return that value so I know the issue is not with my build process. For some reason, it appears that the private data field is never being set. I have read through this documentation https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html and scoured the containerproxy repo, but can’t find any indication of what I’m missing here. If you can point me in the right direction it would be much appreciated.

Currently using shinyproxy-2.0.5 and containerproxy-0.6.0.

Here’s the full edited ProxySpec.java file:

/**
 * ContainerProxy
 *
 * Copyright (C) 2016-2018 Open Analytics
 *
 * ===========================================================================
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the Apache License as published by
 * The Apache Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Apache License for more details.
 *
 * You should have received a copy of the Apache License
 * along with this program.  If not, see <http://www.apache.org/licenses/>
 */
package eu.openanalytics.containerproxy.model.spec;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ProxySpec {

        private String id;
        private String category;
        private String displayName;
        private String description;
        private String logoURL;

        private ProxyAccessControl accessControl;
        private List<ContainerSpec> containerSpecs;
        private List<RuntimeSettingSpec> runtimeSettingSpecs;

        private Map<String, String> settings = new HashMap<>();

        public ProxySpec() {
                settings = new HashMap<>();
        }

        public String getId() {
                return id;
        }

        public void setId(String id) {
                this.id = id;
        }

        public String getCategory() {
                return category;
        }

        public void setCategory(String category) {
                this.category = category;
        }

        public String getDisplayName() {
                return displayName;
        }

        public void setDisplayName(String displayName) {
                this.displayName = displayName;
        }

        public String getDescription() {
                return description;
        }

        public void setDescription(String description) {
                this.description = description;
        }

        public String getLogoURL() {
                return logoURL;
        }

        public void setLogoURL(String logoURL) {
                this.logoURL = logoURL;
        }

        public ProxyAccessControl getAccessControl() {
                return accessControl;
        }

        public void setAccessControl(ProxyAccessControl accessControl) {
                this.accessControl = accessControl;
        }

        public List<ContainerSpec> getContainerSpecs() {
                return containerSpecs;
        }

        public void setContainerSpecs(List<ContainerSpec> containerSpecs) {
                this.containerSpecs = containerSpecs;
        }


        public List<RuntimeSettingSpec> getRuntimeSettingSpecs() {
                return runtimeSettingSpecs;
        }

        public void setRuntimeSettingSpecs(List<RuntimeSettingSpec> runtimeSettingSpecs) {
                this.runtimeSettingSpecs = runtimeSettingSpecs;
        }

        public Map<String, String> getSettings() {
                return settings;
        }

        public void setSettings(Map<String, String> settings) {
                this.settings = settings;
        }

        public void copy(ProxySpec target) {
                target.setId(id);
                target.setCategory(category);
                target.setDisplayName(displayName);
                target.setDescription(description);
                target.setLogoURL(logoURL);

                if (accessControl != null) {
                        if (target.getAccessControl() == null) target.setAccessControl(new ProxyAccessControl());
                        accessControl.copy(target.getAccessControl());
                }

                if (containerSpecs != null) {
                        if (target.getContainerSpecs() == null) target.setContainerSpecs(new ArrayList<>());
                        for (ContainerSpec spec: containerSpecs) {
                                ContainerSpec copy = new ContainerSpec();
                                spec.copy(copy);
                                target.getContainerSpecs().add(copy);
                        }
                }

                if (runtimeSettingSpecs != null) {
                        if (target.getRuntimeSettingSpecs() == null) target.setRuntimeSettingSpecs(new ArrayList<>());
                        for (RuntimeSettingSpec spec: runtimeSettingSpecs) {
                                RuntimeSettingSpec copy = new RuntimeSettingSpec();
                                spec.copy(copy);
                                target.getRuntimeSettingSpecs().add(copy);
                        }
                }

                if (settings != null) {
                        if (target.getSettings() == null) target.setSettings(new HashMap<>());
                        target.getSettings().putAll(settings);
                }
        }
}

Hi @jwmortensen,

ShinyProxy and ContainerProxy use a slightly different spec dialect.
The ShinyProxy version is more compact and convenient; there is a conversion taking place here that you will have to update as well: