Merge branch 'release/0.0.0'

This commit is contained in:
2022-07-01 11:46:22 -05:00
11 changed files with 421 additions and 105 deletions

77
.circleci/config.yml Normal file
View File

@ -0,0 +1,77 @@
version: 2.1
executors:
java17:
docker:
- image: 'cimg/openjdk:17.0'
resource_class: small
orbs:
slack: circleci/slack@4.10.1
commands:
run_maven:
parameters:
maven_subcommand:
default: test
type: string
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "pom.xml" }}
- run:
name: Run Maven
command: |
mvn -s .circleci/mvn-settings.xml << parameters.maven_subcommand >>
- run:
name: Save test results
command: |
mkdir -p ~/test-results/junit/
find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} ~/test-results/junit/ \;
when: always
- store_test_results:
path: ~/test-results
- save_cache:
paths:
- ~/.m2
key: v1-dependencies-{{ checksum "pom.xml" }}
jobs:
mvn_test:
executor: java17
steps:
- run_maven:
maven_subcommand: test
- slack/notify:
event: fail
mvn_deploy:
executor: java17
steps:
- run_maven:
maven_subcommand: deploy
- slack/notify:
event: always
workflows:
test_only:
jobs:
- mvn_test:
context: [ qqq-maven-registry-credentials, kingsrook-slack ]
filters:
branches:
ignore: /dev/
tags:
ignore: /(version|snapshot)-.*/
deploy:
jobs:
- mvn_deploy:
context: [ qqq-maven-registry-credentials, kingsrook-slack ]
filters:
branches:
only: /dev/
tags:
only: /(version|snapshot)-.*/

View File

@ -0,0 +1,9 @@
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>github-qqq-maven-registry</id>
<username>${env.QQQ_MAVEN_REGISTRY_USERNAME}</username>
<password>${env.QQQ_MAVEN_REGISTRY_PASSWORD}</password>
</server>
</servers>
</settings>

View File

@ -1,35 +0,0 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Java CI with Maven
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
cache: maven
- name: maven-settings-xml-action
uses: whelk-io/maven-settings-xml-action@v20
with:
servers: '[{ "id": "github-qqq-maven-registry", "username": "${{ secrets.QQQ_MAVEN_REGISTRY_USERNAME }}", "password": "${{ secrets.QQQ_MAVEN_REGISTRY_PASSWORD }}" }]'
repositories: '[{ "id": "github-qqq-maven-registry", "url": "https://maven.pkg.github.com/Kingsrook/qqq-maven-registry", "snapshots": { "enabled": "true" }}]'
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Publish to GitHub Packages Apache Maven
run: mvn deploy
env:
GITHUB_TOKEN: ${{ github.token }}

View File

