Class QJavalinImplementation
java.lang.Object
com.kingsrook.qqq.middleware.javalin.QJavalinImplementation
QQQ Javalin implementation. Given a QInstance, defines all routes needed
to respond to http requests and route down into the qqq backend.
DEPRECATED ROUTES: the unversioned routes defined by getRoutes() (/metaData,
/data/..., /processes/..., /widget/..., /possibleValues/..., /download/...,
/reports/..., /serverInfo, /manageSession) are the legacy API of the
Material Dashboard. The UI API is the versioned /qqq/v1 (docs/UI-API-*.md);
Next UI makes no calls to these routes. They stay served (the default of
QApplicationJavalinServer.serveLegacyUnversionedMiddlewareAPI) while the
Material Dashboard uses them, and every response carries a Deprecation
header and a Link to the successor. Sunset: they will be removed together
with the Material Dashboard; no date is set yet (docs/UI-API-CHANGELOG.md).
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final Stringstatic final StringThe value of the Deprecation header (RFC 9745) on legacy responses: the date the routes were deprecated (2026-10-13), as @epoch-seconds.static final StringThe Link header on legacy responses, naming the successor API.static final intstatic final Stringstatic final Stringstatic final long -
Constructor Summary
ConstructorsConstructorDescriptionQJavalinImplementation(QInstance qInstance) QJavalinImplementation(QInstance qInstance, QJavalinMetaData javalinMetaData) QJavalinImplementation(String qInstanceFilePath) -
Method Summary
Modifier and TypeMethodDescriptionvoidaddJavalinRoutes(io.javalin.apibuilder.EndpointGroup routes) voidif restarting this class, and you want to re-run addJavalinRoutes, but not create duplicates, well, you might want to call this method!static voidclearQContext(io.javalin.http.Context context) static QJavalinMetaDataGetter for javalinMetaDataio.javalin.Javalinstatic QInstanceGetter for qInstanceGetter for qInstanceHotSwapSupplierstatic ReportFormatgetReportFormat(io.javalin.http.Context context, Optional<String> optionalFilename, String format) io.javalin.apibuilder.EndpointGroupThe legacy (deprecated) unversioned routes - see the class comment.static booleanWhether session cookies are set HttpOnly (see setSessionCookieHttpOnly).static longstatic voidhandleException(io.javalin.http.Context context, Exception e) static voidhotSwapQInstance(io.javalin.http.Context context) If there's a qInstanceHotSwapSupplier, and its been a little while, replace the qInstance with a new one from the supplier.static voidstatic voidmetaData(io.javalin.http.Context context) static <T> voidrunStreamedExportOrReport(io.javalin.http.Context context, ReportFormat reportFormat, String filename, UnsafeFunction<PipedOutputStream, T, Exception> preAction, UnsafeConsumer<T, Exception> executor) static voidsetDefaultPort(int port) voidsetJavalinMetaData(QJavalinMetaData javalinMetaData) Setter for javalinMetaDatastatic voidsetMillisBetweenHotSwaps(long millisBetweenHotSwaps) static voidsetQInstance(QInstance qInstance) Setter for qInstancestatic voidsetQInstanceHotSwapSupplier(Supplier<QInstance> qInstanceHotSwapSupplier) Setter for qInstanceHotSwapSupplierstatic voidsetRecordValuesForInsertOrUpdate(io.javalin.http.Context context, QTableMetaData tableMetaData, QRecord record, AbstractTableActionInput input) Read the values of a record insert or update request into a record: a JSON object body, or multipart form fields (with uploaded files for blob fields, and an `associations` field in the legacy or record-v1 format).static voidsetSessionCookie(io.javalin.http.Context context, String name, String value) Set a session cookie (sessionUUID, sessionId) for the whole site with SameSite=Lax, so other sites cannot send it with cross-site POSTs, and Secure when the request arrived over HTTPS (directly or through a proxy that sets X-Forwarded-Proto) (QRun-IO/qqq#696).static voidsetSessionCookieHttpOnly(boolean sessionCookieHttpOnly) Set whether session cookies (sessionUUID, sessionId) are HttpOnly.static QSessionsetupSession(io.javalin.http.Context context, AbstractActionInput input) static QSessionsetupSession(io.javalin.http.Context context, AbstractActionInput input, QAuthenticationMetaData authMetaData) Setup session using the specified authentication metadata.voidstartJavalinServer(int port) void
-
Field Details
-
LEGACY_DEPRECATION_HEADER_VALUE
The value of the Deprecation header (RFC 9745) on legacy responses: the date the routes were deprecated (2026-10-13), as @epoch-seconds.- See Also:
-
LEGACY_SUCCESSOR_LINK
The Link header on legacy responses, naming the successor API.- See Also:
-
SESSION_COOKIE_AGE
public static final int SESSION_COOKIE_AGE- See Also:
-
SESSION_ID_COOKIE_NAME
- See Also:
-
SESSION_UUID_COOKIE_NAME
- See Also:
-
API_KEY_NAME
- See Also:
-
SLOW_LOG_THRESHOLD_MS
public static final long SLOW_LOG_THRESHOLD_MS- See Also:
-
-
Constructor Details
-
QJavalinImplementation
- Throws:
QInstanceValidationException
-
QJavalinImplementation
public QJavalinImplementation(QInstance qInstance, QJavalinMetaData javalinMetaData) throws QInstanceValidationException - Throws:
QInstanceValidationException
-
QJavalinImplementation
- Throws:
IOException
-
-
Method Details
-
setSessionCookie
Set a session cookie (sessionUUID, sessionId) for the whole site with SameSite=Lax, so other sites cannot send it with cross-site POSTs, and Secure when the request arrived over HTTPS (directly or through a proxy that sets X-Forwarded-Proto) (QRun-IO/qqq#696). HttpOnly, so script in the page cannot read the session token, when setSessionCookieHttpOnly is on (QRun-IO/qqq#733).- Parameters:
context- the request whose response sets the cookiename- cookie namevalue- session value
-
getSessionCookieHttpOnly
public static boolean getSessionCookieHttpOnly()Whether session cookies are set HttpOnly (see setSessionCookieHttpOnly). -
setSessionCookieHttpOnly
public static void setSessionCookieHttpOnly(boolean sessionCookieHttpOnly) Set whether session cookies (sessionUUID, sessionId) are HttpOnly. The Next dashboard resumes sessions through v1 manageSession without reading the cookie, so it works either way; the Material Dashboard reads sessionUUID in the browser, so leave this off while it is in use. Off by default here; QApplicationJavalinServer turns it on unless it serves the Material Dashboard (QRun-IO/qqq#733).- Parameters:
sessionCookieHttpOnly- true to set session cookies HttpOnly
-
main
- Throws:
QInstanceValidationException
-
clearQContext
public static void clearQContext(io.javalin.http.Context context) -
hotSwapQInstance
public static void hotSwapQInstance(io.javalin.http.Context context) If there's a qInstanceHotSwapSupplier, and its been a little while, replace the qInstance with a new one from the supplier. Meant to be used while doing development. -
setDefaultPort
public static void setDefaultPort(int port) -
setupSession
public static QSession setupSession(io.javalin.http.Context context, AbstractActionInput input) throws QModuleDispatchException, QAuthenticationException -
setupSession
public static QSession setupSession(io.javalin.http.Context context, AbstractActionInput input, QAuthenticationMetaData authMetaData) throws QModuleDispatchException, QAuthenticationException Setup session using the specified authentication metadata.- Parameters:
context- The Javalin contextinput- The action input (may be null)authMetaData- The authentication metadata to use- Returns:
- The created session
- Throws:
QModuleDispatchException- If module dispatch failsQAuthenticationException- If authentication fails
-
setRecordValuesForInsertOrUpdate
public static void setRecordValuesForInsertOrUpdate(io.javalin.http.Context context, QTableMetaData tableMetaData, QRecord record, AbstractTableActionInput input) throws IOException, QException Read the values of a record insert or update request into a record: a JSON object body, or multipart form fields (with uploaded files for blob fields, and an `associations` field in the legacy or record-v1 format). Shared by the legacy data routes and the v1 table insert and update specs.- Throws:
IOExceptionQException
-
metaData
public static void metaData(io.javalin.http.Context context) -
runStreamedExportOrReport
public static <T> void runStreamedExportOrReport(io.javalin.http.Context context, ReportFormat reportFormat, String filename, UnsafeFunction<PipedOutputStream, T, throws ExceptionException> preAction, UnsafeConsumer<T, Exception> executor) - Throws:
Exception
-
getReportFormat
public static ReportFormat getReportFormat(io.javalin.http.Context context, Optional<String> optionalFilename, String format) -
handleException
-
getJavalinMetaData
Getter for javalinMetaData -
setJavalinMetaData
Setter for javalinMetaData -
getQInstanceHotSwapSupplier
-
setQInstanceHotSwapSupplier
-
getQInstance
Getter for qInstance -
setQInstance
Setter for qInstance -
setMillisBetweenHotSwaps
public static void setMillisBetweenHotSwaps(long millisBetweenHotSwaps) -
getStartTimeMillis
public static long getStartTimeMillis() -
startJavalinServer
public void startJavalinServer(int port) -
getJavalinService
public io.javalin.Javalin getJavalinService() -
stopJavalinServer
public void stopJavalinServer() -
getRoutes
public io.javalin.apibuilder.EndpointGroup getRoutes()The legacy (deprecated) unversioned routes - see the class comment. -
addJavalinRoutes
public void addJavalinRoutes(io.javalin.apibuilder.EndpointGroup routes) -
clearJavalinRoutes
public void clearJavalinRoutes()if restarting this class, and you want to re-run addJavalinRoutes, but not create duplicates, well, you might want to call this method!
-