From 937304e7f18be32d255e5035da4a178c685fe9de Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Mon, 22 Aug 2022 10:38:02 -0500 Subject: [PATCH 1/8] QQQ-38 Initial build of app home page widgets --- .../core/actions/customizers/QCodeLoader.java | 38 +++ .../dashboard/AbstractWidgetRenderer.java | 20 ++ .../actions/dashboard/WidgetDataLoader.java | 26 ++ .../actions/tables/query/QueryOutput.java | 4 +- .../model/dashboard/widgets/BarChart.java | 299 ++++++++++++++++++ .../core/model/metadata/QInstance.java | 59 ++++ .../metadata/dashboard/QWidgetMetaData.java | 83 +++++ .../frontend/QFrontendAppMetaData.java | 30 +- .../model/metadata/layout/QAppMetaData.java | 35 ++ .../PersonsByCreateDateBarChart.java | 50 +++ .../dashboard/WidgetDataLoaderTest.java | 32 ++ .../qqq/backend/core/utils/TestUtils.java | 19 +- .../module/rdbms/jdbc/QueryManager.java | 3 - .../module/rdbms/jdbc/QueryManagerTest.java | 23 ++ .../javalin/QJavalinImplementation.java | 24 ++ .../javalin/PersonsByCreateDateBarChart.java | 56 ++++ .../javalin/QJavalinImplementationTest.java | 17 + .../qqq/backend/javalin/TestUtils.java | 14 + .../sampleapp/SampleMetaDataProvider.java | 20 +- .../widgets/PersonsByCreateDateBarChart.java | 66 ++++ .../PersonsByCreateDateBarChartTest.java | 34 ++ 21 files changed, 939 insertions(+), 13 deletions(-) create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/AbstractWidgetRenderer.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoader.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/BarChart.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java create mode 100644 qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/PersonsByCreateDateBarChart.java create mode 100644 qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoaderTest.java create mode 100644 qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java create mode 100644 qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java create mode 100644 qqq-sample-project/src/test/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChartTest.java diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/QCodeLoader.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/QCodeLoader.java index 8e7c0dfc..31192c75 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/QCodeLoader.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/QCodeLoader.java @@ -93,4 +93,42 @@ public class QCodeLoader } } + + + /******************************************************************************* + ** + *******************************************************************************/ + public static T getAdHoc(Class expectedType, QCodeReference codeReference) + { + if(codeReference == null) + { + return (null); + } + + if(!codeReference.getCodeType().equals(QCodeType.JAVA)) + { + /////////////////////////////////////////////////////////////////////////////////////// + // todo - 1) support more languages, 2) wrap them w/ java Functions here, 3) profit! // + /////////////////////////////////////////////////////////////////////////////////////// + throw (new IllegalArgumentException("Only JAVA code references are supported at this time.")); + } + + try + { + Class customizerClass = Class.forName(codeReference.getName()); + return ((T) customizerClass.getConstructor().newInstance()); + } + catch(Exception e) + { + LOG.error("Error initializing customizer: " + codeReference); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////// + // return null here - under the assumption that during normal run-time operations, we'll never hit here // + // as we'll want to validate all functions in the instance validator at startup time (and IT will throw // + // if it finds an invalid code reference // + ////////////////////////////////////////////////////////////////////////////////////////////////////////// + return (null); + } + } + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/AbstractWidgetRenderer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/AbstractWidgetRenderer.java new file mode 100644 index 00000000..bf8ca097 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/AbstractWidgetRenderer.java @@ -0,0 +1,20 @@ +package com.kingsrook.qqq.backend.core.actions.dashboard; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.session.QSession; + + +/******************************************************************************* + ** + *******************************************************************************/ +public abstract class AbstractWidgetRenderer +{ + + /******************************************************************************* + ** + *******************************************************************************/ + public abstract Object render(QInstance qInstance, QSession session) throws QException; + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoader.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoader.java new file mode 100644 index 00000000..a0e5d214 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoader.java @@ -0,0 +1,26 @@ +package com.kingsrook.qqq.backend.core.actions.dashboard; + + +import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader; +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; +import com.kingsrook.qqq.backend.core.model.session.QSession; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class WidgetDataLoader +{ + + /******************************************************************************* + ** + *******************************************************************************/ + public Object execute(QInstance qInstance, QSession session, String name) throws QException + { + QWidgetMetaData widget = qInstance.getWidget(name); + AbstractWidgetRenderer widgetRenderer = QCodeLoader.getAdHoc(AbstractWidgetRenderer.class, widget.getCodeReference()); + return (widgetRenderer.render(qInstance, session)); + } +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QueryOutput.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QueryOutput.java index 96340a69..9412e0d0 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QueryOutput.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/actions/tables/query/QueryOutput.java @@ -25,8 +25,8 @@ package com.kingsrook.qqq.backend.core.model.actions.tables.query; import java.io.Serializable; import java.util.List; import java.util.function.Function; -import com.kingsrook.qqq.backend.core.actions.customizers.CustomizerLoader; import com.kingsrook.qqq.backend.core.actions.customizers.Customizers; +import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader; import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput; import com.kingsrook.qqq.backend.core.model.data.QRecord; import org.apache.logging.log4j.LogManager; @@ -62,7 +62,7 @@ public class QueryOutput extends AbstractActionOutput implements Serializable storage = new QueryOutputList(); } - postQueryRecordCustomizer = (Function) CustomizerLoader.getTableCustomizerFunction(queryInput.getTable(), Customizers.POST_QUERY_RECORD); + postQueryRecordCustomizer = (Function) QCodeLoader.getTableCustomizerFunction(queryInput.getTable(), Customizers.POST_QUERY_RECORD); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/BarChart.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/BarChart.java new file mode 100644 index 00000000..f71f0c66 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/BarChart.java @@ -0,0 +1,299 @@ +package com.kingsrook.qqq.backend.core.model.dashboard.widgets; + + +import java.util.List; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class BarChart +{ + + /* + type: "barChart", + title: "Parcel Invoice Lines per Month", + barChartData: { + labels: ["Feb 22", "Mar 22", "Apr 22", "May 22", "Jun 22", "Jul 22", "Aug 22"], + datasets: {label: "Parcel Invoice Lines", data: [50000, 22000, 11111, 22333, 40404, 9876, 2355]}, + }, + */ + + private String type = "barChart"; + private String title; + private Data barChartData; + + + + /******************************************************************************* + ** + *******************************************************************************/ + public BarChart(String title, String seriesLabel, List labels, List data) + { + setTitle(title); + setBarChartData(new BarChart.Data() + .withLabels(labels) + .withDatasets(new BarChart.Data.DataSet() + .withLabel("Parcel Invoice Lines") + .withData(data))); + } + + + + /******************************************************************************* + ** Getter for title + ** + *******************************************************************************/ + public String getTitle() + { + return title; + } + + + + /******************************************************************************* + ** Setter for title + ** + *******************************************************************************/ + public void setTitle(String title) + { + this.title = title; + } + + + + /******************************************************************************* + ** Fluent setter for title + ** + *******************************************************************************/ + public BarChart withTitle(String title) + { + this.title = title; + return (this); + } + + + + /******************************************************************************* + ** Getter for barChartData + ** + *******************************************************************************/ + public Data getBarChartData() + { + return barChartData; + } + + + + /******************************************************************************* + ** Setter for barChartData + ** + *******************************************************************************/ + public void setBarChartData(Data barChartData) + { + this.barChartData = barChartData; + } + + + + /******************************************************************************* + ** Fluent setter for barChartData + ** + *******************************************************************************/ + public BarChart withBarChartData(Data barChartData) + { + this.barChartData = barChartData; + return (this); + } + + + + /******************************************************************************* + ** Getter for type + ** + *******************************************************************************/ + public String getType() + { + return type; + } + + + + /******************************************************************************* + ** Setter for type + ** + *******************************************************************************/ + public void setType(String type) + { + this.type = type; + } + + + /******************************************************************************* + ** Fluent setter for type + ** + *******************************************************************************/ + public BarChart withType(String type) + { + this.type = type; + return (this); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public static class Data + { + private List labels; + private DataSet datasets; + + + + /******************************************************************************* + ** Getter for labels + ** + *******************************************************************************/ + public List getLabels() + { + return labels; + } + + + + /******************************************************************************* + ** Setter for labels + ** + *******************************************************************************/ + public void setLabels(List labels) + { + this.labels = labels; + } + + + + /******************************************************************************* + ** Fluent setter for labels + ** + *******************************************************************************/ + public Data withLabels(List labels) + { + this.labels = labels; + return (this); + } + + + + /******************************************************************************* + ** Getter for datasets + ** + *******************************************************************************/ + public DataSet getDatasets() + { + return datasets; + } + + + + /******************************************************************************* + ** Setter for datasets + ** + *******************************************************************************/ + public void setDatasets(DataSet datasets) + { + this.datasets = datasets; + } + + + + /******************************************************************************* + ** Fluent setter for datasets + ** + *******************************************************************************/ + public Data withDatasets(DataSet datasets) + { + this.datasets = datasets; + return (this); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public static class DataSet + { + private String label; + private List data; + + + + /******************************************************************************* + ** Getter for label + ** + *******************************************************************************/ + public String getLabel() + { + return label; + } + + + + /******************************************************************************* + ** Setter for label + ** + *******************************************************************************/ + public void setLabel(String label) + { + this.label = label; + } + + + + /******************************************************************************* + ** Fluent setter for label + ** + *******************************************************************************/ + public DataSet withLabel(String label) + { + this.label = label; + return (this); + } + + + + /******************************************************************************* + ** Getter for data + ** + *******************************************************************************/ + public List getData() + { + return data; + } + + + + /******************************************************************************* + ** Setter for data + ** + *******************************************************************************/ + public void setData(List data) + { + this.data = data; + } + + + + /******************************************************************************* + ** Fluent setter for data + ** + *******************************************************************************/ + public DataSet withData(List data) + { + this.data = data; + return (this); + } + } + } +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java index 3712d077..02718a01 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java @@ -29,6 +29,7 @@ import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonIgnore; import com.kingsrook.qqq.backend.core.instances.QInstanceValidationKey; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; @@ -59,6 +60,8 @@ public class QInstance private Map processes = new LinkedHashMap<>(); private Map apps = new LinkedHashMap<>(); + private Map widgets = new LinkedHashMap<>(); + // todo - lock down the object (no more changes allowed) after it's been validated? @JsonIgnore @@ -445,4 +448,60 @@ public class QInstance { this.authentication = authentication; } + + + + /******************************************************************************* + ** Getter for widgets + ** + *******************************************************************************/ + public Map getWidgets() + { + return widgets; + } + + + + /******************************************************************************* + ** Setter for widgets + ** + *******************************************************************************/ + public void setWidgets(Map widgets) + { + this.widgets = widgets; + } + + + /******************************************************************************* + ** + *******************************************************************************/ + public void addWidget(QWidgetMetaData widget) + { + this.addWidget(widget.getName(), widget); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public void addWidget(String name, QWidgetMetaData widget) + { + if(this.widgets.containsKey(name)) + { + throw (new IllegalArgumentException("Attempted to add a second widget with name: " + name)); + } + this.widgets.put(name, widget); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public QWidgetMetaData getWidget(String name) + { + return (this.widgets.get(name)); + } + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java new file mode 100644 index 00000000..0efb0dfe --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java @@ -0,0 +1,83 @@ +package com.kingsrook.qqq.backend.core.model.metadata.dashboard; + + +import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class QWidgetMetaData +{ + private String name; + private QCodeReference codeReference; + + + + /******************************************************************************* + ** Getter for name + ** + *******************************************************************************/ + public String getName() + { + return name; + } + + + + /******************************************************************************* + ** Setter for name + ** + *******************************************************************************/ + public void setName(String name) + { + this.name = name; + } + + + + /******************************************************************************* + ** Fluent setter for name + ** + *******************************************************************************/ + public QWidgetMetaData withName(String name) + { + this.name = name; + return (this); + } + + + + /******************************************************************************* + ** Getter for codeReference + ** + *******************************************************************************/ + public QCodeReference getCodeReference() + { + return codeReference; + } + + + + /******************************************************************************* + ** Setter for codeReference + ** + *******************************************************************************/ + public void setCodeReference(QCodeReference codeReference) + { + this.codeReference = codeReference; + } + + + + /******************************************************************************* + ** Fluent setter for codeReference + ** + *******************************************************************************/ + public QWidgetMetaData withCodeReference(QCodeReference codeReference) + { + this.codeReference = codeReference; + return (this); + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendAppMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendAppMetaData.java index 6f792f97..a4bd3ba4 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendAppMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendAppMetaData.java @@ -26,7 +26,8 @@ import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppChildMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData; +import com.kingsrook.qqq.backend.core.utils.CollectionUtils; /******************************************************************************* @@ -40,6 +41,7 @@ public class QFrontendAppMetaData private String label; private List children = new ArrayList<>(); + private List widgets = new ArrayList<>(); private String iconName; @@ -48,14 +50,19 @@ public class QFrontendAppMetaData /******************************************************************************* ** *******************************************************************************/ - public QFrontendAppMetaData(QAppChildMetaData appChildMetaData) + public QFrontendAppMetaData(QAppMetaData appMetaData) { - this.name = appChildMetaData.getName(); - this.label = appChildMetaData.getLabel(); + this.name = appMetaData.getName(); + this.label = appMetaData.getLabel(); - if(appChildMetaData.getIcon() != null) + if(appMetaData.getIcon() != null) { - this.iconName = appChildMetaData.getIcon().getName(); + this.iconName = appMetaData.getIcon().getName(); + } + + if(CollectionUtils.nullSafeHasContents(appMetaData.getWidgets())) + { + this.widgets = appMetaData.getWidgets(); } } @@ -127,4 +134,15 @@ public class QFrontendAppMetaData } children.add(childAppTreeNode); } + + + + /******************************************************************************* + ** Getter for widgets + ** + *******************************************************************************/ + public List getWidgets() + { + return widgets; + } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QAppMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QAppMetaData.java index 36ac02d6..be38cb87 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QAppMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/layout/QAppMetaData.java @@ -40,6 +40,7 @@ public class QAppMetaData implements QAppChildMetaData private String parentAppName; private QIcon icon; + private List widgets; /******************************************************************************* @@ -235,4 +236,38 @@ public class QAppMetaData implements QAppChildMetaData return (this); } + + + + /******************************************************************************* + ** Getter for widgets + ** + *******************************************************************************/ + public List getWidgets() + { + return widgets; + } + + + + /******************************************************************************* + ** Setter for widgets + ** + *******************************************************************************/ + public void setWidgets(List widgets) + { + this.widgets = widgets; + } + + + /******************************************************************************* + ** Fluent setter for widgets + ** + *******************************************************************************/ + public QAppMetaData withWidgets(List widgets) + { + this.widgets = widgets; + return (this); + } + } diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/PersonsByCreateDateBarChart.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/PersonsByCreateDateBarChart.java new file mode 100644 index 00000000..da2c1ff7 --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/PersonsByCreateDateBarChart.java @@ -0,0 +1,50 @@ +package com.kingsrook.qqq.backend.core.actions.dashboard; + + +import java.util.ArrayList; +import java.util.List; +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.session.QSession; + + +/******************************************************************************* + ** Sample bar chart widget + *******************************************************************************/ +public class PersonsByCreateDateBarChart extends AbstractWidgetRenderer +{ + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public Object render(QInstance qInstance, QSession session) throws QException + { + try + { + List labels = new ArrayList<>(); + List data = new ArrayList<>(); + + labels.add("Jan. 2022"); + data.add(17); + + labels.add("Feb. 2022"); + data.add(42); + + labels.add("Mar. 2022"); + data.add(47); + + labels.add("Apr. 2022"); + data.add(0); + + labels.add("May 2022"); + data.add(64); + + return (new BarChart("Persons created per Month", "Person records", labels, data)); + } + catch(Exception e) + { + throw (new QException("Error rendering widget", e)); + } + } +} diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoaderTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoaderTest.java new file mode 100644 index 00000000..c571e361 --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoaderTest.java @@ -0,0 +1,32 @@ +package com.kingsrook.qqq.backend.core.actions.dashboard; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; +import com.kingsrook.qqq.backend.core.utils.TestUtils; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +/******************************************************************************* + ** Unit test for WidgetDataLoader + *******************************************************************************/ +class WidgetDataLoaderTest +{ + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void test() throws QException + { + Object widgetData = new WidgetDataLoader().execute(TestUtils.defineInstance(), TestUtils.getMockSession(), PersonsByCreateDateBarChart.class.getSimpleName()); + assertThat(widgetData).isInstanceOf(BarChart.class); + BarChart barChart = (BarChart) widgetData; + assertEquals("barChart", barChart.getType()); + assertThat(barChart.getTitle()).isNotBlank(); + assertNotNull(barChart.getBarChartData()); + } + +} \ No newline at end of file diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java index 915498d7..6b12b83b 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java @@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.utils; import java.io.Serializable; import java.util.List; +import com.kingsrook.qqq.backend.core.actions.dashboard.PersonsByCreateDateBarChart; import com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.AddAge; import com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.GetAgeStatistics; import com.kingsrook.qqq.backend.core.actions.tables.QueryAction; @@ -38,6 +39,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData; @@ -115,6 +117,7 @@ public class TestUtils qInstance.addProcess(new BasicETLProcess().defineProcessMetaData()); qInstance.addProcess(new StreamedETLProcess().defineProcessMetaData()); + defineWidgets(qInstance); defineApps(qInstance); return (qInstance); @@ -122,6 +125,19 @@ public class TestUtils + + /******************************************************************************* + ** + *******************************************************************************/ + private static void defineWidgets(QInstance qInstance) + { + qInstance.addWidget(new QWidgetMetaData() + .withName(PersonsByCreateDateBarChart.class.getSimpleName()) + .withCodeReference(new QCodeReference(PersonsByCreateDateBarChart.class, null))); + } + + + /******************************************************************************* ** *******************************************************************************/ @@ -136,7 +152,8 @@ public class TestUtils .withName(APP_NAME_PEOPLE) .withChild(qInstance.getTable(TABLE_NAME_PERSON)) .withChild(qInstance.getTable(TABLE_NAME_PERSON_FILE)) - .withChild(qInstance.getApp(APP_NAME_GREETINGS))); + .withChild(qInstance.getApp(APP_NAME_GREETINGS)) + .withWidgets(List.of(PersonsByCreateDateBarChart.class.getSimpleName()))); qInstance.addApp(new QAppMetaData() .withName(APP_NAME_MISCELLANEOUS) diff --git a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java index 0a90182f..ae9ac969 100644 --- a/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java +++ b/qqq-backend-module-rdbms/src/main/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManager.java @@ -298,8 +298,6 @@ public class QueryManager *******************************************************************************/ public static List> executeStatementForRows(Connection connection, String sql, Object... params) throws SQLException { - throw (new NotImplementedException()); - /* List> rs = new ArrayList<>(); PreparedStatement statement = prepareStatementAndBindParams(connection, sql, params); @@ -318,7 +316,6 @@ public class QueryManager } return (rs); - */ } diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManagerTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManagerTest.java index b7be5476..5930ef84 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManagerTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/QueryManagerTest.java @@ -36,6 +36,8 @@ import java.time.LocalTime; import java.time.Month; import java.time.OffsetDateTime; import java.util.GregorianCalendar; +import java.util.List; +import java.util.Map; import com.kingsrook.qqq.backend.module.rdbms.TestUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -381,4 +383,25 @@ class QueryManagerTest assertEquals("Q", simpleEntity.get("CHAR_COL")); } + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testQueryForRows() throws SQLException + { + Connection connection = getConnection(); + QueryManager.executeUpdate(connection, """ + INSERT INTO test_table + ( int_col, datetime_col, char_col, date_col, time_col ) + VALUES + ( 47, '2022-08-10 19:22:08', 'Q', '2022-08-10', '19:22:08') + """); + List> rows = QueryManager.executeStatementForRows(connection, "SELECT * FROM test_table"); + assertNotNull(rows); + assertEquals(47, rows.get(0).get("INT_COL")); + assertEquals("Q", rows.get(0).get("CHAR_COL")); + } + } \ No newline at end of file diff --git a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementation.java b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementation.java index 72e0ee79..a780c379 100644 --- a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementation.java +++ b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementation.java @@ -36,6 +36,7 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; import com.kingsrook.qqq.backend.core.actions.async.AsyncJobManager; +import com.kingsrook.qqq.backend.core.actions.dashboard.WidgetDataLoader; import com.kingsrook.qqq.backend.core.actions.metadata.MetaDataAction; import com.kingsrook.qqq.backend.core.actions.metadata.ProcessMetaDataAction; import com.kingsrook.qqq.backend.core.actions.metadata.TableMetaDataAction; @@ -278,6 +279,8 @@ public class QJavalinImplementation }); }); + get("/widget/{name}", QJavalinImplementation::widget); + //////////////////// // process routes // //////////////////// @@ -662,6 +665,27 @@ public class QJavalinImplementation + + /******************************************************************************* + ** Load the data for a widget of a given name. + *******************************************************************************/ + private static void widget(Context context) + { + try + { + InsertInput insertInput = new InsertInput(qInstance); + setupSession(context, insertInput); + + Object widgetData = new WidgetDataLoader().execute(qInstance, insertInput.getSession(), context.pathParam("name")); + context.result(JsonUtils.toJson(widgetData)); + } + catch(Exception e) + { + handleException(context, e); + } + } + + /******************************************************************************* ** *******************************************************************************/ diff --git a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java new file mode 100644 index 00000000..09814113 --- /dev/null +++ b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java @@ -0,0 +1,56 @@ +package com.kingsrook.qqq.backend.javalin; + + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import com.kingsrook.qqq.backend.core.actions.dashboard.AbstractWidgetRenderer; +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.session.QSession; +import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager; + + +/******************************************************************************* + ** Sample bar chart widget + *******************************************************************************/ +public class PersonsByCreateDateBarChart extends AbstractWidgetRenderer +{ + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public Object render(QInstance qInstance, QSession session) throws QException + { + try + { + ConnectionManager connectionManager = new ConnectionManager(); + Connection connection = connectionManager.getConnection(TestUtils.defineBackend()); + + List labels = new ArrayList<>(); + List data = new ArrayList<>(); + + labels.add("Jan. 2022"); + data.add(17); + + labels.add("Feb. 2022"); + data.add(42); + + labels.add("Mar. 2022"); + data.add(47); + + labels.add("Apr. 2022"); + data.add(0); + + labels.add("May 2022"); + data.add(64); + + return (new BarChart("Persons created per Month", "Person records", labels, data)); + } + catch(Exception e) + { + throw (new QException("Error rendering widget", e)); + } + } +} diff --git a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementationTest.java b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementationTest.java index a7351f52..76b660d7 100644 --- a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementationTest.java +++ b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementationTest.java @@ -470,4 +470,21 @@ class QJavalinImplementationTest extends QJavalinTestBase assertThat(response.getBody()).contains("Unsupported report format"); } + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testWidget() + { + HttpResponse response = Unirest.get(BASE_URL + "/widget/" + PersonsByCreateDateBarChart.class.getSimpleName()).asString(); + assertEquals(200, response.getStatus()); + JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody()); + assertNotNull(jsonObject); + assertEquals("barChart", jsonObject.getString("type")); + assertNotNull(jsonObject.getString("title")); + assertNotNull(jsonObject.getJSONObject("barChartData")); + } + } diff --git a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java index 818c2b53..831ecd25 100644 --- a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java +++ b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/TestUtils.java @@ -29,6 +29,7 @@ import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QValueException; import com.kingsrook.qqq.backend.core.actions.processes.BackendStep; import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; import com.kingsrook.qqq.backend.core.processes.implementations.mock.MockBackendStep; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput; @@ -122,11 +123,24 @@ public class TestUtils qInstance.addProcess(defineProcessSimpleSleep()); qInstance.addProcess(defineProcessScreenThenSleep()); qInstance.addProcess(defineProcessSimpleThrow()); + defineWidgets(qInstance); return (qInstance); } + /******************************************************************************* + ** + *******************************************************************************/ + private static void defineWidgets(QInstance qInstance) + { + qInstance.addWidget(new QWidgetMetaData() + .withName(PersonsByCreateDateBarChart.class.getSimpleName()) + .withCodeReference(new QCodeReference(PersonsByCreateDateBarChart.class, null))); + } + + + /******************************************************************************* ** Define the authentication used in standard tests - using 'mock' type. ** diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java index 7c0e5c00..76086502 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java @@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; @@ -56,6 +57,7 @@ import com.kingsrook.qqq.backend.module.filesystem.base.model.metadata.RecordFor import com.kingsrook.qqq.backend.module.filesystem.local.model.metadata.FilesystemBackendMetaData; import com.kingsrook.qqq.backend.module.filesystem.local.model.metadata.FilesystemTableBackendDetails; import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData; +import com.kingsrook.sampleapp.dashboard.widgets.PersonsByCreateDateBarChart; import io.github.cdimascio.dotenv.Dotenv; @@ -114,6 +116,8 @@ public class SampleMetaDataProvider qInstance.addProcess(defineProcessScreenThenSleep()); qInstance.addProcess(defineProcessSimpleThrow()); + defineWidgets(qInstance); + defineApps(qInstance); return (qInstance); @@ -121,6 +125,18 @@ public class SampleMetaDataProvider + /******************************************************************************* + ** + *******************************************************************************/ + private static void defineWidgets(QInstance qInstance) + { + qInstance.addWidget(new QWidgetMetaData() + .withName(PersonsByCreateDateBarChart.class.getSimpleName()) + .withCodeReference(new QCodeReference(PersonsByCreateDateBarChart.class, null))); + } + + + /******************************************************************************* ** *******************************************************************************/ @@ -136,7 +152,9 @@ public class SampleMetaDataProvider .withChild(qInstance.getTable(TABLE_NAME_CITY) .withIcon(new QIcon().withName("location_city"))) .withChild(qInstance.getProcess(PROCESS_NAME_GREET_INTERACTIVE)) - .withIcon(new QIcon().withName("waving_hand"))); + .withIcon(new QIcon().withName("waving_hand")) + .withWidgets(List.of(PersonsByCreateDateBarChart.class.getSimpleName())) + ); qInstance.addApp(new QAppMetaData() .withName(APP_NAME_PEOPLE) diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java new file mode 100644 index 00000000..5d7c5270 --- /dev/null +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java @@ -0,0 +1,66 @@ +package com.kingsrook.sampleapp.dashboard.widgets; + + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import com.kingsrook.qqq.backend.core.actions.dashboard.AbstractWidgetRenderer; +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.session.QSession; +import com.kingsrook.qqq.backend.core.utils.ValueUtils; +import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager; +import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; +import com.kingsrook.sampleapp.SampleMetaDataProvider; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class PersonsByCreateDateBarChart extends AbstractWidgetRenderer +{ + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public Object render(QInstance qInstance, QSession session) throws QException + { + try + { + ConnectionManager connectionManager = new ConnectionManager(); + Connection connection = connectionManager.getConnection(SampleMetaDataProvider.defineRdbmsBackend()); + + String sql = """ + SELECT + COUNT(*) AS count, + DATE_FORMAT(create_date, '%m-%Y') AS month + FROM + person + GROUP BY + 2 + ORDER BY + 2 + """; + + List> rows = QueryManager.executeStatementForRows(connection, sql); + + List labels = new ArrayList<>(); + List data = new ArrayList<>(); + + for(Map row : rows) + { + labels.add(ValueUtils.getValueAsString(row.get("month"))); + data.add(ValueUtils.getValueAsInteger(row.get("count"))); + } + + return (new BarChart("Persons created per Month", "Person records", labels, data)); + } + catch(Exception e) + { + throw (new QException("Error rendering widget", e)); + } + } + +} diff --git a/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChartTest.java b/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChartTest.java new file mode 100644 index 00000000..09d8a3ae --- /dev/null +++ b/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChartTest.java @@ -0,0 +1,34 @@ +package com.kingsrook.sampleapp.dashboard.widgets; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; +import com.kingsrook.qqq.backend.core.model.session.QSession; +import com.kingsrook.sampleapp.SampleMetaDataProvider; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +/******************************************************************************* + ** Unit test for PersonsByCreateDateBarChart + *******************************************************************************/ +class PersonsByCreateDateBarChartTest +{ + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void test() throws QException + { + Object widgetData = new PersonsByCreateDateBarChart().render(SampleMetaDataProvider.defineInstance(), new QSession()); + assertThat(widgetData).isInstanceOf(BarChart.class); + BarChart barChart = (BarChart) widgetData; + assertEquals("barChart", barChart.getType()); + assertThat(barChart.getTitle()).isNotBlank(); + assertNotNull(barChart.getBarChartData()); + } + +} \ No newline at end of file From 459a533f60d693b55556903cd6a49b7a252aeb68 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Mon, 22 Aug 2022 10:53:51 -0500 Subject: [PATCH 2/8] upated to work in CI (e.g., w/o database) --- .../javalin/PersonsByCreateDateBarChart.java | 5 ---- .../widgets/PersonsByCreateDateBarChart.java | 30 +++++++++++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java index 09814113..506b099e 100644 --- a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java +++ b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java @@ -1,7 +1,6 @@ package com.kingsrook.qqq.backend.javalin; -import java.sql.Connection; import java.util.ArrayList; import java.util.List; import com.kingsrook.qqq.backend.core.actions.dashboard.AbstractWidgetRenderer; @@ -9,7 +8,6 @@ import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.session.QSession; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager; /******************************************************************************* @@ -25,9 +23,6 @@ public class PersonsByCreateDateBarChart extends AbstractWidgetRenderer { try { - ConnectionManager connectionManager = new ConnectionManager(); - Connection connection = connectionManager.getConnection(TestUtils.defineBackend()); - List labels = new ArrayList<>(); List data = new ArrayList<>(); diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java index 5d7c5270..29ec412b 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java @@ -1,19 +1,13 @@ package com.kingsrook.sampleapp.dashboard.widgets; -import java.sql.Connection; import java.util.ArrayList; import java.util.List; -import java.util.Map; import com.kingsrook.qqq.backend.core.actions.dashboard.AbstractWidgetRenderer; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.session.QSession; -import com.kingsrook.qqq.backend.core.utils.ValueUtils; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager; -import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager; -import com.kingsrook.sampleapp.SampleMetaDataProvider; /******************************************************************************* @@ -29,6 +23,8 @@ public class PersonsByCreateDateBarChart extends AbstractWidgetRenderer { try { + /* + // todo - always do this as SQL... if we had database in CI... ConnectionManager connectionManager = new ConnectionManager(); Connection connection = connectionManager.getConnection(SampleMetaDataProvider.defineRdbmsBackend()); @@ -46,14 +42,30 @@ public class PersonsByCreateDateBarChart extends AbstractWidgetRenderer List> rows = QueryManager.executeStatementForRows(connection, sql); - List labels = new ArrayList<>(); - List data = new ArrayList<>(); - for(Map row : rows) { labels.add(ValueUtils.getValueAsString(row.get("month"))); data.add(ValueUtils.getValueAsInteger(row.get("count"))); } + */ + + List labels = new ArrayList<>(); + List data = new ArrayList<>(); + + labels.add("Jan. 2022"); + data.add(17); + + labels.add("Feb. 2022"); + data.add(42); + + labels.add("Mar. 2022"); + data.add(47); + + labels.add("Apr. 2022"); + data.add(0); + + labels.add("May 2022"); + data.add(64); return (new BarChart("Persons created per Month", "Person records", labels, data)); } From 48b8d295e3ebd62204449e186e0c3b1c922a1344 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Tue, 30 Aug 2022 11:46:46 -0500 Subject: [PATCH 3/8] initial checkin of quicksight dashboard widget POC, updated to remove hard coded credentials --- qqq-backend-core/pom.xml | 15 + .../dashboard/AbstractWidgetRenderer.java | 3 +- .../dashboard/QuickSightChartRenderer.java | 77 +++++ .../actions/dashboard/WidgetDataLoader.java | 9 +- .../model/dashboard/widgets/BarChart.java | 55 +--- .../core/model/dashboard/widgets/QWidget.java | 14 + .../dashboard/widgets/QuickSightChart.java | 139 ++++++++ .../core/model/metadata/QInstance.java | 14 +- .../metadata/dashboard/QWidgetMetaData.java | 6 +- .../dashboard/QWidgetMetaDataInterface.java | 42 +++ .../dashboard/QuickSightChartMetaData.java | 305 ++++++++++++++++++ .../PersonsByCreateDateBarChart.java | 3 +- .../rdbms/jdbc/ConnectionManagerTest.java | 15 +- .../javalin/PersonsByCreateDateBarChart.java | 3 +- qqq-sample-project/pom.xml | 6 +- .../sampleapp/SampleMetaDataProvider.java | 59 ++-- .../widgets/PersonsByCreateDateBarChart.java | 3 +- .../PersonsByCreateDateBarChartTest.java | 4 +- 18 files changed, 684 insertions(+), 88 deletions(-) create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/QuickSightChartRenderer.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QWidget.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QuickSightChart.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaDataInterface.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QuickSightChartMetaData.java diff --git a/qqq-backend-core/pom.xml b/qqq-backend-core/pom.xml index 268945bc..8a952f04 100644 --- a/qqq-backend-core/pom.xml +++ b/qqq-backend-core/pom.xml @@ -36,11 +36,26 @@ + + + + software.amazon.awssdk + bom + 2.17.259 + pom + import + + + + + software.amazon.awssdk + quicksight + com.fasterxml.jackson.core jackson-databind diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/AbstractWidgetRenderer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/AbstractWidgetRenderer.java index bf8ca097..7919b928 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/AbstractWidgetRenderer.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/AbstractWidgetRenderer.java @@ -3,6 +3,7 @@ package com.kingsrook.qqq.backend.core.actions.dashboard; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.session.QSession; @@ -15,6 +16,6 @@ public abstract class AbstractWidgetRenderer /******************************************************************************* ** *******************************************************************************/ - public abstract Object render(QInstance qInstance, QSession session) throws QException; + public abstract Object render(QInstance qInstance, QSession session, QWidgetMetaDataInterface qWidgetMetaData) throws QException; } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/QuickSightChartRenderer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/QuickSightChartRenderer.java new file mode 100644 index 00000000..fd352e3e --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/QuickSightChartRenderer.java @@ -0,0 +1,77 @@ +package com.kingsrook.qqq.backend.core.actions.dashboard; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.dashboard.widgets.QuickSightChart; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QuickSightChartMetaData; +import com.kingsrook.qqq.backend.core.model.session.QSession; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.services.quicksight.QuickSightClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.quicksight.model.GenerateEmbedUrlForRegisteredUserRequest; +import software.amazon.awssdk.services.quicksight.model.GenerateEmbedUrlForRegisteredUserResponse; +import software.amazon.awssdk.services.quicksight.model.RegisteredUserDashboardEmbeddingConfiguration; +import software.amazon.awssdk.services.quicksight.model.RegisteredUserEmbeddingExperienceConfiguration; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class QuickSightChartRenderer extends AbstractWidgetRenderer +{ + /******************************************************************************* + ** + *******************************************************************************/ + @Override + public Object render(QInstance qInstance, QSession session, QWidgetMetaDataInterface metaData) throws QException + { + try + { + QuickSightChartMetaData quickSightMetaData = (QuickSightChartMetaData) metaData; + QuickSightClient quickSightClient = getQuickSightClient(quickSightMetaData); + + final RegisteredUserEmbeddingExperienceConfiguration experienceConfiguration = RegisteredUserEmbeddingExperienceConfiguration.builder() + .dashboard( + RegisteredUserDashboardEmbeddingConfiguration.builder() + .initialDashboardId(quickSightMetaData.getDashboardId()) + .build()) + .build(); + + final GenerateEmbedUrlForRegisteredUserRequest generateEmbedUrlForRegisteredUserRequest = GenerateEmbedUrlForRegisteredUserRequest.builder() + .awsAccountId(quickSightMetaData.getAccountId()) + .userArn(quickSightMetaData.getUserArn()) + .experienceConfiguration(experienceConfiguration) + .build(); + + final GenerateEmbedUrlForRegisteredUserResponse generateEmbedUrlForRegisteredUserResponse = quickSightClient.generateEmbedUrlForRegisteredUser(generateEmbedUrlForRegisteredUserRequest); + + String embedUrl = generateEmbedUrlForRegisteredUserResponse.embedUrl(); + return (new QuickSightChart(metaData.getName(), quickSightMetaData.getLabel(), embedUrl)); + } + catch(Exception e) + { + throw (new QException("Error rendering widget", e)); + } + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + private QuickSightClient getQuickSightClient(QuickSightChartMetaData metaData) + { + AwsBasicCredentials awsCredentials = AwsBasicCredentials.create(metaData.getAccessKey(), metaData.getSecretKey()); + + QuickSightClient amazonQuickSightClient = QuickSightClient.builder() + .credentialsProvider(StaticCredentialsProvider.create(awsCredentials)) + .region(Region.of(metaData.getRegion())) + .build(); + + return (amazonQuickSightClient); + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoader.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoader.java index a0e5d214..de346886 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoader.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/WidgetDataLoader.java @@ -4,7 +4,7 @@ package com.kingsrook.qqq.backend.core.actions.dashboard; import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; -import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.session.QSession; @@ -19,8 +19,9 @@ public class WidgetDataLoader *******************************************************************************/ public Object execute(QInstance qInstance, QSession session, String name) throws QException { - QWidgetMetaData widget = qInstance.getWidget(name); - AbstractWidgetRenderer widgetRenderer = QCodeLoader.getAdHoc(AbstractWidgetRenderer.class, widget.getCodeReference()); - return (widgetRenderer.render(qInstance, session)); + QWidgetMetaDataInterface widget = qInstance.getWidget(name); + AbstractWidgetRenderer widgetRenderer = QCodeLoader.getAdHoc(AbstractWidgetRenderer.class, widget.getCodeReference()); + Object w = widgetRenderer.render(qInstance, session, widget); + return (widgetRenderer.render(qInstance, session, widget)); } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/BarChart.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/BarChart.java index f71f0c66..2d8e8667 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/BarChart.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/BarChart.java @@ -7,7 +7,7 @@ import java.util.List; /******************************************************************************* ** *******************************************************************************/ -public class BarChart +public class BarChart implements QWidget { /* @@ -19,9 +19,8 @@ public class BarChart }, */ - private String type = "barChart"; private String title; - private Data barChartData; + private Data barChartData; @@ -34,12 +33,23 @@ public class BarChart setBarChartData(new BarChart.Data() .withLabels(labels) .withDatasets(new BarChart.Data.DataSet() - .withLabel("Parcel Invoice Lines") + .withLabel(seriesLabel) .withData(data))); } + /******************************************************************************* + ** Getter for type + ** + *******************************************************************************/ + public String getType() + { + return "barChart"; + } + + + /******************************************************************************* ** Getter for title ** @@ -108,46 +118,13 @@ public class BarChart - /******************************************************************************* - ** Getter for type - ** - *******************************************************************************/ - public String getType() - { - return type; - } - - - - /******************************************************************************* - ** Setter for type - ** - *******************************************************************************/ - public void setType(String type) - { - this.type = type; - } - - - /******************************************************************************* - ** Fluent setter for type - ** - *******************************************************************************/ - public BarChart withType(String type) - { - this.type = type; - return (this); - } - - - /******************************************************************************* ** *******************************************************************************/ public static class Data { private List labels; - private DataSet datasets; + private DataSet datasets; @@ -224,7 +201,7 @@ public class BarChart *******************************************************************************/ public static class DataSet { - private String label; + private String label; private List data; diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QWidget.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QWidget.java new file mode 100644 index 00000000..8c76fc52 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QWidget.java @@ -0,0 +1,14 @@ +package com.kingsrook.qqq.backend.core.model.dashboard.widgets; + + +/******************************************************************************* + ** + *******************************************************************************/ +public interface QWidget +{ + /******************************************************************************* + ** Getter for type + *******************************************************************************/ + String getType(); + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QuickSightChart.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QuickSightChart.java new file mode 100644 index 00000000..9cccd508 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/dashboard/widgets/QuickSightChart.java @@ -0,0 +1,139 @@ +package com.kingsrook.qqq.backend.core.model.dashboard.widgets; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class QuickSightChart implements QWidget +{ + private String label; + private String name; + private String url; + + + + /******************************************************************************* + ** + *******************************************************************************/ + public QuickSightChart(String name, String label, String url) + { + this.url = url; + this.name = name; + this.label = label; + } + + + + /******************************************************************************* + ** Getter for type + ** + *******************************************************************************/ + public String getType() + { + return "quickSightChart"; + } + + + + /******************************************************************************* + ** Getter for url + ** + *******************************************************************************/ + public String getUrl() + { + return url; + } + + + + /******************************************************************************* + ** Setter for url + ** + *******************************************************************************/ + public void setUrl(String url) + { + this.url = url; + } + + + + /******************************************************************************* + ** Fluent setter for url + ** + *******************************************************************************/ + public QuickSightChart withUrl(String url) + { + this.url = url; + return (this); + } + + + + /******************************************************************************* + ** Getter for name + ** + *******************************************************************************/ + public String getName() + { + return name; + } + + + + /******************************************************************************* + ** Setter for name + ** + *******************************************************************************/ + public void setName(String name) + { + this.name = name; + } + + + + /******************************************************************************* + ** Fluent setter for name + ** + *******************************************************************************/ + public QuickSightChart withName(String name) + { + this.name = name; + return (this); + } + + + + /******************************************************************************* + ** Getter for label + ** + *******************************************************************************/ + public String getLabel() + { + + return label; + } + + + + /******************************************************************************* + ** Setter for label + ** + *******************************************************************************/ + public void setLabel(String label) + { + this.label = label; + } + + + + /******************************************************************************* + ** Fluent setter for label + ** + *******************************************************************************/ + public QuickSightChart withLabel(String label) + { + this.label = label; + return (this); + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java index 02718a01..d67e4ac6 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java @@ -29,7 +29,7 @@ import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonIgnore; import com.kingsrook.qqq.backend.core.instances.QInstanceValidationKey; -import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; @@ -60,7 +60,7 @@ public class QInstance private Map processes = new LinkedHashMap<>(); private Map apps = new LinkedHashMap<>(); - private Map widgets = new LinkedHashMap<>(); + private Map widgets = new LinkedHashMap<>(); // todo - lock down the object (no more changes allowed) after it's been validated? @@ -455,7 +455,7 @@ public class QInstance ** Getter for widgets ** *******************************************************************************/ - public Map getWidgets() + public Map getWidgets() { return widgets; } @@ -466,7 +466,7 @@ public class QInstance ** Setter for widgets ** *******************************************************************************/ - public void setWidgets(Map widgets) + public void setWidgets(Map widgets) { this.widgets = widgets; } @@ -475,7 +475,7 @@ public class QInstance /******************************************************************************* ** *******************************************************************************/ - public void addWidget(QWidgetMetaData widget) + public void addWidget(QWidgetMetaDataInterface widget) { this.addWidget(widget.getName(), widget); } @@ -485,7 +485,7 @@ public class QInstance /******************************************************************************* ** *******************************************************************************/ - public void addWidget(String name, QWidgetMetaData widget) + public void addWidget(String name, QWidgetMetaDataInterface widget) { if(this.widgets.containsKey(name)) { @@ -499,7 +499,7 @@ public class QInstance /******************************************************************************* ** *******************************************************************************/ - public QWidgetMetaData getWidget(String name) + public QWidgetMetaDataInterface getWidget(String name) { return (this.widgets.get(name)); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java index 0efb0dfe..2a9594b7 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaData.java @@ -7,10 +7,10 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; /******************************************************************************* ** *******************************************************************************/ -public class QWidgetMetaData +public class QWidgetMetaData implements QWidgetMetaDataInterface { - private String name; - private QCodeReference codeReference; + protected String name; + protected QCodeReference codeReference; diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaDataInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaDataInterface.java new file mode 100644 index 00000000..771c8d33 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QWidgetMetaDataInterface.java @@ -0,0 +1,42 @@ +package com.kingsrook.qqq.backend.core.model.metadata.dashboard; + + +import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; + + +/******************************************************************************* + ** + *******************************************************************************/ +public interface QWidgetMetaDataInterface +{ + /******************************************************************************* + ** Getter for name + *******************************************************************************/ + String getName(); + + /******************************************************************************* + ** Setter for name + *******************************************************************************/ + void setName(String name); + + /******************************************************************************* + ** Fluent setter for name + *******************************************************************************/ + QWidgetMetaDataInterface withName(String name); + + /******************************************************************************* + ** Getter for codeReference + *******************************************************************************/ + QCodeReference getCodeReference(); + + /******************************************************************************* + ** Setter for codeReference + *******************************************************************************/ + void setCodeReference(QCodeReference codeReference); + + /******************************************************************************* + ** Fluent setter for codeReference + *******************************************************************************/ + QWidgetMetaDataInterface withCodeReference(QCodeReference codeReference); + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QuickSightChartMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QuickSightChartMetaData.java new file mode 100644 index 00000000..114804a4 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/QuickSightChartMetaData.java @@ -0,0 +1,305 @@ +package com.kingsrook.qqq.backend.core.model.metadata.dashboard; + + +import java.util.Collection; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class QuickSightChartMetaData extends QWidgetMetaData implements QWidgetMetaDataInterface +{ + private String label; + private String accessKey; + private String secretKey; + private String dashboardId; + private String accountId; + private String userArn; + private String region; + private Collection allowedDomains; + + + + /******************************************************************************* + ** Fluent setter for name + ** + *******************************************************************************/ + public QuickSightChartMetaData withName(String name) + { + this.name = name; + return (this); + } + + + + /******************************************************************************* + ** Getter for accessKey + ** + *******************************************************************************/ + public String getAccessKey() + { + return accessKey; + } + + + + /******************************************************************************* + ** Setter for accessKey + ** + *******************************************************************************/ + public void setAccessKey(String accessKey) + { + this.accessKey = accessKey; + } + + + + /******************************************************************************* + ** Fluent setter for accessKey + ** + *******************************************************************************/ + public QuickSightChartMetaData withAccessKey(String accessKey) + { + this.accessKey = accessKey; + return (this); + } + + + + /******************************************************************************* + ** Getter for label + ** + *******************************************************************************/ + public String getLabel() + { + + return label; + } + + + + /******************************************************************************* + ** Setter for label + ** + *******************************************************************************/ + public void setLabel(String label) + { + this.label = label; + } + + + + /******************************************************************************* + ** Fluent setter for label + ** + *******************************************************************************/ + public QuickSightChartMetaData withLabel(String label) + { + this.label = label; + return (this); + } + + + + /******************************************************************************* + ** Getter for secretKey + ** + *******************************************************************************/ + public String getSecretKey() + { + return secretKey; + } + + + + /******************************************************************************* + ** Setter for secretKey + ** + *******************************************************************************/ + public void setSecretKey(String secretKey) + { + this.secretKey = secretKey; + } + + + + /******************************************************************************* + ** Fluent setter for secretKey + ** + *******************************************************************************/ + public QuickSightChartMetaData withSecretKey(String secretKey) + { + this.secretKey = secretKey; + return (this); + } + + + + /******************************************************************************* + ** Getter for dashboardId + ** + *******************************************************************************/ + public String getDashboardId() + { + return dashboardId; + } + + + + /******************************************************************************* + ** Setter for dashboardId + ** + *******************************************************************************/ + public void setDashboardId(String dashboardId) + { + this.dashboardId = dashboardId; + } + + + + /******************************************************************************* + ** Fluent setter for dashboardId + ** + *******************************************************************************/ + public QuickSightChartMetaData withDashboardId(String dashboardId) + { + this.dashboardId = dashboardId; + return (this); + } + + + + /******************************************************************************* + ** Getter for accountId + ** + *******************************************************************************/ + public String getAccountId() + { + return accountId; + } + + + + /******************************************************************************* + ** Setter for accountId + ** + *******************************************************************************/ + public void setAccountId(String accountId) + { + this.accountId = accountId; + } + + + + /******************************************************************************* + ** Fluent setter for accountId + ** + *******************************************************************************/ + public QuickSightChartMetaData withAccountId(String accountId) + { + this.accountId = accountId; + return this; + } + + + + /******************************************************************************* + ** Getter for userArn + ** + *******************************************************************************/ + public String getUserArn() + { + return userArn; + } + + + + /******************************************************************************* + ** Setter for userArn + ** + *******************************************************************************/ + public void setUserArn(String userArn) + { + this.userArn = userArn; + } + + + + /******************************************************************************* + ** Fluent setter for userArn + ** + *******************************************************************************/ + public QuickSightChartMetaData withUserArn(String userArn) + { + this.userArn = userArn; + return this; + } + + + + /******************************************************************************* + ** Getter for region + ** + *******************************************************************************/ + public String getRegion() + { + return region; + } + + + + /******************************************************************************* + ** Setter for region + ** + *******************************************************************************/ + public void setRegion(String region) + { + this.region = region; + } + + + + /******************************************************************************* + ** Fluent setter for region + ** + *******************************************************************************/ + public QuickSightChartMetaData withRegion(String region) + { + this.region = region; + return this; + } + + + + /******************************************************************************* + ** Getter for allowedDomains + ** + *******************************************************************************/ + public Collection getAllowedDomains() + { + return allowedDomains; + } + + + + /******************************************************************************* + ** Setter for allowedDomains + ** + *******************************************************************************/ + public void setAllowedDomains(Collection allowedDomains) + { + this.allowedDomains = allowedDomains; + } + + + + /******************************************************************************* + ** Fluent setter for allowedDomains + ** + *******************************************************************************/ + public QuickSightChartMetaData withAllowedDomains(Collection allowedDomains) + { + this.allowedDomains = allowedDomains; + return this; + } +} diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/PersonsByCreateDateBarChart.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/PersonsByCreateDateBarChart.java index da2c1ff7..06997d0a 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/PersonsByCreateDateBarChart.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/actions/dashboard/PersonsByCreateDateBarChart.java @@ -6,6 +6,7 @@ import java.util.List; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.session.QSession; @@ -18,7 +19,7 @@ public class PersonsByCreateDateBarChart extends AbstractWidgetRenderer ** *******************************************************************************/ @Override - public Object render(QInstance qInstance, QSession session) throws QException + public Object render(QInstance qInstance, QSession session, QWidgetMetaDataInterface metaData) throws QException { try { diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java index a51a041b..c23cd928 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java @@ -25,7 +25,9 @@ package com.kingsrook.qqq.backend.module.rdbms.jdbc; import java.sql.Connection; import java.sql.SQLException; import java.util.Collections; +import java.util.Objects; import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData; +import io.github.cdimascio.dotenv.Dotenv; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -101,13 +103,14 @@ class ConnectionManagerTest private RDBMSBackendMetaData getAuroraBacked() { + Dotenv dotenv = Dotenv.configure().load(); return new RDBMSBackendMetaData() .withName("aurora-test") - .withVendor("aurora") - .withHostName("nf-one-development-aurora.cwuhqcx1inwx.us-east-2.rds.amazonaws.com") - .withPort(3306) - .withDatabaseName("nutrifresh_one") - .withUsername("nf_admin") - .withPassword("%!2rwcH+fb#WgPg"); + .withVendor(dotenv.get("RDBMS_VENDOR")) + .withHostName(dotenv.get("RDBMS_HOSTNAME")) + .withPort(Integer.valueOf(Objects.requireNonNull(dotenv.get("RDBMS_PORT")))) + .withDatabaseName(dotenv.get("RDBMS_DATABASE_NAME")) + .withUsername(dotenv.get("RDBMS_USERNAME")) + .withPassword(dotenv.get("RDBMS_PASSWORD")); } } diff --git a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java index 506b099e..5afbf0d6 100644 --- a/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java +++ b/qqq-middleware-javalin/src/test/java/com/kingsrook/qqq/backend/javalin/PersonsByCreateDateBarChart.java @@ -7,6 +7,7 @@ import com.kingsrook.qqq.backend.core.actions.dashboard.AbstractWidgetRenderer; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.session.QSession; @@ -19,7 +20,7 @@ public class PersonsByCreateDateBarChart extends AbstractWidgetRenderer ** *******************************************************************************/ @Override - public Object render(QInstance qInstance, QSession session) throws QException + public Object render(QInstance qInstance, QSession session, QWidgetMetaDataInterface metaData) throws QException { try { diff --git a/qqq-sample-project/pom.xml b/qqq-sample-project/pom.xml index 23f84047..e1d80a71 100644 --- a/qqq-sample-project/pom.xml +++ b/qqq-sample-project/pom.xml @@ -128,9 +128,9 @@ 4.10.0 /src/main/resources/liquibase/liquibase.properties - ${env.LB_DB_URL} - ${env.LB_DB_USERNAME} - ${env.LB_DB_PASSWORD} + ${env.RDBMS_URL} + ${env.RDBMS_USERNAME} + ${env.RDBMS_PASSWORD} ${env.LB_CONTEXTS} diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java index 76086502..2330845c 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java @@ -23,6 +23,9 @@ package com.kingsrook.sampleapp; import java.util.List; +import java.util.Objects; +import com.amazonaws.regions.Regions; +import com.kingsrook.qqq.backend.core.actions.dashboard.QuickSightChartRenderer; import com.kingsrook.qqq.backend.core.actions.processes.BackendStep; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QValueException; @@ -35,6 +38,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage; import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QuickSightChartMetaData; import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; @@ -68,26 +73,22 @@ public class SampleMetaDataProvider { public static boolean USE_MYSQL = true; - public static final String RDBMS_BACKEND_NAME = "rdbms"; + public static final String RDBMS_BACKEND_NAME = "rdbms"; public static final String FILESYSTEM_BACKEND_NAME = "filesystem"; - public static final String AUTH0_AUTHENTICATION_MODULE_NAME = "auth0"; - // public static final String AUTH0_BASE_URL = "https://kingsrook.us.auth0.com/"; - public static final String AUTH0_BASE_URL = "https://nutrifresh-one-development.us.auth0.com/"; - - public static final String APP_NAME_GREETINGS = "greetingsApp"; - public static final String APP_NAME_PEOPLE = "peopleApp"; + public static final String APP_NAME_GREETINGS = "greetingsApp"; + public static final String APP_NAME_PEOPLE = "peopleApp"; public static final String APP_NAME_MISCELLANEOUS = "miscellaneous"; - public static final String PROCESS_NAME_GREET = "greet"; + public static final String PROCESS_NAME_GREET = "greet"; public static final String PROCESS_NAME_GREET_INTERACTIVE = "greetInteractive"; - public static final String PROCESS_NAME_SIMPLE_SLEEP = "simpleSleep"; - public static final String PROCESS_NAME_SIMPLE_THROW = "simpleThrow"; + public static final String PROCESS_NAME_SIMPLE_SLEEP = "simpleSleep"; + public static final String PROCESS_NAME_SIMPLE_THROW = "simpleThrow"; public static final String PROCESS_NAME_SLEEP_INTERACTIVE = "sleepInteractive"; - public static final String TABLE_NAME_PERSON = "person"; + public static final String TABLE_NAME_PERSON = "person"; public static final String TABLE_NAME_CARRIER = "carrier"; - public static final String TABLE_NAME_CITY = "city"; + public static final String TABLE_NAME_CITY = "city"; public static final String STEP_NAME_SLEEPER = "sleeper"; public static final String STEP_NAME_THROWER = "thrower"; @@ -133,6 +134,20 @@ public class SampleMetaDataProvider qInstance.addWidget(new QWidgetMetaData() .withName(PersonsByCreateDateBarChart.class.getSimpleName()) .withCodeReference(new QCodeReference(PersonsByCreateDateBarChart.class, null))); + + Dotenv dotenv = Dotenv.configure().load(); + QWidgetMetaDataInterface quickSightChartMetaData = new QuickSightChartMetaData() + .withAccountId(dotenv.get("QUICKSIGHT_ACCCOUNT_ID")) + .withAccessKey(dotenv.get("QUICKSIGHT_ACCESS_KEY")) + .withSecretKey(dotenv.get("QUICKSIGHT_SECRET_KEY")) + .withUserArn(dotenv.get("QUICKSIGHT_USER_ARN")) + .withDashboardId("9e452e78-8509-4c81-bb7f-967abfc356da") + .withRegion(Regions.US_EAST_2.getName()) + .withName(QuickSightChartRenderer.class.getSimpleName()) + .withLabel("Example Quicksight Chart") + .withCodeReference(new QCodeReference(QuickSightChartRenderer.class, null)); + + qInstance.addWidget(quickSightChartMetaData); } @@ -153,7 +168,11 @@ public class SampleMetaDataProvider .withIcon(new QIcon().withName("location_city"))) .withChild(qInstance.getProcess(PROCESS_NAME_GREET_INTERACTIVE)) .withIcon(new QIcon().withName("waving_hand")) - .withWidgets(List.of(PersonsByCreateDateBarChart.class.getSimpleName())) + .withWidgets(List.of + ( + PersonsByCreateDateBarChart.class.getSimpleName(), + QuickSightChartRenderer.class.getSimpleName() + )) ); qInstance.addApp(new QAppMetaData() @@ -194,11 +213,11 @@ public class SampleMetaDataProvider Dotenv dotenv = Dotenv.configure().load(); return new RDBMSBackendMetaData() .withName(RDBMS_BACKEND_NAME) - .withVendor("mysql") - .withHostName("127.0.0.1") - .withPort(3306) - .withDatabaseName("qqq") - .withUsername("root") + .withVendor(dotenv.get("RDBMS_VENDOR")) + .withHostName(dotenv.get("RDBMS_HOSTNAME")) + .withPort(Integer.valueOf(Objects.requireNonNull(dotenv.get("RDBMS_PORT")))) + .withDatabaseName(dotenv.get("RDBMS_DATABASE_NAME")) + .withUsername(dotenv.get("RDBMS_USERNAME")) .withPassword(dotenv.get("RDBMS_PASSWORD")); } else @@ -249,8 +268,8 @@ public class SampleMetaDataProvider .withBackendName("company_code")); table.addField(new QFieldMetaData("service_level", QFieldType.STRING) // todo PVS - .withLabel("Service Level") - .withIsRequired(true)); + .withLabel("Service Level") + .withIsRequired(true)); table.addSection(new QFieldSection("identity", "Identity", new QIcon("badge"), Tier.T1, List.of("id", "name"))); table.addSection(new QFieldSection("basicInfo", "Basic Info", new QIcon("dataset"), Tier.T2, List.of("company_code", "service_level"))); diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java index 29ec412b..490ac39f 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChart.java @@ -7,6 +7,7 @@ import com.kingsrook.qqq.backend.core.actions.dashboard.AbstractWidgetRenderer; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.dashboard.widgets.BarChart; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface; import com.kingsrook.qqq.backend.core.model.session.QSession; @@ -19,7 +20,7 @@ public class PersonsByCreateDateBarChart extends AbstractWidgetRenderer ** *******************************************************************************/ @Override - public Object render(QInstance qInstance, QSession session) throws QException + public Object render(QInstance qInstance, QSession session, QWidgetMetaDataInterface metaData) throws QException { try { diff --git a/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChartTest.java b/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChartTest.java index 09d8a3ae..b74f98ba 100644 --- a/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChartTest.java +++ b/qqq-sample-project/src/test/java/com/kingsrook/sampleapp/dashboard/widgets/PersonsByCreateDateBarChartTest.java @@ -23,7 +23,7 @@ class PersonsByCreateDateBarChartTest @Test void test() throws QException { - Object widgetData = new PersonsByCreateDateBarChart().render(SampleMetaDataProvider.defineInstance(), new QSession()); + Object widgetData = new PersonsByCreateDateBarChart().render(SampleMetaDataProvider.defineInstance(), new QSession(), null); assertThat(widgetData).isInstanceOf(BarChart.class); BarChart barChart = (BarChart) widgetData; assertEquals("barChart", barChart.getType()); @@ -31,4 +31,4 @@ class PersonsByCreateDateBarChartTest assertNotNull(barChart.getBarChartData()); } -} \ No newline at end of file +} From 4316b4791605bc3c171c874abc64325ec417b18e Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Tue, 30 Aug 2022 12:13:29 -0500 Subject: [PATCH 4/8] fixed incorrect import order --- .../backend/core/actions/dashboard/QuickSightChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/QuickSightChartRenderer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/QuickSightChartRenderer.java index fd352e3e..74687c75 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/QuickSightChartRenderer.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/QuickSightChartRenderer.java @@ -9,8 +9,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QuickSightChartMe import com.kingsrook.qqq.backend.core.model.session.QSession; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; -import software.amazon.awssdk.services.quicksight.QuickSightClient; import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.quicksight.QuickSightClient; import software.amazon.awssdk.services.quicksight.model.GenerateEmbedUrlForRegisteredUserRequest; import software.amazon.awssdk.services.quicksight.model.GenerateEmbedUrlForRegisteredUserResponse; import software.amazon.awssdk.services.quicksight.model.RegisteredUserDashboardEmbeddingConfiguration; From 4c2ebf8a94bcb864586da37e5ab1084d674b4cd8 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Tue, 30 Aug 2022 12:17:37 -0500 Subject: [PATCH 5/8] PRDONE-94: updated to ignore missing .env file --- .../qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java | 4 +++- .../java/com/kingsrook/sampleapp/SampleMetaDataProvider.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java index c23cd928..715e4358 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java @@ -103,7 +103,9 @@ class ConnectionManagerTest private RDBMSBackendMetaData getAuroraBacked() { - Dotenv dotenv = Dotenv.configure().load(); + Dotenv dotenv = Dotenv.configure() + .ignoreIfMissing() + .load(); return new RDBMSBackendMetaData() .withName("aurora-test") .withVendor(dotenv.get("RDBMS_VENDOR")) diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java index 2330845c..fd48661d 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java @@ -135,7 +135,9 @@ public class SampleMetaDataProvider .withName(PersonsByCreateDateBarChart.class.getSimpleName()) .withCodeReference(new QCodeReference(PersonsByCreateDateBarChart.class, null))); - Dotenv dotenv = Dotenv.configure().load(); + Dotenv dotenv = Dotenv.configure() + .ignoreIfMissing() + .load(); QWidgetMetaDataInterface quickSightChartMetaData = new QuickSightChartMetaData() .withAccountId(dotenv.get("QUICKSIGHT_ACCCOUNT_ID")) .withAccessKey(dotenv.get("QUICKSIGHT_ACCESS_KEY")) From dcea96579c6293a77b43a0c0536102113b29e233 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Tue, 30 Aug 2022 12:28:40 -0500 Subject: [PATCH 6/8] PRDONE-94: updated to set dotenv variables as system properties --- .../rdbms/jdbc/ConnectionManagerTest.java | 13 +++++----- .../sampleapp/SampleMetaDataProvider.java | 26 +++++++++++-------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java index 715e4358..8a9ce4a9 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java @@ -104,15 +104,16 @@ class ConnectionManagerTest private RDBMSBackendMetaData getAuroraBacked() { Dotenv dotenv = Dotenv.configure() + .systemProperties() .ignoreIfMissing() .load(); return new RDBMSBackendMetaData() .withName("aurora-test") - .withVendor(dotenv.get("RDBMS_VENDOR")) - .withHostName(dotenv.get("RDBMS_HOSTNAME")) - .withPort(Integer.valueOf(Objects.requireNonNull(dotenv.get("RDBMS_PORT")))) - .withDatabaseName(dotenv.get("RDBMS_DATABASE_NAME")) - .withUsername(dotenv.get("RDBMS_USERNAME")) - .withPassword(dotenv.get("RDBMS_PASSWORD")); + .withVendor(System.getProperty("RDBMS_VENDOR")) + .withHostName(System.getProperty("RDBMS_HOSTNAME")) + .withPort(Integer.valueOf(Objects.requireNonNull(System.getProperty("RDBMS_PORT")))) + .withDatabaseName(System.getProperty("RDBMS_DATABASE_NAME")) + .withUsername(System.getProperty("RDBMS_USERNAME")) + .withPassword(System.getProperty("RDBMS_PASSWORD")); } } diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java index fd48661d..d024c0a8 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java @@ -137,12 +137,13 @@ public class SampleMetaDataProvider Dotenv dotenv = Dotenv.configure() .ignoreIfMissing() + .systemProperties() .load(); QWidgetMetaDataInterface quickSightChartMetaData = new QuickSightChartMetaData() - .withAccountId(dotenv.get("QUICKSIGHT_ACCCOUNT_ID")) - .withAccessKey(dotenv.get("QUICKSIGHT_ACCESS_KEY")) - .withSecretKey(dotenv.get("QUICKSIGHT_SECRET_KEY")) - .withUserArn(dotenv.get("QUICKSIGHT_USER_ARN")) + .withAccountId(System.getProperty("QUICKSIGHT_ACCCOUNT_ID")) + .withAccessKey(System.getProperty("QUICKSIGHT_ACCESS_KEY")) + .withSecretKey(System.getProperty("QUICKSIGHT_SECRET_KEY")) + .withUserArn(System.getProperty("QUICKSIGHT_USER_ARN")) .withDashboardId("9e452e78-8509-4c81-bb7f-967abfc356da") .withRegion(Regions.US_EAST_2.getName()) .withName(QuickSightChartRenderer.class.getSimpleName()) @@ -212,15 +213,18 @@ public class SampleMetaDataProvider { if(USE_MYSQL) { - Dotenv dotenv = Dotenv.configure().load(); + Dotenv dotenv = Dotenv.configure() + .ignoreIfMissing() + .systemProperties() + .load(); return new RDBMSBackendMetaData() .withName(RDBMS_BACKEND_NAME) - .withVendor(dotenv.get("RDBMS_VENDOR")) - .withHostName(dotenv.get("RDBMS_HOSTNAME")) - .withPort(Integer.valueOf(Objects.requireNonNull(dotenv.get("RDBMS_PORT")))) - .withDatabaseName(dotenv.get("RDBMS_DATABASE_NAME")) - .withUsername(dotenv.get("RDBMS_USERNAME")) - .withPassword(dotenv.get("RDBMS_PASSWORD")); + .withVendor(System.getProperty("RDBMS_VENDOR")) + .withHostName(System.getProperty("RDBMS_HOSTNAME")) + .withPort(Integer.valueOf(Objects.requireNonNull(System.getProperty("RDBMS_PORT")))) + .withDatabaseName(System.getProperty("RDBMS_DATABASE_NAME")) + .withUsername(System.getProperty("RDBMS_USERNAME")) + .withPassword(System.getProperty("RDBMS_PASSWORD")); } else { From 4bf1fe863886cfd7521518d9798f3da9fe513b18 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Tue, 30 Aug 2022 13:33:13 -0500 Subject: [PATCH 7/8] PRDONE-94: updated to look for dotenv properties and fall back to environment vars --- .../rdbms/jdbc/ConnectionManagerTest.java | 24 ++++--- .../sampleapp/SampleMetaDataProvider.java | 64 ++++++++++--------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java index 8a9ce4a9..0c063dd1 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java @@ -103,17 +103,21 @@ class ConnectionManagerTest private RDBMSBackendMetaData getAuroraBacked() { - Dotenv dotenv = Dotenv.configure() - .systemProperties() - .ignoreIfMissing() - .load(); + Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); + String vendor = (dotenv.get("RDBMS_VENDOR") != null) ? dotenv.get("RDBMS_VENDOR") : System.getenv("RDBMS_VENDOR"); + String hostname = (dotenv.get("RDBMS_HOSTNAME") != null) ? dotenv.get("RDBMS_HOSTNAME") : System.getenv("RDBMS_HOSTNAME"); + Integer port = (dotenv.get("RDBMS_PORT") != null) ? Integer.valueOf(Objects.requireNonNull(dotenv.get("RDBMS_PORT"))) : Integer.valueOf(System.getenv("RDBMS_PORT")); + String databaseName = (dotenv.get("RDBMS_DATABASE_NAME") != null) ? dotenv.get("RDBMS_DATABASE_NAME") : System.getenv("RDBMS_DATABASE_NAME"); + String userName = (dotenv.get("RDBMS_USERNAME") != null) ? dotenv.get("RDBMS_USERNAME") : System.getenv("RDBMS_USERNAME"); + String password = (dotenv.get("RDBMS_PASSWORD") != null) ? dotenv.get("RDBMS_PASSWORD") : System.getenv("RDBMS_PASSWORD"); + return new RDBMSBackendMetaData() .withName("aurora-test") - .withVendor(System.getProperty("RDBMS_VENDOR")) - .withHostName(System.getProperty("RDBMS_HOSTNAME")) - .withPort(Integer.valueOf(Objects.requireNonNull(System.getProperty("RDBMS_PORT")))) - .withDatabaseName(System.getProperty("RDBMS_DATABASE_NAME")) - .withUsername(System.getProperty("RDBMS_USERNAME")) - .withPassword(System.getProperty("RDBMS_PASSWORD")); + .withVendor(vendor) + .withHostName(hostname) + .withPort(port) + .withDatabaseName(databaseName) + .withUsername(userName) + .withPassword(password); } } diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java index d024c0a8..db74876f 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java @@ -73,22 +73,22 @@ public class SampleMetaDataProvider { public static boolean USE_MYSQL = true; - public static final String RDBMS_BACKEND_NAME = "rdbms"; + public static final String RDBMS_BACKEND_NAME = "rdbms"; public static final String FILESYSTEM_BACKEND_NAME = "filesystem"; - public static final String APP_NAME_GREETINGS = "greetingsApp"; - public static final String APP_NAME_PEOPLE = "peopleApp"; + public static final String APP_NAME_GREETINGS = "greetingsApp"; + public static final String APP_NAME_PEOPLE = "peopleApp"; public static final String APP_NAME_MISCELLANEOUS = "miscellaneous"; - public static final String PROCESS_NAME_GREET = "greet"; + public static final String PROCESS_NAME_GREET = "greet"; public static final String PROCESS_NAME_GREET_INTERACTIVE = "greetInteractive"; - public static final String PROCESS_NAME_SIMPLE_SLEEP = "simpleSleep"; - public static final String PROCESS_NAME_SIMPLE_THROW = "simpleThrow"; + public static final String PROCESS_NAME_SIMPLE_SLEEP = "simpleSleep"; + public static final String PROCESS_NAME_SIMPLE_THROW = "simpleThrow"; public static final String PROCESS_NAME_SLEEP_INTERACTIVE = "sleepInteractive"; - public static final String TABLE_NAME_PERSON = "person"; + public static final String TABLE_NAME_PERSON = "person"; public static final String TABLE_NAME_CARRIER = "carrier"; - public static final String TABLE_NAME_CITY = "city"; + public static final String TABLE_NAME_CITY = "city"; public static final String STEP_NAME_SLEEPER = "sleeper"; public static final String STEP_NAME_THROWER = "thrower"; @@ -135,15 +135,17 @@ public class SampleMetaDataProvider .withName(PersonsByCreateDateBarChart.class.getSimpleName()) .withCodeReference(new QCodeReference(PersonsByCreateDateBarChart.class, null))); - Dotenv dotenv = Dotenv.configure() - .ignoreIfMissing() - .systemProperties() - .load(); + Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); + String accountId = (dotenv.get("QUICKSIGHT_ACCOUNT_ID") != null) ? dotenv.get("QUICKSIGHT_ACCOUNT_ID") : System.getenv("QUICKSIGHT_ACCOUNT_ID"); + String accessKey = (dotenv.get("QUICKSIGHT_ACCESS_KEY") != null) ? dotenv.get("QUICKSIGHT_ACCESS_KEY") : System.getenv("QUICKSIGHT_ACCESS_KEY"); + String secretKey = (dotenv.get("QUICKSIGHT_SECRET_KEY") != null) ? dotenv.get("QUICKSIGHT_SECRET_KEY") : System.getenv("QUICKSIGHT_SECRET_KEY"); + String userArn = (dotenv.get("QUICKSIGHT_USER_ARN") != null) ? dotenv.get("QUICKSIGHT_USER_ARN") : System.getenv("QUICKSIGHT_USER_ARN"); + QWidgetMetaDataInterface quickSightChartMetaData = new QuickSightChartMetaData() - .withAccountId(System.getProperty("QUICKSIGHT_ACCCOUNT_ID")) - .withAccessKey(System.getProperty("QUICKSIGHT_ACCESS_KEY")) - .withSecretKey(System.getProperty("QUICKSIGHT_SECRET_KEY")) - .withUserArn(System.getProperty("QUICKSIGHT_USER_ARN")) + .withAccountId(accountId) + .withAccessKey(accessKey) + .withSecretKey(secretKey) + .withUserArn(userArn) .withDashboardId("9e452e78-8509-4c81-bb7f-967abfc356da") .withRegion(Regions.US_EAST_2.getName()) .withName(QuickSightChartRenderer.class.getSimpleName()) @@ -171,11 +173,7 @@ public class SampleMetaDataProvider .withIcon(new QIcon().withName("location_city"))) .withChild(qInstance.getProcess(PROCESS_NAME_GREET_INTERACTIVE)) .withIcon(new QIcon().withName("waving_hand")) - .withWidgets(List.of - ( - PersonsByCreateDateBarChart.class.getSimpleName(), - QuickSightChartRenderer.class.getSimpleName() - )) + .withWidgets(List.of(PersonsByCreateDateBarChart.class.getSimpleName(), QuickSightChartRenderer.class.getSimpleName())) ); qInstance.addApp(new QAppMetaData() @@ -213,18 +211,22 @@ public class SampleMetaDataProvider { if(USE_MYSQL) { - Dotenv dotenv = Dotenv.configure() - .ignoreIfMissing() - .systemProperties() - .load(); + Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); + String vendor = (dotenv.get("RDBMS_VENDOR") != null) ? dotenv.get("RDBMS_VENDOR") : System.getenv("RDBMS_VENDOR"); + String hostname = (dotenv.get("RDBMS_HOSTNAME") != null) ? dotenv.get("RDBMS_HOSTNAME") : System.getenv("RDBMS_HOSTNAME"); + Integer port = (dotenv.get("RDBMS_PORT") != null) ? Integer.valueOf(Objects.requireNonNull(dotenv.get("RDBMS_PORT"))) : Integer.valueOf(System.getenv("RDBMS_PORT")); + String databaseName = (dotenv.get("RDBMS_DATABASE_NAME") != null) ? dotenv.get("RDBMS_DATABASE_NAME") : System.getenv("RDBMS_DATABASE_NAME"); + String userName = (dotenv.get("RDBMS_USERNAME") != null) ? dotenv.get("RDBMS_USERNAME") : System.getenv("RDBMS_USERNAME"); + String password = (dotenv.get("RDBMS_PASSWORD") != null) ? dotenv.get("RDBMS_PASSWORD") : System.getenv("RDBMS_PASSWORD"); + return new RDBMSBackendMetaData() .withName(RDBMS_BACKEND_NAME) - .withVendor(System.getProperty("RDBMS_VENDOR")) - .withHostName(System.getProperty("RDBMS_HOSTNAME")) - .withPort(Integer.valueOf(Objects.requireNonNull(System.getProperty("RDBMS_PORT")))) - .withDatabaseName(System.getProperty("RDBMS_DATABASE_NAME")) - .withUsername(System.getProperty("RDBMS_USERNAME")) - .withPassword(System.getProperty("RDBMS_PASSWORD")); + .withVendor(vendor) + .withHostName(hostname) + .withPort(port) + .withDatabaseName(databaseName) + .withUsername(userName) + .withPassword(password); } else { From f08ffe691fbdcd11d8bf31bbd379b1060e9befb9 Mon Sep 17 00:00:00 2001 From: Tim Chamberlain Date: Wed, 31 Aug 2022 12:05:35 -0500 Subject: [PATCH 8/8] PRDONE-94: updated to use interpreter for getting environment credentials, updated interpreter to load Dotenv files as environment overrides --- .../QMetaDataVariableInterpreter.java | 38 ++++++++++++----- .../QMetaDataVariableInterpreterTest.java | 4 +- .../s3/model/metadata/S3BackendMetaData.java | 42 +++++++++++++++++++ .../rdbms/jdbc/ConnectionManagerTest.java | 19 ++++----- .../sampleapp/SampleMetaDataProvider.java | 29 +++++++------ 5 files changed, 95 insertions(+), 37 deletions(-) diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QMetaDataVariableInterpreter.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QMetaDataVariableInterpreter.java index d3ae8884..7549d047 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QMetaDataVariableInterpreter.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QMetaDataVariableInterpreter.java @@ -23,9 +23,12 @@ package com.kingsrook.qqq.backend.core.instances; import java.lang.reflect.Method; +import java.util.HashMap; import java.util.Locale; import java.util.Map; import com.kingsrook.qqq.backend.core.exceptions.QException; +import io.github.cdimascio.dotenv.Dotenv; +import io.github.cdimascio.dotenv.DotenvEntry; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -45,7 +48,22 @@ public class QMetaDataVariableInterpreter { private static final Logger LOG = LogManager.getLogger(QMetaDataVariableInterpreter.class); - private Map customEnvironment; + private Map environmentOverrides; + + + + /******************************************************************************* + ** + *******************************************************************************/ + public QMetaDataVariableInterpreter() + { + environmentOverrides = new HashMap<>(); + Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); + for(DotenvEntry e : dotenv.entries()) + { + environmentOverrides.put(e.getKey(), e.getValue()); + } + } @@ -86,7 +104,7 @@ public class QMetaDataVariableInterpreter ////////////////////////////////////////////////////////////////////////////////////////////// // get the value - if it's null, move on, else, interpret it, and put it back in the object // ////////////////////////////////////////////////////////////////////////////////////////////// - Object value = getter.invoke(o); + Object value = getter.invoke(o); if(value == null) { continue; @@ -124,7 +142,7 @@ public class QMetaDataVariableInterpreter if(value.startsWith(envPrefix) && value.endsWith("}")) { String envVarName = value.substring(envPrefix.length()).replaceFirst("}$", ""); - String envValue = getEnvironment().get(envVarName); + String envValue = getEnvironmentVariable(envVarName); return (envValue); } @@ -149,13 +167,13 @@ public class QMetaDataVariableInterpreter /******************************************************************************* - ** Setter for customEnvironment - protected - meant to be called (at least at this + ** Setter for environmentOverrides - protected - meant to be called (at least at this ** time), only in unit test ** *******************************************************************************/ - protected void setCustomEnvironment(Map customEnvironment) + protected void setEnvironmentOverrides(Map environmentOverrides) { - this.customEnvironment = customEnvironment; + this.environmentOverrides = environmentOverrides; } @@ -163,13 +181,13 @@ public class QMetaDataVariableInterpreter /******************************************************************************* ** *******************************************************************************/ - private Map getEnvironment() + private String getEnvironmentVariable(String key) { - if(this.customEnvironment != null) + if(this.environmentOverrides.containsKey(key)) { - return (this.customEnvironment); + return (this.environmentOverrides.get(key)); } - return System.getenv(); + return System.getenv(key); } } diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QMetaDataVariableInterpreterTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QMetaDataVariableInterpreterTest.java index e3881b00..d40a82d9 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QMetaDataVariableInterpreterTest.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QMetaDataVariableInterpreterTest.java @@ -102,7 +102,7 @@ class QMetaDataVariableInterpreterTest QMetaDataVariableInterpreter secretReader = new QMetaDataVariableInterpreter(); String key = "CUSTOM_PROPERTY"; String value = "ABCD-9876"; - secretReader.setCustomEnvironment(Map.of(key, value)); + secretReader.setEnvironmentOverrides(Map.of(key, value)); assertNull(secretReader.interpret(null)); assertEquals("foo", secretReader.interpret("foo")); @@ -278,4 +278,4 @@ class QMetaDataVariableInterpreterTest } } -} \ No newline at end of file +} diff --git a/qqq-backend-module-filesystem/src/main/java/com/kingsrook/qqq/backend/module/filesystem/s3/model/metadata/S3BackendMetaData.java b/qqq-backend-module-filesystem/src/main/java/com/kingsrook/qqq/backend/module/filesystem/s3/model/metadata/S3BackendMetaData.java index 92dfccc1..037c9550 100644 --- a/qqq-backend-module-filesystem/src/main/java/com/kingsrook/qqq/backend/module/filesystem/s3/model/metadata/S3BackendMetaData.java +++ b/qqq-backend-module-filesystem/src/main/java/com/kingsrook/qqq/backend/module/filesystem/s3/model/metadata/S3BackendMetaData.java @@ -50,6 +50,48 @@ public class S3BackendMetaData extends AbstractFilesystemBackendMetaData + /******************************************************************************* + ** Fluent setter for basePath + ** + *******************************************************************************/ + @SuppressWarnings("unchecked") + @Override + public S3BackendMetaData withBasePath(String basePath) + { + setBasePath(basePath); + return this; + } + + + + /******************************************************************************* + ** Fluent setter for name + ** + *******************************************************************************/ + @SuppressWarnings("unchecked") + @Override + public S3BackendMetaData withName(String name) + { + setName(name); + return this; + } + + + + /******************************************************************************* + ** Fluent setter for backendType + ** + *******************************************************************************/ + @SuppressWarnings("unchecked") + @Override + public S3BackendMetaData withBackendType(String backendType) + { + setBackendType(backendType); + return this; + } + + + /******************************************************************************* ** Getter for bucketName ** diff --git a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java index 0c063dd1..64aa4da9 100644 --- a/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java +++ b/qqq-backend-module-rdbms/src/test/java/com/kingsrook/qqq/backend/module/rdbms/jdbc/ConnectionManagerTest.java @@ -25,9 +25,8 @@ package com.kingsrook.qqq.backend.module.rdbms.jdbc; import java.sql.Connection; import java.sql.SQLException; import java.util.Collections; -import java.util.Objects; +import com.kingsrook.qqq.backend.core.instances.QMetaDataVariableInterpreter; import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData; -import io.github.cdimascio.dotenv.Dotenv; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -103,13 +102,13 @@ class ConnectionManagerTest private RDBMSBackendMetaData getAuroraBacked() { - Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); - String vendor = (dotenv.get("RDBMS_VENDOR") != null) ? dotenv.get("RDBMS_VENDOR") : System.getenv("RDBMS_VENDOR"); - String hostname = (dotenv.get("RDBMS_HOSTNAME") != null) ? dotenv.get("RDBMS_HOSTNAME") : System.getenv("RDBMS_HOSTNAME"); - Integer port = (dotenv.get("RDBMS_PORT") != null) ? Integer.valueOf(Objects.requireNonNull(dotenv.get("RDBMS_PORT"))) : Integer.valueOf(System.getenv("RDBMS_PORT")); - String databaseName = (dotenv.get("RDBMS_DATABASE_NAME") != null) ? dotenv.get("RDBMS_DATABASE_NAME") : System.getenv("RDBMS_DATABASE_NAME"); - String userName = (dotenv.get("RDBMS_USERNAME") != null) ? dotenv.get("RDBMS_USERNAME") : System.getenv("RDBMS_USERNAME"); - String password = (dotenv.get("RDBMS_PASSWORD") != null) ? dotenv.get("RDBMS_PASSWORD") : System.getenv("RDBMS_PASSWORD"); + QMetaDataVariableInterpreter interpreter = new QMetaDataVariableInterpreter(); + String vendor = interpreter.interpret("${env.RDBMS_VENDOR}"); + String hostname = interpreter.interpret("${env.RDBMS_HOSTNAME}"); + Integer port = Integer.valueOf(interpreter.interpret("${env.RDBMS_PORT}")); + String databaseName = interpreter.interpret("${env.RDBMS_DATABASE_NAME}"); + String username = interpreter.interpret("${env.RDBMS_USERNAME}"); + String password= interpreter.interpret("${env.RDBMS_PASSWORD}"); return new RDBMSBackendMetaData() .withName("aurora-test") @@ -117,7 +116,7 @@ class ConnectionManagerTest .withHostName(hostname) .withPort(port) .withDatabaseName(databaseName) - .withUsername(userName) + .withUsername(username) .withPassword(password); } } diff --git a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java index db74876f..1d67b933 100644 --- a/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java +++ b/qqq-sample-project/src/main/java/com/kingsrook/sampleapp/SampleMetaDataProvider.java @@ -23,13 +23,13 @@ package com.kingsrook.sampleapp; import java.util.List; -import java.util.Objects; import com.amazonaws.regions.Regions; import com.kingsrook.qqq.backend.core.actions.dashboard.QuickSightChartRenderer; import com.kingsrook.qqq.backend.core.actions.processes.BackendStep; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QValueException; import com.kingsrook.qqq.backend.core.instances.QInstanceEnricher; +import com.kingsrook.qqq.backend.core.instances.QMetaDataVariableInterpreter; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput; import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType; @@ -63,7 +63,6 @@ import com.kingsrook.qqq.backend.module.filesystem.local.model.metadata.Filesyst import com.kingsrook.qqq.backend.module.filesystem.local.model.metadata.FilesystemTableBackendDetails; import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData; import com.kingsrook.sampleapp.dashboard.widgets.PersonsByCreateDateBarChart; -import io.github.cdimascio.dotenv.Dotenv; /******************************************************************************* @@ -135,11 +134,11 @@ public class SampleMetaDataProvider .withName(PersonsByCreateDateBarChart.class.getSimpleName()) .withCodeReference(new QCodeReference(PersonsByCreateDateBarChart.class, null))); - Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); - String accountId = (dotenv.get("QUICKSIGHT_ACCOUNT_ID") != null) ? dotenv.get("QUICKSIGHT_ACCOUNT_ID") : System.getenv("QUICKSIGHT_ACCOUNT_ID"); - String accessKey = (dotenv.get("QUICKSIGHT_ACCESS_KEY") != null) ? dotenv.get("QUICKSIGHT_ACCESS_KEY") : System.getenv("QUICKSIGHT_ACCESS_KEY"); - String secretKey = (dotenv.get("QUICKSIGHT_SECRET_KEY") != null) ? dotenv.get("QUICKSIGHT_SECRET_KEY") : System.getenv("QUICKSIGHT_SECRET_KEY"); - String userArn = (dotenv.get("QUICKSIGHT_USER_ARN") != null) ? dotenv.get("QUICKSIGHT_USER_ARN") : System.getenv("QUICKSIGHT_USER_ARN"); + QMetaDataVariableInterpreter interpreter = new QMetaDataVariableInterpreter(); + String accountId = interpreter.interpret("${env.QUICKSIGHT_ACCOUNT_ID}"); + String accessKey = interpreter.interpret("${env.QUICKSIGHT_ACCESS_KEY}"); + String secretKey = interpreter.interpret("${env.QUICKSIGHT_SECRET_KEY}"); + String userArn = interpreter.interpret("${env.QUICKSIGHT_USER_ARN}"); QWidgetMetaDataInterface quickSightChartMetaData = new QuickSightChartMetaData() .withAccountId(accountId) @@ -211,13 +210,13 @@ public class SampleMetaDataProvider { if(USE_MYSQL) { - Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load(); - String vendor = (dotenv.get("RDBMS_VENDOR") != null) ? dotenv.get("RDBMS_VENDOR") : System.getenv("RDBMS_VENDOR"); - String hostname = (dotenv.get("RDBMS_HOSTNAME") != null) ? dotenv.get("RDBMS_HOSTNAME") : System.getenv("RDBMS_HOSTNAME"); - Integer port = (dotenv.get("RDBMS_PORT") != null) ? Integer.valueOf(Objects.requireNonNull(dotenv.get("RDBMS_PORT"))) : Integer.valueOf(System.getenv("RDBMS_PORT")); - String databaseName = (dotenv.get("RDBMS_DATABASE_NAME") != null) ? dotenv.get("RDBMS_DATABASE_NAME") : System.getenv("RDBMS_DATABASE_NAME"); - String userName = (dotenv.get("RDBMS_USERNAME") != null) ? dotenv.get("RDBMS_USERNAME") : System.getenv("RDBMS_USERNAME"); - String password = (dotenv.get("RDBMS_PASSWORD") != null) ? dotenv.get("RDBMS_PASSWORD") : System.getenv("RDBMS_PASSWORD"); + QMetaDataVariableInterpreter interpreter = new QMetaDataVariableInterpreter(); + String vendor = interpreter.interpret("${env.RDBMS_VENDOR}"); + String hostname = interpreter.interpret("${env.RDBMS_HOSTNAME}"); + Integer port = Integer.valueOf(interpreter.interpret("${env.RDBMS_PORT}")); + String databaseName = interpreter.interpret("${env.RDBMS_DATABASE_NAME}"); + String username = interpreter.interpret("${env.RDBMS_USERNAME}"); + String password= interpreter.interpret("${env.RDBMS_PASSWORD}"); return new RDBMSBackendMetaData() .withName(RDBMS_BACKEND_NAME) @@ -225,7 +224,7 @@ public class SampleMetaDataProvider .withHostName(hostname) .withPort(port) .withDatabaseName(databaseName) - .withUsername(userName) + .withUsername(username) .withPassword(password); } else