mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-21 06:28:44 +00:00
Compare commits
27 Commits
version-0.
...
feature/18
Author | SHA1 | Date | |
---|---|---|---|
9c60c483aa
|
|||
753f8bb276
|
|||
a131bc782e
|
|||
6262974a4c
|
|||
fe0c9f4b9c
|
|||
b93f262622
|
|||
a6047dcc18
|
|||
fecfb5c19a
|
|||
fca857cf98
|
|||
e558450f6b
|
|||
d3ce24d00e
|
|||
7575a57ae9
|
|||
54f40fbc83
|
|||
caa6723cd2
|
|||
b21ea60c80 | |||
ea15640db1 | |||
9cb401a20e | |||
010b64a0d3 | |||
46bca6efb9 | |||
f6859d040f | |||
d13fc4a863 | |||
eab87b9d80 | |||
707400a8b2 | |||
ffca465f04 | |||
dfb584b367 | |||
504c53b108 | |||
3395ee2146 |
2
.idea/checkstyle-idea.xml
generated
2
.idea/checkstyle-idea.xml
generated
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CheckStyle-IDEA" serialisationVersion="2">
|
||||
<checkstyleVersion>9.0.1</checkstyleVersion>
|
||||
<checkstyleVersion>10.3.4</checkstyleVersion>
|
||||
<scanScope>JavaOnly</scanScope>
|
||||
<suppressErrors>true</suppressErrors>
|
||||
<option name="thirdPartyClasspath" />
|
||||
|
29
.idea/compiler.xml
generated
29
.idea/compiler.xml
generated
@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="qqq-backend-module-rdbms" />
|
||||
<module name="qqq-middleware-picocli" />
|
||||
<module name="qqq-backend-module-filesystem" />
|
||||
<module name="qqq-backend-core" />
|
||||
<module name="qqq-middleware-javalin" />
|
||||
<module name="qqq-sample-project" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
<component name="JavacSettings">
|
||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||
<module name="qqq-backend-core" options="-Xlint:unchecked" />
|
||||
<module name="qqq-backend-module-filesystem" options="-Xlint:unchecked" />
|
||||
<module name="qqq-backend-module-rdbms" options="-Xlint:unchecked" />
|
||||
<module name="qqq-middleware-javalin" options="-Xlint:unchecked" />
|
||||
<module name="qqq-middleware-picocli" options="-Xlint:unchecked" />
|
||||
<module name="qqq-parent-project" options="" />
|
||||
<module name="qqq-sample-project" options="-Xlint:unchecked" />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
19
.idea/encodings.xml
generated
19
.idea/encodings.xml
generated
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/qqq-backend-core/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-backend-core/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-backend-module-filesystem/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-backend-module-filesystem/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-backend-module-rdbms/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-backend-module-rdbms/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-middleware-javalin/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-middleware-javalin/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-middleware-picocli/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-middleware-picocli/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-sample-project/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/qqq-sample-project/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
2
pom.xml
2
pom.xml
@ -48,7 +48,7 @@
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<revision>0.25.0</revision>
|
||||
<revision>0.26.0-SNAPSHOT</revision>
|
||||
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.model.common;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Function;
|
||||
@ -47,7 +48,7 @@ public class TimeZonePossibleValueSourceMetaDataProvider
|
||||
*******************************************************************************/
|
||||
public QPossibleValueSource produce()
|
||||
{
|
||||
return (produce(null, null));
|
||||
return (produce(null, null, null));
|
||||
}
|
||||
|
||||
|
||||
@ -56,6 +57,16 @@ public class TimeZonePossibleValueSourceMetaDataProvider
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QPossibleValueSource produce(Predicate<String> filter, Function<String, String> labelMapper)
|
||||
{
|
||||
return (produce(filter, labelMapper, null));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QPossibleValueSource produce(Predicate<String> filter, Function<String, String> labelMapper, Comparator<QPossibleValue<?>> comparator)
|
||||
{
|
||||
QPossibleValueSource possibleValueSource = new QPossibleValueSource()
|
||||
.withName("timeZones")
|
||||
@ -72,6 +83,11 @@ public class TimeZonePossibleValueSourceMetaDataProvider
|
||||
}
|
||||
}
|
||||
|
||||
if(comparator != null)
|
||||
{
|
||||
enumValues.sort(comparator);
|
||||
}
|
||||
|
||||
possibleValueSource.withEnumValues(enumValues);
|
||||
return (possibleValueSource);
|
||||
}
|
||||
|
@ -594,6 +594,7 @@ public abstract class QRecordEntity
|
||||
{
|
||||
Field tableNameField = entityClass.getDeclaredField("TABLE_NAME");
|
||||
String tableNameValue = (String) tableNameField.get(null);
|
||||
|
||||
return (tableNameValue);
|
||||
}
|
||||
catch(Exception e)
|
||||
|
@ -1 +1 @@
|
||||
0.25.0
|
||||
0.26.0
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
<!-- When updating to javalin 6.3.0, we received classNotFound errors - which this fixed. -->
|
||||
<kotlin.version>1.9.10</kotlin.version>
|
||||
<javalin.version>6.3.0</javalin.version>
|
||||
<javalin.version>6.6.0</javalin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@ -117,11 +117,29 @@
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.kingsrook.qqq</groupId>
|
||||
<artifactId>qqq-middleware-api</artifactId>
|
||||
<version>0.26.0-integration-20250615-161253</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<configuration>
|
||||
<additionalClasspathElements>
|
||||
<additionalClasspathElement>
|
||||
${project.basedir}/src/test/resources/static-site.jar
|
||||
</additionalClasspathElement>
|
||||
</additionalClasspathElements>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
|
@ -26,6 +26,7 @@ import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import com.kingsrook.qqq.api.javalin.QJavalinApiHandler;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||
import com.kingsrook.qqq.backend.core.instances.AbstractQQQApplication;
|
||||
@ -74,9 +75,11 @@ public class QApplicationJavalinServer
|
||||
|
||||
private Integer port = 8000;
|
||||
private boolean serveFrontendMaterialDashboard = true;
|
||||
private String frontendMaterialDashboardHostedPath = "/"; // TODO - Things like this should be moved into a central configuration file system, so that it can be changed in userspace without code changes.
|
||||
private boolean serveLegacyUnversionedMiddlewareAPI = true;
|
||||
private List<AbstractMiddlewareVersion> middlewareVersionList = List.of(new MiddlewareVersionV1());
|
||||
private List<QJavalinRouteProviderInterface> additionalRouteProviders = null;
|
||||
private boolean serveApplicationApi = true;
|
||||
private List<AbstractMiddlewareVersion> middlewareVersionList = List.of(new MiddlewareVersionV1()); // TODO - Seems like this should be null by default, and only set if the application developer wants to serve versioned middleware APIs. @DK
|
||||
private List<QJavalinRouteProvider> additionalRouteProviders = null;
|
||||
private Consumer<Javalin> javalinConfigurationCustomizer = null;
|
||||
private QJavalinMetaData javalinMetaData = null;
|
||||
|
||||
@ -132,20 +135,24 @@ public class QApplicationJavalinServer
|
||||
{
|
||||
if(resource != null)
|
||||
{
|
||||
config.staticFiles.add("/material-dashboard-overlay");
|
||||
config.staticFiles.add(staticFileConfig ->
|
||||
{
|
||||
staticFileConfig.hostedPath = this.frontendMaterialDashboardHostedPath;
|
||||
staticFileConfig.directory = "/material-dashboard-overlay";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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");
|
||||
config.staticFiles.add(staticFileConfig ->
|
||||
{
|
||||
staticFileConfig.hostedPath = this.frontendMaterialDashboardHostedPath;
|
||||
staticFileConfig.directory = "/material-dashboard";
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// set the index page for the SPA from material dashboard //
|
||||
////////////////////////////////////////////////////////////
|
||||
config.spaRoot.addFile("/", "material-dashboard/index.html");
|
||||
config.spaRoot.addFile(this.frontendMaterialDashboardHostedPath, "material-dashboard/index.html");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
@ -167,6 +174,20 @@ public class QApplicationJavalinServer
|
||||
}
|
||||
}
|
||||
|
||||
if(serveApplicationApi)
|
||||
{
|
||||
try
|
||||
{
|
||||
QJavalinApiHandler qJavalinApiHandler = new QJavalinApiHandler(qInstance);
|
||||
config.router.apiBuilder(qJavalinApiHandler.getRoutes());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.error("Unable to add application API routes to Javalin service.", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// versioned qqq middleware routes //
|
||||
/////////////////////////////////////
|
||||
@ -183,7 +204,7 @@ public class QApplicationJavalinServer
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// additional route providers (e.g., application-apis, other middlewares) //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
for(QJavalinRouteProviderInterface routeProvider : CollectionUtils.nonNullList(additionalRouteProviders))
|
||||
for(QJavalinRouteProvider routeProvider : CollectionUtils.nonNullList(additionalRouteProviders))
|
||||
{
|
||||
routeProvider.setQInstance(qInstance);
|
||||
|
||||
@ -201,7 +222,7 @@ public class QApplicationJavalinServer
|
||||
// also pass the javalin service into any additionalRouteProviders, //
|
||||
// in case they need additional setup, e.g., before/after handlers. //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
for(QJavalinRouteProviderInterface routeProvider : CollectionUtils.nonNullList(additionalRouteProviders))
|
||||
for(QJavalinRouteProvider routeProvider : CollectionUtils.nonNullList(additionalRouteProviders))
|
||||
{
|
||||
routeProvider.acceptJavalinService(service);
|
||||
}
|
||||
@ -379,7 +400,7 @@ public class QApplicationJavalinServer
|
||||
}
|
||||
}
|
||||
|
||||
for(QJavalinRouteProviderInterface routeProvider : CollectionUtils.nonNullList(additionalRouteProviders))
|
||||
for(QJavalinRouteProvider routeProvider : CollectionUtils.nonNullList(additionalRouteProviders))
|
||||
{
|
||||
routeProvider.setQInstance(newQInstance);
|
||||
}
|
||||
@ -470,6 +491,25 @@ public class QApplicationJavalinServer
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Sets the hosted path for the frontend Material Dashboard UI.
|
||||
*
|
||||
* This value determines the base URL path under which the static frontend
|
||||
* dashboard assets are served. It should match the path configured in your
|
||||
* frontend build or static asset router.
|
||||
*
|
||||
* @param frontendMaterialDashboardHostedPath the hosted path (e.g., "/admin" or "/dashboard"). Default is "/"
|
||||
*
|
||||
* @see #withServeFrontendMaterialDashboard(boolean)
|
||||
*******************************************************************************/
|
||||
public QApplicationJavalinServer withFrontendMaterialDashboardHostedPath(String frontendMaterialDashboardHostedPath)
|
||||
{
|
||||
this.frontendMaterialDashboardHostedPath = frontendMaterialDashboardHostedPath;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for serveLegacyUnversionedMiddlewareAPI
|
||||
*******************************************************************************/
|
||||
@ -535,7 +575,7 @@ public class QApplicationJavalinServer
|
||||
/*******************************************************************************
|
||||
** Getter for additionalRouteProviders
|
||||
*******************************************************************************/
|
||||
public List<QJavalinRouteProviderInterface> getAdditionalRouteProviders()
|
||||
public List<QJavalinRouteProvider> getAdditionalRouteProviders()
|
||||
{
|
||||
return (this.additionalRouteProviders);
|
||||
}
|
||||
@ -545,7 +585,7 @@ public class QApplicationJavalinServer
|
||||
/*******************************************************************************
|
||||
** Setter for additionalRouteProviders
|
||||
*******************************************************************************/
|
||||
public void setAdditionalRouteProviders(List<QJavalinRouteProviderInterface> additionalRouteProviders)
|
||||
public void setAdditionalRouteProviders(List<QJavalinRouteProvider> additionalRouteProviders)
|
||||
{
|
||||
this.additionalRouteProviders = additionalRouteProviders;
|
||||
}
|
||||
@ -555,7 +595,7 @@ public class QApplicationJavalinServer
|
||||
/*******************************************************************************
|
||||
** Fluent setter for additionalRouteProviders
|
||||
*******************************************************************************/
|
||||
public QApplicationJavalinServer withAdditionalRouteProviders(List<QJavalinRouteProviderInterface> additionalRouteProviders)
|
||||
public QApplicationJavalinServer withAdditionalRouteProviders(List<QJavalinRouteProvider> additionalRouteProviders)
|
||||
{
|
||||
this.additionalRouteProviders = additionalRouteProviders;
|
||||
return (this);
|
||||
@ -566,7 +606,7 @@ public class QApplicationJavalinServer
|
||||
/*******************************************************************************
|
||||
** Fluent setter to add a single additionalRouteProvider
|
||||
*******************************************************************************/
|
||||
public QApplicationJavalinServer withAdditionalRouteProvider(QJavalinRouteProviderInterface additionalRouteProvider)
|
||||
public QApplicationJavalinServer withAdditionalRouteProvider(QJavalinRouteProvider additionalRouteProvider)
|
||||
{
|
||||
if(this.additionalRouteProviders == null)
|
||||
{
|
||||
@ -690,4 +730,57 @@ public class QApplicationJavalinServer
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for frontendMaterialDashboardHostedPath
|
||||
*
|
||||
* @see #withFrontendMaterialDashboardHostedPath(String)
|
||||
*******************************************************************************/
|
||||
public String getFrontendMaterialDashboardHostedPath()
|
||||
{
|
||||
return (this.frontendMaterialDashboardHostedPath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for frontendMaterialDashboardHostedPath
|
||||
*
|
||||
* @see #withFrontendMaterialDashboardHostedPath(String)
|
||||
*******************************************************************************/
|
||||
public void setFrontendMaterialDashboardHostedPath(String frontendMaterialDashboardHostedPath)
|
||||
{
|
||||
this.frontendMaterialDashboardHostedPath = frontendMaterialDashboardHostedPath;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for serveApplicationApi
|
||||
*******************************************************************************/
|
||||
public boolean getServeApplicationApi()
|
||||
{
|
||||
return (this.serveApplicationApi);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for serveApplicationApi
|
||||
*******************************************************************************/
|
||||
public void setServeApplicationApi(boolean serveApplicationApi)
|
||||
{
|
||||
this.serveApplicationApi = serveApplicationApi;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for serveApplicationApi
|
||||
*******************************************************************************/
|
||||
public QApplicationJavalinServer withServeApplicationApi(boolean serveApplicationApi)
|
||||
{
|
||||
this.serveApplicationApi = serveApplicationApi;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -32,19 +32,20 @@ import io.javalin.config.JavalinConfig;
|
||||
** Interface for classes that can provide a list of endpoints to a javalin
|
||||
** server.
|
||||
*******************************************************************************/
|
||||
public interface QJavalinRouteProviderInterface
|
||||
public abstract class QJavalinRouteProvider
|
||||
{
|
||||
|
||||
/***************************************************************************
|
||||
** For initial setup when server boots, set the qInstance - but also,
|
||||
** e.g., for development, to do a hot-swap.
|
||||
***************************************************************************/
|
||||
void setQInstance(QInstance qInstance);
|
||||
public abstract void setQInstance(QInstance qInstance);
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
default EndpointGroup getJavalinEndpointGroup()
|
||||
public EndpointGroup getJavalinEndpointGroup()
|
||||
{
|
||||
/////////////////////////////
|
||||
// no endpoints at default //
|
||||
@ -58,7 +59,7 @@ public interface QJavalinRouteProviderInterface
|
||||
** accept the javalinConfig object, to perform whatever setup you need,
|
||||
** such as setting up routes.
|
||||
***************************************************************************/
|
||||
default void acceptJavalinConfig(JavalinConfig config)
|
||||
public void acceptJavalinConfig(JavalinConfig config)
|
||||
{
|
||||
/////////////////////
|
||||
// noop at default //
|
||||
@ -70,11 +71,10 @@ public interface QJavalinRouteProviderInterface
|
||||
** accept the Javalin service object, to perform whatever setup you need,
|
||||
** such as setting up before/after handlers.
|
||||
***************************************************************************/
|
||||
default void acceptJavalinService(Javalin service)
|
||||
public void acceptJavalinService(Javalin service)
|
||||
{
|
||||
/////////////////////
|
||||
// noop at default //
|
||||
/////////////////////
|
||||
}
|
||||
|
||||
}
|
@ -32,13 +32,12 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
*******************************************************************************/
|
||||
public class JavalinRouteProviderMetaData implements QMetaDataObject
|
||||
{
|
||||
private String hostedPath;
|
||||
|
||||
private String fileSystemPath;
|
||||
private String processName;
|
||||
|
||||
private List<String> methods;
|
||||
|
||||
private String hostedPath;
|
||||
private String spaRootPath;
|
||||
private String spaRootFile;
|
||||
private String fileSystemPath;
|
||||
private String processName;
|
||||
private List<String> methods;
|
||||
private QCodeReference routeAuthenticator;
|
||||
|
||||
|
||||
@ -206,4 +205,70 @@ public class JavalinRouteProviderMetaData implements QMetaDataObject
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for spaRootPath
|
||||
*******************************************************************************/
|
||||
public String getSpaRootPath()
|
||||
{
|
||||
return (this.spaRootPath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for spaRootPath
|
||||
*******************************************************************************/
|
||||
public void setSpaRootPath(String spaRootPath)
|
||||
{
|
||||
this.spaRootPath = spaRootPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for spaRootPath
|
||||
*******************************************************************************/
|
||||
public JavalinRouteProviderMetaData withSpaRootPath(String spaRootPath)
|
||||
{
|
||||
this.spaRootPath = spaRootPath;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Getter for spaRootFile
|
||||
* @see #withSpaRootFile(String)
|
||||
*******************************************************************************/
|
||||
public String getSpaRootFile()
|
||||
{
|
||||
return (this.spaRootFile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Setter for spaRootFile
|
||||
* @see #withSpaRootFile(String)
|
||||
*******************************************************************************/
|
||||
public void setSpaRootFile(String spaRootFile)
|
||||
{
|
||||
this.spaRootFile = spaRootFile;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Fluent setter for spaRootFile
|
||||
* @param spaRootFile TODO document this property
|
||||
* @return this
|
||||
*******************************************************************************/
|
||||
public JavalinRouteProviderMetaData withSpaRootFile(String spaRootFile)
|
||||
{
|
||||
this.spaRootFile = spaRootFile;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
import com.kingsrook.qqq.backend.javalin.QJavalinImplementation;
|
||||
import com.kingsrook.qqq.backend.javalin.QJavalinUtils;
|
||||
import com.kingsrook.qqq.middleware.javalin.QJavalinRouteProviderInterface;
|
||||
import com.kingsrook.qqq.middleware.javalin.QJavalinRouteProvider;
|
||||
import com.kingsrook.qqq.middleware.javalin.metadata.JavalinRouteProviderMetaData;
|
||||
import com.kingsrook.qqq.middleware.javalin.routeproviders.authentication.RouteAuthenticatorInterface;
|
||||
import io.javalin.apibuilder.ApiBuilder;
|
||||
@ -56,7 +56,7 @@ import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class ProcessBasedRouter implements QJavalinRouteProviderInterface
|
||||
public class ProcessBasedRouter extends QJavalinRouteProvider
|
||||
{
|
||||
private static final QLogger LOG = QLogger.getLogger(ProcessBasedRouter.class);
|
||||
|
||||
|
@ -31,7 +31,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.session.QSystemUserSession;
|
||||
import com.kingsrook.qqq.backend.javalin.QJavalinImplementation;
|
||||
import com.kingsrook.qqq.middleware.javalin.QJavalinRouteProviderInterface;
|
||||
import com.kingsrook.qqq.middleware.javalin.QJavalinRouteProvider;
|
||||
import com.kingsrook.qqq.middleware.javalin.metadata.JavalinRouteProviderMetaData;
|
||||
import com.kingsrook.qqq.middleware.javalin.routeproviders.authentication.RouteAuthenticatorInterface;
|
||||
import io.javalin.Javalin;
|
||||
@ -46,16 +46,17 @@ import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||
** javalin route provider that hosts a path in the http server via a path on
|
||||
** the file system
|
||||
*******************************************************************************/
|
||||
public class SimpleFileSystemDirectoryRouter implements QJavalinRouteProviderInterface
|
||||
public class SimpleFileSystemDirectoryRouter extends QJavalinRouteProvider
|
||||
{
|
||||
public static final String LOAD_STATIC_FILES_FROM_JAR_PROPERTY = "qqq.javalin.enableStaticFilesFromJar";
|
||||
private static final QLogger LOG = QLogger.getLogger(SimpleFileSystemDirectoryRouter.class);
|
||||
|
||||
private final String hostedPath;
|
||||
private final String fileSystemPath;
|
||||
|
||||
private QCodeReference routeAuthenticator;
|
||||
|
||||
private QInstance qInstance;
|
||||
public static boolean loadStaticFilesFromJar = false;
|
||||
private final String fileSystemPath;
|
||||
private final String hostedPath;
|
||||
private QCodeReference routeAuthenticator;
|
||||
private QInstance qInstance;
|
||||
private String spaRootPath;
|
||||
private String spaRootFile;
|
||||
|
||||
|
||||
|
||||
@ -67,6 +68,24 @@ public class SimpleFileSystemDirectoryRouter implements QJavalinRouteProviderInt
|
||||
{
|
||||
this.hostedPath = hostedPath;
|
||||
this.fileSystemPath = fileSystemPath;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// read the property to see if we should load static files from the jar file or from the file system //
|
||||
// Javan only supports loading via one method per path, so its a choice of one or the other... //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
try
|
||||
{
|
||||
String propertyValue = System.getProperty(SimpleFileSystemDirectoryRouter.LOAD_STATIC_FILES_FROM_JAR_PROPERTY, "");
|
||||
if(propertyValue.equals("true"))
|
||||
{
|
||||
loadStaticFilesFromJar = true;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
loadStaticFilesFromJar = false;
|
||||
LOG.warn("Exception attempting to read system property, defaulting to false. ", e, logPair("system property", SimpleFileSystemDirectoryRouter.LOAD_STATIC_FILES_FROM_JAR_PROPERTY));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -77,6 +96,8 @@ public class SimpleFileSystemDirectoryRouter implements QJavalinRouteProviderInt
|
||||
public SimpleFileSystemDirectoryRouter(JavalinRouteProviderMetaData routeProvider)
|
||||
{
|
||||
this(routeProvider.getHostedPath(), routeProvider.getFileSystemPath());
|
||||
setSpaRootPath(routeProvider.getSpaRootPath());
|
||||
setSpaRootFile(routeProvider.getSpaRootFile());
|
||||
setRouteAuthenticator(routeProvider.getRouteAuthenticator());
|
||||
}
|
||||
|
||||
@ -98,25 +119,40 @@ public class SimpleFileSystemDirectoryRouter implements QJavalinRouteProviderInt
|
||||
***************************************************************************/
|
||||
private void handleJavalinStaticFileConfig(StaticFileConfig staticFileConfig)
|
||||
{
|
||||
URL resource = getClass().getClassLoader().getResource(fileSystemPath);
|
||||
if(resource == null)
|
||||
{
|
||||
String message = "Could not find file system path: " + fileSystemPath;
|
||||
if(fileSystemPath.startsWith("/") && getClass().getClassLoader().getResource(fileSystemPath.replaceFirst("^/+", "")) != null)
|
||||
{
|
||||
message += ". For non-absolute paths, do not prefix with a leading slash.";
|
||||
}
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
|
||||
if(!hostedPath.startsWith("/"))
|
||||
{
|
||||
LOG.warn("hostedPath [" + hostedPath + "] should probably start with a leading slash...");
|
||||
LOG.warn("hostedPath should probably start with a leading slash...", logPair("hostedPath", hostedPath));
|
||||
}
|
||||
|
||||
staticFileConfig.directory = resource.getFile();
|
||||
staticFileConfig.hostedPath = hostedPath;
|
||||
staticFileConfig.location = Location.EXTERNAL;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Handle loading static files from the jar OR the filesystem based on system property //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(SimpleFileSystemDirectoryRouter.loadStaticFilesFromJar)
|
||||
{
|
||||
staticFileConfig.directory = fileSystemPath;
|
||||
staticFileConfig.hostedPath = hostedPath;
|
||||
staticFileConfig.location = Location.CLASSPATH;
|
||||
}
|
||||
else
|
||||
{
|
||||
URL resource = getClass().getClassLoader().getResource(fileSystemPath);
|
||||
if(resource == null)
|
||||
{
|
||||
String message = "Could not find file system path: " + fileSystemPath;
|
||||
if(fileSystemPath.startsWith("/") && getClass().getClassLoader().getResource(fileSystemPath.replaceFirst("^/+", "")) != null)
|
||||
{
|
||||
message += ". For non-absolute paths, do not prefix with a leading slash.";
|
||||
}
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
|
||||
staticFileConfig.directory = resource.getFile();
|
||||
staticFileConfig.hostedPath = hostedPath;
|
||||
staticFileConfig.location = Location.EXTERNAL;
|
||||
}
|
||||
|
||||
LOG.info("Static File Config", logPair("hostedPath", hostedPath), logPair("directory", staticFileConfig.directory), logPair("location", staticFileConfig.location));
|
||||
}
|
||||
|
||||
|
||||
@ -168,6 +204,10 @@ public class SimpleFileSystemDirectoryRouter implements QJavalinRouteProviderInt
|
||||
@Override
|
||||
public void acceptJavalinConfig(JavalinConfig config)
|
||||
{
|
||||
if(this.getSpaRootPath() != null && !this.getSpaRootPath().isEmpty())
|
||||
{
|
||||
config.spaRoot.addFile(this.spaRootPath, this.spaRootFile);
|
||||
}
|
||||
config.staticFiles.add(this::handleJavalinStaticFileConfig);
|
||||
}
|
||||
|
||||
@ -221,4 +261,74 @@ public class SimpleFileSystemDirectoryRouter implements QJavalinRouteProviderInt
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Getter for spaRootPath
|
||||
* @see #withSpaRootPath(String)
|
||||
*******************************************************************************/
|
||||
public String getSpaRootPath()
|
||||
{
|
||||
return (this.spaRootPath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Setter for spaRootPath
|
||||
* @see #withSpaRootPath(String)
|
||||
*******************************************************************************/
|
||||
public void setSpaRootPath(String spaRootPath)
|
||||
{
|
||||
this.spaRootPath = spaRootPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Fluent setter for spaRootPath
|
||||
* @param spaRootPath TODO document this property
|
||||
* @return this
|
||||
*******************************************************************************/
|
||||
public SimpleFileSystemDirectoryRouter withSpaRootPath(String spaRootPath)
|
||||
{
|
||||
this.spaRootPath = spaRootPath;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Getter for spaRootFile
|
||||
* @see #withSpaRootFile(String)
|
||||
*******************************************************************************/
|
||||
public String getSpaRootFile()
|
||||
{
|
||||
return (this.spaRootFile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Setter for spaRootFile
|
||||
* @see #withSpaRootFile(String)
|
||||
*******************************************************************************/
|
||||
public void setSpaRootFile(String spaRootFile)
|
||||
{
|
||||
this.spaRootFile = spaRootFile;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Fluent setter for spaRootFile
|
||||
* @param spaRootFile TODO document this property
|
||||
* @return this
|
||||
*******************************************************************************/
|
||||
public SimpleFileSystemDirectoryRouter withSpaRootFile(String spaRootFile)
|
||||
{
|
||||
this.spaRootFile = spaRootFile;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.instances.AbstractQQQApplication;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.javalin.TestUtils;
|
||||
import com.kingsrook.qqq.middleware.javalin.routeproviders.SimpleFileSystemDirectoryRouter;
|
||||
import com.kingsrook.qqq.middleware.javalin.specs.v1.MiddlewareVersionV1;
|
||||
import io.javalin.http.HttpStatus;
|
||||
import kong.unirest.HttpResponse;
|
||||
@ -36,6 +37,7 @@ import kong.unirest.Unirest;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static com.kingsrook.qqq.middleware.javalin.routeproviders.SimpleFileSystemDirectoryRouter.LOAD_STATIC_FILES_FROM_JAR_PROPERTY;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -52,6 +54,16 @@ class QApplicationJavalinServerTest
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private static AbstractQQQApplication getQqqApplication()
|
||||
{
|
||||
return new TestApplication();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -60,6 +72,7 @@ class QApplicationJavalinServerTest
|
||||
{
|
||||
javalinServer.stop();
|
||||
TestApplication.callCount = 0;
|
||||
System.clearProperty(LOAD_STATIC_FILES_FROM_JAR_PROPERTY);
|
||||
}
|
||||
|
||||
|
||||
@ -196,6 +209,128 @@ class QApplicationJavalinServerTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testStaticRouterFilesFromExternal() throws Exception
|
||||
{
|
||||
System.setProperty(LOAD_STATIC_FILES_FROM_JAR_PROPERTY, "false");
|
||||
|
||||
javalinServer = new QApplicationJavalinServer(getQqqApplication())
|
||||
.withServeFrontendMaterialDashboard(false)
|
||||
.withPort(PORT);
|
||||
javalinServer.start();
|
||||
|
||||
Unirest.config().setDefaultResponseEncoding("UTF-8");
|
||||
HttpResponse<String> response = Unirest.get("http://localhost:" + PORT + "/statically-served/foo.html").asString();
|
||||
assertEquals("Foo? Bar!", response.getBody());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testFrontendMaterialDashboardHostedPathDefault() throws Exception
|
||||
{
|
||||
javalinServer = new QApplicationJavalinServer(getQqqApplication())
|
||||
.withServeFrontendMaterialDashboard(true)
|
||||
.withPort(PORT)
|
||||
.withFrontendMaterialDashboardHostedPath("/");
|
||||
javalinServer.start();
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Verify that we can get access the file correctly //
|
||||
//////////////////////////////////////////////////////
|
||||
Unirest.config().setDefaultResponseEncoding("UTF-8");
|
||||
HttpResponse<String> response = Unirest.get("http://localhost:" + PORT + "/dashboard.html").asString();
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals("This is a mock of /material-dashboard/dashboard.html for testing purposes.", response.getBody());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testFrontendMaterialDashboardHostedPathDefaultInverse() throws Exception
|
||||
{
|
||||
javalinServer = new QApplicationJavalinServer(getQqqApplication())
|
||||
.withServeFrontendMaterialDashboard(true)
|
||||
.withPort(PORT)
|
||||
.withFrontendMaterialDashboardHostedPath("/");
|
||||
javalinServer.start();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Verify that the file is not accessible at the app path //
|
||||
////////////////////////////////////////////////////////////
|
||||
Unirest.config().setDefaultResponseEncoding("UTF-8");
|
||||
HttpResponse<String> response = Unirest.get("http://localhost:" + PORT + "/bs-directory/dashboard.html").asString();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Note, this will not 404, instead it will return the default index.html file //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
assertEquals("This is a mock of /material-dashboard/index.html for testing purposes.", response.getBody());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testFrontendMaterialDashboardHostedPathCustomApp() throws Exception
|
||||
{
|
||||
javalinServer = new QApplicationJavalinServer(getQqqApplication())
|
||||
.withServeFrontendMaterialDashboard(true)
|
||||
.withPort(PORT)
|
||||
.withFrontendMaterialDashboardHostedPath("/app");
|
||||
javalinServer.start();
|
||||
|
||||
Unirest.config().setDefaultResponseEncoding("UTF-8");
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// verify that we can get access the file correctly //
|
||||
//////////////////////////////////////////////////////
|
||||
HttpResponse<String> response1 = Unirest.get("http://localhost:" + PORT + "/app/dashboard.html").asString();
|
||||
assertEquals(200, response1.getStatus());
|
||||
assertEquals("This is a mock of /material-dashboard/dashboard.html for testing purposes.", response1.getBody());
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Verify that the file is not accessible at the root path //
|
||||
/////////////////////////////////////////////////////////////
|
||||
HttpResponse<String> response2 = Unirest.get("http://localhost:" + PORT + "/index.html").asString();
|
||||
assertEquals(404, response2.getStatus());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testStaticRouterFilesFromClasspath() throws Exception
|
||||
{
|
||||
System.setProperty(LOAD_STATIC_FILES_FROM_JAR_PROPERTY, "true");
|
||||
|
||||
javalinServer = new QApplicationJavalinServer(new QApplicationJavalinServerTest.TestApplication())
|
||||
.withServeFrontendMaterialDashboard(false)
|
||||
.withPort(PORT)
|
||||
.withAdditionalRouteProvider(new SimpleFileSystemDirectoryRouter("/statically-served-from-jar", "static-site-from-jar/"));
|
||||
|
||||
javalinServer.start();
|
||||
|
||||
Unirest.config().setDefaultResponseEncoding("UTF-8");
|
||||
HttpResponse<String> response = Unirest.get("http://localhost:" + PORT + "/statically-served-from-jar/foo-in-jar.html").asString();
|
||||
assertEquals("Foo in a Jar!\n", response.getBody());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -296,16 +431,6 @@ class QApplicationJavalinServerTest
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private static AbstractQQQApplication getQqqApplication()
|
||||
{
|
||||
return new TestApplication();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
|
@ -0,0 +1 @@
|
||||
This is a mock of /material-dashboard-overlay/overlay.html for testing purposes.
|
@ -0,0 +1 @@
|
||||
This is a mock of /material-dashboard/dashboard.html for testing purposes.
|
@ -0,0 +1 @@
|
||||
This is a mock of /material-dashboard/index.html for testing purposes.
|
BIN
qqq-middleware-javalin/src/test/resources/static-site.jar
Normal file
BIN
qqq-middleware-javalin/src/test/resources/static-site.jar
Normal file
Binary file not shown.
@ -68,7 +68,7 @@
|
||||
<dependency>
|
||||
<groupId>com.kingsrook.qqq</groupId>
|
||||
<artifactId>qqq-frontend-material-dashboard</artifactId>
|
||||
<version>0.24.0</version>
|
||||
<version>0.26.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
|
Reference in New Issue
Block a user