@ -5,8 +5,7 @@ This is a qqq middleware module, providing [javalin](https://javalin.io) access
QQQ - Low-code Application Framework for Engineers. \
Copyright (C) 2022. Kingsrook, LLC \
651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States \
contact@kingsrook.com
https://github.com/Kingsrook/intellij-commentator-plugin
contact@kingsrook.com | https://github.com/Kingsrook/
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as

View File

@ -46,6 +46,7 @@
-->
<module name="TreeWalker">
<module name="SuppressWarningsHolder"/>
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
@ -171,7 +172,7 @@
<property name="caseIndent" value="3"/>
<property name="throwsIndent" value="6"/>
<property name="lineWrappingIndentation" value="3"/>
<property name="arrayInitIndent" value="2"/>
<property name="arrayInitIndent" value="6"/>
</module>
<!--
<module name="AbbreviationAsWordInName">
@ -260,4 +261,5 @@
<module name="MissingOverride"/>
</module>
<module name="SuppressWarningsFilter"/>
</module>

55
pom.xml
View File

@ -20,14 +20,18 @@
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kingsrook.qqq</groupId>
<artifactId>qqq-middleware-javalin</artifactId>
<version>0.0-SNAPSHOT</version>
<version>0.0.0</version>
<scm>
<connection>scm:git:git@github.com:Kingsrook/qqq-middleware-javalin.git</connection>
<developerConnection>scm:git:git@github.com:Kingsrook/qqq-middleware-javalin.git</developerConnection>
<tag>HEAD</tag>
</scm>
<properties>
<!-- props specifically to this module -->
@ -47,12 +51,12 @@
<dependency>
<groupId>com.kingsrook.qqq</groupId>
<artifactId>qqq-backend-core</artifactId>
<version>0.0-SNAPSHOT</version>
<version>0.0.0</version>
</dependency>
<dependency>
<groupId>com.kingsrook.qqq</groupId>
<artifactId>qqq-backend-module-rdbms</artifactId>
<version>0.0-SNAPSHOT</version>
<version>0.0.0</version>
<scope>test</scope>
</dependency>
@ -71,23 +75,13 @@
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.197</version>
<version>2.1.210</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.30</version>
<version>1.7.36</version>
</dependency>
<!-- Common deps for all qqq modules -->
@ -99,17 +93,17 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.15.0</version>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.15.0</version>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.1</version>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
@ -165,13 +159,28 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.amashchenko.maven.plugin</groupId>
<artifactId>gitflow-maven-plugin</artifactId>
<version>1.18.0</version>
<configuration>
<gitFlowConfig>
<productionBranch>main</productionBranch>
<developmentBranch>dev</developmentBranch>
<versionTagPrefix>version-</versionTagPrefix>
</gitFlowConfig>
<skipFeatureVersion>true</skipFeatureVersion> <!-- Keep feature names out of versions -->
<postReleaseGoals>install</postReleaseGoals> <!-- Let CI run deploys -->
<commitDevelopmentVersionAtStart>true</commitDevelopmentVersionAtStart>
<versionDigitToIncrement>1</versionDigitToIncrement> <!-- In general, we update the minor -->
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>github</id>
<id>github-qqq-maven-registry</id>
<name>GitHub QQQ Maven Registry</name>
<url>https://maven.pkg.github.com/Kingsrook/qqq-maven-registry</url>
</repository>

View File

@ -29,13 +29,19 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import com.kingsrook.qqq.backend.core.actions.DeleteAction;
import com.kingsrook.qqq.backend.core.actions.InsertAction;
import com.kingsrook.qqq.backend.core.actions.MetaDataAction;
import com.kingsrook.qqq.backend.core.actions.QueryAction;
import com.kingsrook.qqq.backend.core.actions.RunProcessAction;
import com.kingsrook.qqq.backend.core.actions.TableMetaDataAction;
import com.kingsrook.qqq.backend.core.actions.UpdateAction;
import com.kingsrook.qqq.backend.core.adapters.QInstanceAdapter;
import com.kingsrook.qqq.backend.core.exceptions.QException;
import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException;
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
import com.kingsrook.qqq.backend.core.model.actions.AbstractQRequest;
@ -47,17 +53,21 @@ import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataRequest;
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataResult;
import com.kingsrook.qqq.backend.core.model.actions.metadata.table.TableMetaDataRequest;
import com.kingsrook.qqq.backend.core.model.actions.metadata.table.TableMetaDataResult;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessRequest;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessResult;
import com.kingsrook.qqq.backend.core.model.actions.query.QQueryFilter;
import com.kingsrook.qqq.backend.core.model.actions.query.QueryRequest;
import com.kingsrook.qqq.backend.core.model.actions.query.QueryResult;
import com.kingsrook.qqq.backend.core.model.actions.update.UpdateRequest;
import com.kingsrook.qqq.backend.core.model.actions.update.UpdateResult;
import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.session.QSession;
import com.kingsrook.qqq.backend.core.modules.QAuthenticationModuleDispatcher;
import com.kingsrook.qqq.backend.core.modules.interfaces.QAuthenticationModuleInterface;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
import com.kingsrook.qqq.backend.core.utils.ExceptionUtils;
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils;
@ -84,6 +94,7 @@ import static io.javalin.apibuilder.ApiBuilder.put;
public class QJavalinImplementation
{
private static final Logger LOG = LogManager.getLogger(QJavalinImplementation.class);
private static final int SESSION_COOKIE_AGE = 60 * 60 * 24;
private static QInstance qInstance;
@ -154,6 +165,7 @@ public class QJavalinImplementation
path("/:table", () ->
{
get("", QJavalinImplementation::tableMetaData);
// todo - process meta data - just under tables? or top-level too? maybe move tables to be under /tables/?
});
});
path("/data", () ->
@ -172,6 +184,14 @@ public class QJavalinImplementation
});
});
});
path("/processes", () ->
{
path("/:process", () ->
{
get("/init", QJavalinImplementation::processInit);
get("/step", QJavalinImplementation::processStep);
});
});
});
}
@ -183,7 +203,7 @@ public class QJavalinImplementation
private static void setupSession(Context context, AbstractQRequest request) throws QModuleDispatchException
{
QAuthenticationModuleDispatcher qAuthenticationModuleDispatcher = new QAuthenticationModuleDispatcher();
QAuthenticationModuleInterface authenticationModule = qAuthenticationModuleDispatcher.getQModule(request.getAuthenticationMetaData());
QAuthenticationModuleInterface authenticationModule = qAuthenticationModuleDispatcher.getQModule(request.getAuthenticationMetaData());
// todo - does this need some per-provider logic actually? mmm...
Map<String, String> authenticationContext = new HashMap<>();
@ -203,7 +223,7 @@ public class QJavalinImplementation
{
try
{
String table = context.pathParam("table");
String table = context.pathParam("table");
List<Serializable> primaryKeys = new ArrayList<>();
primaryKeys.add(context.pathParam("primaryKey"));
@ -232,9 +252,9 @@ public class QJavalinImplementation
{
try
{
String table = context.pathParam("table");
String table = context.pathParam("table");
List<QRecord> recordList = new ArrayList<>();
QRecord record = new QRecord();
QRecord record = new QRecord();
record.setTableName(table);
recordList.add(record);
@ -276,9 +296,9 @@ public class QJavalinImplementation
{
try
{
String table = context.pathParam("table");
String table = context.pathParam("table");
List<QRecord> recordList = new ArrayList<>();
QRecord record = new QRecord();
QRecord record = new QRecord();
record.setTableName(table);
recordList.add(record);
@ -422,7 +442,6 @@ public class QJavalinImplementation
else
{
LOG.warn("Exception in javalin request", e);
e.printStackTrace();
context.status(HttpStatus.INTERNAL_SERVER_ERROR_500)
.result("{\"error\":\"" + e.getClass().getSimpleName() + " (" + e.getMessage() + ")\"}");
}
@ -462,4 +481,88 @@ public class QJavalinImplementation
return (null);
}
/*******************************************************************************
** Init a process (named in path param :process)
**
*******************************************************************************/
private static void processInit(Context context) throws QException
{
RunProcessRequest runProcessRequest = new RunProcessRequest(qInstance);
setupSession(context, runProcessRequest);
runProcessRequest.setProcessName(context.pathParam("process"));
runProcessRequest.setCallback(new QJavalinProcessCallback());
/////////////////////////////////////////////////////////////////////////////////////
// take values from query-string params, and put them into the run process request //
// todo - better from POST body, or with a "field-" type of prefix?? //
/////////////////////////////////////////////////////////////////////////////////////
for(Map.Entry<String, List<String>> queryParam : context.queryParamMap().entrySet())
{
String fieldName = queryParam.getKey();
List<String> values = queryParam.getValue();
if(CollectionUtils.nullSafeHasContents(values))
{
runProcessRequest.addValue(fieldName, values.get(0));
}
}
try
{
////////////////////////////////////////////////
// run the process //
// todo - some "job id" to return to caller? //
////////////////////////////////////////////////
CompletableFuture<RunProcessResult> future = CompletableFuture.supplyAsync(() ->
{
try
{
LOG.info("Running process [" + runProcessRequest.getProcessName() + "]");
RunProcessResult runProcessResult = new RunProcessAction().execute(runProcessRequest);
LOG.info("Process result error? " + runProcessResult.getError());
for(QFieldMetaData outputField : qInstance.getProcess(runProcessRequest.getProcessName()).getOutputFields())
{
LOG.info("Process result output value: " + outputField.getName() + ": " + runProcessResult.getValues().get(outputField.getName()));
}
return (runProcessResult);
}
catch(Exception e)
{
LOG.error("Error running future for process", e);
throw (new CompletionException(e));
}
});
Map<String, Object> resultForCaller = new HashMap<>();
try
{
RunProcessResult runProcessResult = future.get(3, TimeUnit.SECONDS);
resultForCaller.put("error", runProcessResult.getError());
resultForCaller.put("values", runProcessResult.getValues());
}
catch(TimeoutException te)
{
resultForCaller.put("jobId", "Job is running asynchronously... job id available in a later version.");
}
context.result(JsonUtils.toJson(resultForCaller));
}
catch(Exception e)
{
handleException(context, e);
}
}
/*******************************************************************************
** Run a step in a process (named in path param :process)
**
*******************************************************************************/
private static void processStep(Context context)
{
}
}

View File

@ -0,0 +1,66 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2022. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.javalin;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.kingsrook.qqq.backend.core.callbacks.QProcessCallback;
import com.kingsrook.qqq.backend.core.model.actions.query.QQueryFilter;
import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/*******************************************************************************
**
*******************************************************************************/
public class QJavalinProcessCallback implements QProcessCallback
{
private static final Logger LOG = LogManager.getLogger(QJavalinProcessCallback.class);
/*******************************************************************************
**
*******************************************************************************/
@Override
public QQueryFilter getQueryFilter()
{
LOG.warn("Getting a query filter in javalin is NOT yet implemented");
return (new QQueryFilter());
}
/*******************************************************************************
**
*******************************************************************************/
@Override
public Map<String, Serializable> getFieldValues(List<QFieldMetaData> fields)
{
LOG.warn("Getting field values in javalin is NOT yet implemented");
return (new HashMap<>());
}
}

View File

@ -203,6 +203,7 @@ class QJavalinImplementationTest
Map<String, Serializable> body = new HashMap<>();
body.put("firstName", "Bobby");
body.put("lastName", "Hull");
body.put("email", "bobby@hull.com");
HttpResponse<String> response = Unirest.post(BASE_URL + "/data/person")
.header("Content-Type", "application/json")
@ -284,4 +285,43 @@ class QJavalinImplementationTest
assertEquals(4, rowsFound);
}));
}
/*******************************************************************************
** test running a process
**
*******************************************************************************/
@Test
public void test_processGreetInit() throws Exception
{
HttpResponse<String> response = Unirest.get(BASE_URL + "/processes/greet/init")
.header("Content-Type", "application/json")
.asString();
assertEquals(200, response.getStatus());
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
assertNotNull(jsonObject);
assertEquals("null X null", jsonObject.getJSONObject("values").getString("outputMessage"));
}
/*******************************************************************************
** test running a process with field values on the query string
**
*******************************************************************************/
@Test
public void test_processGreetInitWithQueryValues() throws Exception
{
HttpResponse<String> response = Unirest.get(BASE_URL + "/processes/greet/init?greetingPrefix=Hey&greetingSuffix=Jude")
.header("Content-Type", "application/json")
.asString();
assertEquals(200, response.getStatus());
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
assertNotNull(jsonObject);
assertEquals("Hey X Jude", jsonObject.getJSONObject("values").getString("outputMessage"));
}
}

