mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 20:50:44 +00:00
Merged dev into feature/meta-data-loaders
This commit is contained in:
@ -127,14 +127,9 @@ commands:
|
||||
command: |
|
||||
cd docs
|
||||
asciidoctor -a docinfo=shared index.adoc
|
||||
|
||||
upload_docs_site:
|
||||
steps:
|
||||
- run:
|
||||
name: scp html to justinsgotskinnylegs.com
|
||||
command: |
|
||||
cd docs
|
||||
scp index.html dkelkhoff@45.79.44.221:/mnt/first-volume/dkelkhoff/nginx/html/justinsgotskinnylegs.com/qqq-docs.html
|
||||
- store_artifacts:
|
||||
path: docs/index.html
|
||||
when: always
|
||||
|
||||
jobs:
|
||||
mvn_test:
|
||||
@ -159,7 +154,6 @@ jobs:
|
||||
steps:
|
||||
- install_asciidoctor
|
||||
- run_asciidoctor
|
||||
- upload_docs_site
|
||||
|
||||
workflows:
|
||||
test_only:
|
||||
|
@ -147,8 +147,8 @@ public class BackendMetaDataProvider
|
||||
As the size of your application grows, if you're doing per-object meta-data providers, you may find it
|
||||
burdensome, when adding a new object to your instance, to have to write code for it in two places -
|
||||
that is - a new class to produce that meta-data object, AND a single line of code to add that object
|
||||
to your `QInstance`. As such, a mechanism to avoid that line-of-code to add the object to the
|
||||
`QInstance` exists.
|
||||
to your `QInstance`. As such, a mechanism exists to let you avoid that line-of-code for adding the object
|
||||
to the `QInstance`.
|
||||
|
||||
This mechanism involves adding the `MetaDataProducerInterface` to all of your classes that produce a
|
||||
meta-data object. This interface is generic, with a type parameter that will typically be the type of
|
||||
@ -204,7 +204,7 @@ that are all related, and it's only a handful of lines of code for each one, may
|
||||
produce them all in the same class. Or maybe when you define a table, you'd like to define its
|
||||
joins and widgets at the same time.
|
||||
|
||||
This approach can be accomplished by making your `MetaDataProducerInterface`'s type argument by
|
||||
This approach can be accomplished by making the type argument for your `MetaDataProducerInterface` be
|
||||
`MetaDataProducerMultiOutput` - a simple class that just wraps a list of other `MetaDataProducerOutput`
|
||||
objects.
|
||||
|
||||
@ -238,12 +238,13 @@ be specified in their meta-data object.
|
||||
At the same time, if you're writing any custom code in your QQQ application
|
||||
(e.g., any processes or table customizers), where you're working with records from tables, you may
|
||||
prefer being able to work with entity beans (e.g., java classes with typed getter & setter methods),
|
||||
rather than the default object type that QQQ's ORM actions return, the `QRecord`, which carriers all
|
||||
of its values in a `Map`. QQQ has a mechanism for dealing with this - in the form of the `QRecordEntity`
|
||||
class.
|
||||
rather than the default object type that QQQ's ORM actions return, the `QRecord`, which carries all
|
||||
of its values in a `Map` (where you don't get compile-time checks of field names or data types).
|
||||
QQQ has a mechanism for dealing with this - in the form of the `QRecordEntity` class.
|
||||
|
||||
So - if you want to build your application using entity beans (which is recommended, for the compile-time
|
||||
safety that they provide in custom code), you will be writing a `QRecordEntity` class, which will look like:
|
||||
safety that they provide in custom code), you will be writing a `QRecordEntity` class for each of your tables,
|
||||
which will look like:
|
||||
|
||||
[source,java]
|
||||
.QRecordEntity example
|
||||
@ -280,7 +281,7 @@ public QTableMetaData produce(QInstance qInstance) throws QExcpetion
|
||||
----
|
||||
|
||||
That `withFieldsFromEntity` call is one of the biggest benefits of this technique. It allows you to avoid defining
|
||||
all of the field in you table in two place (the entity and the table meta-data).
|
||||
all of the fields in you table in two places (the entity and the table meta-data).
|
||||
|
||||
== MetaData Producing Annotations for Entities
|
||||
|
||||
|
@ -186,7 +186,7 @@ public class AsyncRecordPipeLoop
|
||||
|
||||
if(recordCount > 0)
|
||||
{
|
||||
LOG.info("End of job summary", logPair("recordCount", recordCount), logPair("jobName", jobName), logPair("millis", endTime - jobStartTime), logPair("recordsPerSecond", 1000d * (recordCount / (.001d + (endTime - jobStartTime)))));
|
||||
LOG.debug("End of job summary", logPair("recordCount", recordCount), logPair("jobName", jobName), logPair("millis", endTime - jobStartTime), logPair("recordsPerSecond", 1000d * (recordCount / (.001d + (endTime - jobStartTime)))));
|
||||
}
|
||||
|
||||
return (recordCount);
|
||||
|
@ -120,6 +120,16 @@ public enum QFieldType
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public boolean isTemporal()
|
||||
{
|
||||
return this == QFieldType.DATE || this == QFieldType.DATE_TIME || this == QFieldType.TIME;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -189,7 +189,7 @@ public class StreamedETLExecuteStep extends BaseStreamedETLStep implements Backe
|
||||
|
||||
if(recordCount > 0)
|
||||
{
|
||||
LOG.info("Processed [" + recordCount + "] records.");
|
||||
LOG.debug("Processed [" + recordCount + "] records.");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -223,7 +223,7 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
|
||||
{
|
||||
if(CollectionUtils.nullSafeIsEmpty(runBackendStepInput.getRecords()))
|
||||
{
|
||||
LOG.info("No input records were found.");
|
||||
LOG.debug("No input records were found.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,10 @@ public class RDBMSAggregateAction extends AbstractRDBMSAction implements Aggrega
|
||||
{
|
||||
fieldType = QFieldType.DECIMAL;
|
||||
}
|
||||
else if(field.getType().isTemporal() && (aggregate.getOperator().equals(AggregateOperator.COUNT)) || aggregate.getOperator().equals(AggregateOperator.COUNT_DISTINCT))
|
||||
{
|
||||
fieldType = QFieldType.INTEGER;
|
||||
}
|
||||
}
|
||||
|
||||
if(fieldType != null)
|
||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.module.rdbms.actions;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
@ -42,13 +43,16 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
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.session.QSession;
|
||||
import com.kingsrook.qqq.backend.core.utils.ExceptionUtils;
|
||||
import com.kingsrook.qqq.backend.module.rdbms.TestUtils;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
@ -83,20 +87,56 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
||||
Aggregate averageOfDaysWorked = new Aggregate("daysWorked", AggregateOperator.AVG);
|
||||
Aggregate maxAnnualSalary = new Aggregate("annualSalary", AggregateOperator.MAX);
|
||||
Aggregate minFirstName = new Aggregate("firstName", AggregateOperator.MIN);
|
||||
Aggregate countOfBirthDate = new Aggregate("birthDate", AggregateOperator.COUNT);
|
||||
aggregateInput.withAggregate(countOfId);
|
||||
aggregateInput.withAggregate(sumOfId);
|
||||
aggregateInput.withAggregate(averageOfDaysWorked);
|
||||
aggregateInput.withAggregate(maxAnnualSalary);
|
||||
aggregateInput.withAggregate(minFirstName);
|
||||
aggregateInput.withAggregate(countOfBirthDate);
|
||||
|
||||
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
|
||||
AggregateResult aggregateResult = aggregateOutput.getResults().get(0);
|
||||
Assertions.assertEquals(5, aggregateResult.getAggregateValue(countOfId));
|
||||
Assertions.assertEquals(15, aggregateResult.getAggregateValue(sumOfId));
|
||||
Assertions.assertEquals(new BigDecimal("96.4"), aggregateResult.getAggregateValue(averageOfDaysWorked));
|
||||
Assertions.assertEquals(new BigDecimal("1000000.00"), aggregateResult.getAggregateValue(maxAnnualSalary));
|
||||
Assertions.assertEquals("Darin", aggregateResult.getAggregateValue(minFirstName));
|
||||
assertEquals(5, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals(15, aggregateResult.getAggregateValue(sumOfId));
|
||||
assertEquals(new BigDecimal("96.4"), aggregateResult.getAggregateValue(averageOfDaysWorked));
|
||||
assertEquals(new BigDecimal("1000000.00"), aggregateResult.getAggregateValue(maxAnnualSalary));
|
||||
assertEquals("Darin", aggregateResult.getAggregateValue(minFirstName));
|
||||
assertEquals(4, aggregateResult.getAggregateValue(countOfBirthDate));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
@Disabled("Interesting to see effects of all operators on all types, but failures are expected (e.g., avg(string), so not for CI.")
|
||||
void testOperatorsCrossTypes()
|
||||
{
|
||||
List<String> failures = new ArrayList<>();
|
||||
for(QFieldMetaData field : QContext.getQInstance().getTable(TestUtils.TABLE_NAME_PERSON).getFields().values())
|
||||
{
|
||||
for(AggregateOperator aggregateOperator : AggregateOperator.values())
|
||||
{
|
||||
try
|
||||
{
|
||||
AggregateInput aggregateInput = initAggregateRequest();
|
||||
Aggregate aggregate = new Aggregate(field.getName(), aggregateOperator);
|
||||
aggregateInput.withAggregate(aggregate);
|
||||
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
AggregateResult aggregateResult = aggregateOutput.getResults().get(0);
|
||||
assertNotNull(aggregateResult.getAggregateValue(aggregate));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
failures.add(ExceptionUtils.getRootException(e).getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
failures.forEach(System.out::println);
|
||||
}
|
||||
|
||||
|
||||
@ -123,11 +163,11 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
||||
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
|
||||
AggregateResult aggregateResult = aggregateOutput.getResults().get(0);
|
||||
Assertions.assertEquals(2, aggregateResult.getAggregateValue(countOfId));
|
||||
Assertions.assertEquals(5, aggregateResult.getAggregateValue(sumOfId));
|
||||
Assertions.assertEquals(new BigDecimal("62.0"), aggregateResult.getAggregateValue(averageOfDaysWorked));
|
||||
Assertions.assertEquals(new BigDecimal("26000.00"), aggregateResult.getAggregateValue(maxAnnualSalary));
|
||||
Assertions.assertEquals("James", aggregateResult.getAggregateValue(minFirstName));
|
||||
assertEquals(2, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals(5, aggregateResult.getAggregateValue(sumOfId));
|
||||
assertEquals(new BigDecimal("62.0"), aggregateResult.getAggregateValue(averageOfDaysWorked));
|
||||
assertEquals(new BigDecimal("26000.00"), aggregateResult.getAggregateValue(maxAnnualSalary));
|
||||
assertEquals("James", aggregateResult.getAggregateValue(minFirstName));
|
||||
}
|
||||
|
||||
|
||||
@ -156,15 +196,15 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
||||
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
{
|
||||
AggregateResult aggregateResult = aggregateOutput.getResults().get(0);
|
||||
Assertions.assertEquals("Chamberlain", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals(2, aggregateResult.getAggregateValue(countOfId));
|
||||
Assertions.assertEquals(17, aggregateResult.getAggregateValue(sumOfDaysWorked));
|
||||
assertEquals("Chamberlain", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals(2, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals(17, aggregateResult.getAggregateValue(sumOfDaysWorked));
|
||||
}
|
||||
{
|
||||
AggregateResult aggregateResult = aggregateOutput.getResults().get(1);
|
||||
Assertions.assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals(4, aggregateResult.getAggregateValue(countOfId));
|
||||
Assertions.assertEquals(11364, aggregateResult.getAggregateValue(sumOfDaysWorked));
|
||||
assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals(4, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals(11364, aggregateResult.getAggregateValue(sumOfDaysWorked));
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,29 +241,29 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
||||
AggregateResult aggregateResult;
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Chamberlain", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals("Donny", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
Assertions.assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Chamberlain", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals("Donny", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Chamberlain", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals("Tim", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
Assertions.assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Chamberlain", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals("Tim", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals("Aaron", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
Assertions.assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals("Aaron", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals("Darin", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
Assertions.assertEquals(2, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals("Darin", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
assertEquals(2, aggregateResult.getAggregateValue(countOfId));
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals("Trevor", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
Assertions.assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals("Trevor", aggregateResult.getGroupByValue(firstNameGroupBy));
|
||||
assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
}
|
||||
|
||||
|
||||
@ -255,24 +295,24 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
||||
AggregateResult aggregateResult;
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals(4, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Kelkhoff", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals(4, aggregateResult.getAggregateValue(countOfId));
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Richardson", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Richardson", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Maes", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Maes", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Samples", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Samples", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals(1, aggregateResult.getAggregateValue(countOfId));
|
||||
|
||||
aggregateResult = iterator.next();
|
||||
Assertions.assertEquals("Chamberlain", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
Assertions.assertEquals(2, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals("Chamberlain", aggregateResult.getGroupByValue(lastNameGroupBy));
|
||||
assertEquals(2, aggregateResult.getAggregateValue(countOfId));
|
||||
}
|
||||
|
||||
|
||||
@ -293,7 +333,7 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
||||
////////////////////////////////////////////////////////////
|
||||
AggregateOutput aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
AggregateResult aggregateResult = aggregateOutput.getResults().get(0);
|
||||
Assertions.assertEquals(0, aggregateResult.getAggregateValue(countOfId));
|
||||
assertEquals(0, aggregateResult.getAggregateValue(countOfId));
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// but re-run w/ a group-by -- then, if no rows are found, there are 0 result objects. //
|
||||
@ -324,12 +364,12 @@ public class RDBMSAggregateActionTest extends RDBMSActionTest
|
||||
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_STORE_ALL_ACCESS, true));
|
||||
aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
aggregateResult = aggregateOutput.getResults().get(0);
|
||||
Assertions.assertEquals(43, aggregateResult.getAggregateValue(sumOfQuantity));
|
||||
assertEquals(43, aggregateResult.getAggregateValue(sumOfQuantity));
|
||||
|
||||
QContext.setQSession(new QSession().withSecurityKeyValue(TestUtils.TABLE_NAME_STORE, 1));
|
||||
aggregateOutput = new RDBMSAggregateAction().execute(aggregateInput);
|
||||
aggregateResult = aggregateOutput.getResults().get(0);
|
||||
Assertions.assertEquals(33, aggregateResult.getAggregateValue(sumOfQuantity));
|
||||
assertEquals(33, aggregateResult.getAggregateValue(sumOfQuantity));
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +38,7 @@ import com.kingsrook.qqq.middleware.javalin.specs.v1.MiddlewareVersionV1;
|
||||
import io.javalin.Javalin;
|
||||
import io.javalin.http.Context;
|
||||
import org.apache.commons.lang.BooleanUtils;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -102,17 +103,23 @@ public class QApplicationJavalinServer
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// If you have any assets to add to the web server (e.g., logos, icons) place them at //
|
||||
// src/main/resources/material-dashboard-overlay (or a directory of your choice //
|
||||
// under src/main/resources) and use this line of code to tell javalin about it. //
|
||||
// Make sure to add your app-specific directory to the javalin config before the core //
|
||||
// material-dashboard directory, so in case the same file exists in both (e.g., //
|
||||
// favicon.png), the app-specific one will be used. //
|
||||
// src/main/resources/material-dashboard-overlay //
|
||||
// we'll use the same check that javalin (jetty?) internally uses to see if this //
|
||||
// directory exists - because if it doesn't, then it'll fail to start the server... //
|
||||
// note that that Resource object is auto-closable, hence the try-with-resources //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
config.staticFiles.add("/material-dashboard-overlay");
|
||||
try(Resource resource = Resource.newClassPathResource("/material-dashboard-overlay"))
|
||||
{
|
||||
if(resource !=null)
|
||||
{
|
||||
config.staticFiles.add("/material-dashboard-overlay");
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// tell javalin where to find material-dashboard static web assets //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// tell javalin where to find material-dashboard static web assets //
|
||||
// in this case, this path is coming from the qqq-frontend-material-dashboard jar //
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
config.staticFiles.add("/material-dashboard");
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -68,7 +68,7 @@
|
||||
<dependency>
|
||||
<groupId>com.kingsrook.qqq</groupId>
|
||||
<artifactId>qqq-frontend-material-dashboard</artifactId>
|
||||
<version>0.20.0</version>
|
||||
<version>0.24.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
@ -119,12 +119,16 @@
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.kingsrook.sampleapp.SampleCli</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
|
@ -23,10 +23,8 @@ package com.kingsrook.sampleapp;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.javalin.QJavalinImplementation;
|
||||
import com.kingsrook.qqq.middleware.javalin.QApplicationJavalinServer;
|
||||
import com.kingsrook.sampleapp.metadata.SampleMetaDataProvider;
|
||||
import io.javalin.Javalin;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -36,12 +34,6 @@ public class SampleJavalinServer
|
||||
{
|
||||
private static final QLogger LOG = QLogger.getLogger(SampleJavalinServer.class);
|
||||
|
||||
private static final int PORT = 8000;
|
||||
|
||||
private QInstance qInstance;
|
||||
|
||||
private Javalin javalinService;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -49,7 +41,7 @@ public class SampleJavalinServer
|
||||
*******************************************************************************/
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SampleJavalinServer().startJavalinServer();
|
||||
new SampleJavalinServer().start();
|
||||
}
|
||||
|
||||
|
||||
@ -57,38 +49,11 @@ public class SampleJavalinServer
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void startJavalinServer()
|
||||
public void start()
|
||||
{
|
||||
try
|
||||
{
|
||||
qInstance = SampleMetaDataProvider.defineInstance();
|
||||
|
||||
QJavalinImplementation qJavalinImplementation = new QJavalinImplementation(qInstance);
|
||||
javalinService = Javalin.create(config ->
|
||||
{
|
||||
config.router.apiBuilder(qJavalinImplementation.getRoutes());
|
||||
// todo - not all?
|
||||
config.bundledPlugins.enableCors(cors -> cors.addRule(corsRule -> corsRule.anyHost()));
|
||||
}).start(PORT);
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// set the server to hot-swap the q instance before all routes //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
QJavalinImplementation.setQInstanceHotSwapSupplier(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
return (SampleMetaDataProvider.defineInstance());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.warn("Error hot-swapping meta data", e);
|
||||
return (null);
|
||||
}
|
||||
});
|
||||
javalinService.before(QJavalinImplementation::hotSwapQInstance);
|
||||
|
||||
javalinService.after(ctx -> ctx.res().setHeader("Access-Control-Allow-Origin", "http://localhost:3000"));
|
||||
new QApplicationJavalinServer(new SampleMetaDataProvider()).start();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
@ -96,16 +61,4 @@ public class SampleJavalinServer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void stopJavalinServer()
|
||||
{
|
||||
if(javalinService != null)
|
||||
{
|
||||
javalinService.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.QuickSightChartR
|
||||
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.AbstractQQQApplication;
|
||||
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;
|
||||
@ -78,7 +79,7 @@ import com.kingsrook.sampleapp.processes.clonepeople.ClonePeopleTransformStep;
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class SampleMetaDataProvider
|
||||
public class SampleMetaDataProvider extends AbstractQQQApplication
|
||||
{
|
||||
public static boolean USE_MYSQL = true;
|
||||
|
||||
@ -108,6 +109,17 @@ public class SampleMetaDataProvider
|
||||
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@Override
|
||||
public QInstance defineQInstance() throws QException
|
||||
{
|
||||
return (defineInstance());
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -145,7 +157,7 @@ public class SampleMetaDataProvider
|
||||
private static void defineBranding(QInstance qInstance)
|
||||
{
|
||||
qInstance.setBranding(new QBrandingMetaData()
|
||||
.withLogo("/kr-logo.png")
|
||||
.withLogo("/samples-logo.png")
|
||||
.withIcon("/kr-icon.png"));
|
||||
}
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 129 KiB |
@ -38,8 +38,7 @@ class SampleJavalinServerTest
|
||||
void testStartStop()
|
||||
{
|
||||
SampleJavalinServer sampleJavalinServer = new SampleJavalinServer();
|
||||
sampleJavalinServer.startJavalinServer();
|
||||
sampleJavalinServer.stopJavalinServer();
|
||||
sampleJavalinServer.start();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user