View File

@ -25,13 +25,23 @@ package com.kingsrook.qqq.backend.javalin;
import java.io.InputStream;
import java.sql.Connection;
import java.util.List;
import com.kingsrook.qqq.backend.core.interfaces.mock.MockFunctionBody;
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.QCodeType;
import com.kingsrook.qqq.backend.core.model.metadata.QCodeUsage;
import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
import com.kingsrook.qqq.backend.module.rdbms.RDBMSBackendMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionOutputMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QOutputView;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListView;
import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData;
import com.kingsrook.qqq.backend.module.rdbms.jdbc.ConnectionManager;
import com.kingsrook.qqq.backend.module.rdbms.jdbc.QueryManager;
import org.apache.commons.io.IOUtils;
@ -52,11 +62,12 @@ public class TestUtils
@SuppressWarnings("unchecked")
public static void primeTestDatabase() throws Exception
{
ConnectionManager connectionManager = new ConnectionManager();
Connection connection = connectionManager.getConnection(new RDBMSBackendMetaData(TestUtils.defineBackend()));
InputStream primeTestDatabaseSqlStream = TestUtils.class.getResourceAsStream("/prime-test-database.sql");
ConnectionManager connectionManager = new ConnectionManager();
Connection connection = connectionManager.getConnection(TestUtils.defineBackend());
InputStream primeTestDatabaseSqlStream = TestUtils.class.getResourceAsStream("/prime-test-database.sql");
assertNotNull(primeTestDatabaseSqlStream);
List<String> lines = (List<String>) IOUtils.readLines(primeTestDatabaseSqlStream);
lines = lines.stream().filter(line -> !line.startsWith("-- ")).toList();
String joinedSQL = String.join("\n", lines);
for(String sql : joinedSQL.split(";"))
{
@ -73,7 +84,7 @@ public class TestUtils
public static void runTestSql(String sql, QueryManager.ResultSetProcessor resultSetProcessor) throws Exception
{
ConnectionManager connectionManager = new ConnectionManager();
Connection connection = connectionManager.getConnection(new RDBMSBackendMetaData(defineBackend()));
Connection connection = connectionManager.getConnection(defineBackend());
QueryManager.executeStatement(connection, sql, resultSetProcessor);
}
@ -89,6 +100,7 @@ public class TestUtils
qInstance.setAuthentication(defineAuthentication());
qInstance.addBackend(defineBackend());
qInstance.addTable(defineTablePerson());
qInstance.addProcess(defineProcessGreetPeople());
return (qInstance);
}
@ -111,16 +123,16 @@ public class TestUtils
** Define the h2 rdbms backend
**
*******************************************************************************/
public static QBackendMetaData defineBackend()
public static RDBMSBackendMetaData defineBackend()
{
return new QBackendMetaData()
.withName("default")
.withType("rdbms")
.withValue("vendor", "h2")
.withValue("hostName", "mem")
.withValue("databaseName", "test_database")
.withValue("username", "sa")
.withValue("password", "");
RDBMSBackendMetaData rdbmsBackendMetaData = new RDBMSBackendMetaData()
.withVendor("h2")
.withHostName("mem")
.withDatabaseName("test_database")
.withUsername("sa")
.withPassword("");
rdbmsBackendMetaData.setName("default");
return (rdbmsBackendMetaData);
}
@ -145,4 +157,38 @@ public class TestUtils
.withField(new QFieldMetaData("email", QFieldType.STRING));
}
/*******************************************************************************
** Define the 'greet people' process
*******************************************************************************/
private static QProcessMetaData defineProcessGreetPeople()
{
return new QProcessMetaData()
.withName("greet")
.withTableName("person")
.addFunction(new QFunctionMetaData()
.withName("prepare")
.withCode(new QCodeReference()
.withName(MockFunctionBody.class.getName())
.withCodeType(QCodeType.JAVA)
.withCodeUsage(QCodeUsage.FUNCTION)) // todo - needed, or implied in this context?
.withInputData(new QFunctionInputMetaData()
.withRecordListMetaData(new QRecordListMetaData().withTableName("person"))
.withFieldList(List.of(
new QFieldMetaData("greetingPrefix", QFieldType.STRING),
new QFieldMetaData("greetingSuffix", QFieldType.STRING)
)))
.withOutputMetaData(new QFunctionOutputMetaData()
.withRecordListMetaData(new QRecordListMetaData()
.withTableName("person")
.addField(new QFieldMetaData("fullGreeting", QFieldType.STRING))
)
.withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING))))
.withOutputView(new QOutputView()
.withMessageField("outputMessage")
.withRecordListView(new QRecordListView().withFieldNames(List.of("id", "firstName", "lastName", "fullGreeting"))))
);
}
}

View File

@ -1,28 +1,28 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2022. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
--
-- QQQ - Low-code Application Framework for Engineers.
-- Copyright (C) 2021-2022. Kingsrook, LLC
-- 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
-- contact@kingsrook.com
-- https://github.com/Kingsrook/
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as
-- published by the Free Software Foundation, either version 3 of the
-- License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Affero General Public License for more details.
--
-- You should have received a copy of the GNU Affero General Public License
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
--
DROP TABLE IF EXISTS person;
CREATE TABLE person
(
id SERIAL,
id INT AUTO_INCREMENT,
create_date TIMESTAMP DEFAULT now(),
modify_date TIMESTAMP DEFAULT now(),