Compare commits

..
Author SHA1 Message Date
CI 61618f3345 Bump version to 0.6.0-SNAPSHOT [skip ci] 2026-11-07 19:22:54 +00:00
james.maes 835c5add68 Merge pull request 'build(deps): align with Gitea registry (parent 2.2.1, QQQ 4.1.0-RC.26)' (#32) from deps/align-gitea into develop
maven / build (push) Successful in 2m37s
build / maven (push) Successful in 2m37s
2026-11-07 19:20:28 +00:00
james.maesandClaude Opus 5.5 a9fa2bc932 build: surefire 3.5.6 (3.5.2 POM is served brotli-encoded by maven.kof22.com and fails to parse)
maven / build (push) Successful in 1m26s
build / maven (push) Successful in 1m26s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 19:18:37 +00:00
james.maesandClaude Opus 5.5 d4b2b626ca build(deps): align with Gitea registry (parent 2.2.1, QQQ 4.1.0-RC.26)
maven / build (push) Canceled after 36s
build / maven (push) Canceled after 36s
demo/pom.xml: qqq.version: 4.1.0-RC.21 -> 4.1.0-RC.26
demo/pom.xml: qqq-frontend-next: 1.0.0-RC.35 -> 1.0.0-RC.38
examples/echo/demo/pom.xml: qqq.version: 4.1.0-RC.21 -> 4.1.0-RC.26
examples/echo/demo/pom.xml: qqq-frontend-next: 1.0.0-RC.35 -> 1.0.0-RC.38
examples/echo/demo/pom.xml: generation.version: 0.1.0-SNAPSHOT -> 1.1.0-RC.1
examples/echo/demo/pom.xml: printing.version: 1.0.0 -> 1.2.0-RC.1
examples/echo/demo/pom.xml: recordfiles.version: 0.1.0-SNAPSHOT -> 0.4.0-RC.1
examples/echo/demo/pom.xml: collaboration.version: 0.1.0-record-files-SNAPSHOT -> 1.2.0-RC.1
examples/echo/pom.xml: qqq.version: 4.1.0-RC.21 -> 4.1.0-RC.26
examples/echo/pom.xml: qqq-frontend-next: 1.0.0-RC.35 -> 1.0.0-RC.38
examples/echo/pom.xml: generation.version: 0.1.0-SNAPSHOT -> 1.1.0-RC.1
examples/echo/pom.xml: printing.version: 1.0.0 -> 1.2.0-RC.1
integrations/record-files/pom.xml: collaboration.version: 1.1.0-RC.1 -> 1.2.0-RC.1
integrations/record-files/pom.xml: recordfiles.version: 0.1.0-RC.1 -> 0.4.0-RC.1
pom.xml: parent -> 2.2.1
pom.xml: qqq.version: 4.1.0-RC.22 -> 4.1.0-RC.26

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 19:16:11 +00:00
10 changed files with 27 additions and 329 deletions

No files matched your search

@@ -117,8 +117,6 @@ public class MobileScannersRouteProvider implements QJavalinRouteProviderInterfa
{
try
{
// Tombstone only: the core handler that follows still owns the provider logout
// (including native logout data, which needs the core session intact) and session removal.
ExecutorSessionUtils.setupSession(context, instance);
MobileSessionService.recordLogout();
}
@@ -219,16 +219,13 @@ final class MobileSessionService
/***************************************************************************
** Standard logout remains usable by clients that predate session telemetry.
** The core /qqq/v1/logout handler that follows prepares any native provider
** logout data from the still-valid core session and then ends it, so the
** tombstone is recorded here without running that logout a second time.
***************************************************************************/
static void recordLogout() throws QException
{
QRecord binding = MobileService.get(MobileScannersQBitProducer.SESSION_BINDING, MobileService.hash(authenticatedUuid()));
if(binding != null)
{
end(binding.getValueString("sessionId"), "SIGN_OUT", false, true);
end(binding.getValueString("sessionId"), "SIGN_OUT", false);
}
}
@@ -238,17 +235,6 @@ final class MobileSessionService
** Persist the tombstone before calling provider cleanup; never trust a no-op.
***************************************************************************/
static Instant end(String id, String reason, boolean administrator) throws QException
{
return end(id, reason, administrator, false);
}
/***************************************************************************
** With coreLogoutFollows, the request's own core logout handler owns the
** provider logout and session removal: the status becomes DELEGATED.
***************************************************************************/
private static Instant end(String id, String reason, boolean administrator, boolean coreLogoutFollows) throws QException
{
synchronized(current())
{
@@ -277,13 +263,10 @@ final class MobileSessionService
current().screens.remove(id);
if(binding != null)
{
if(coreLogoutFollows)
String coreUuid = binding.getValueString("coreSessionUuid");
if(MobileService.TRANSACTION.get() == null)
{
update(new QRecord().withValue("id", id).withValue("authCleanupStatus", "DELEGATED").withValue("authCleanupAt", Instant.now()));
}
else if(MobileService.TRANSACTION.get() == null)
{
cleanupAuthentication(id, binding.getValueString("coreSessionUuid"));
cleanupAuthentication(id, coreUuid);
}
}
return endedAt;
@@ -7,26 +7,18 @@ package com.kingsrook.qbits.mobilescanners;
import java.io.Serializable;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionsHelper;
import com.kingsrook.qqq.backend.core.actions.processes.RunProcessAction;
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
@@ -51,21 +43,12 @@ import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.authentication.AuthScope;
import com.kingsrook.qqq.backend.core.model.metadata.authentication.QAuthenticationMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
import com.kingsrook.qqq.backend.core.model.session.QCredentialScope;
import com.kingsrook.qqq.backend.core.model.session.QSession;
import com.kingsrook.qqq.backend.core.model.session.QUser;
import com.kingsrook.qqq.backend.core.modules.authentication.QSessionStoreHelper;
import com.kingsrook.qqq.backend.core.modules.authentication.QSessionStoreProviderInterface;
import com.kingsrook.qqq.backend.core.modules.authentication.QSessionStoreRegistry;
import com.kingsrook.qqq.backend.core.modules.authentication.implementations.MockAuthenticationModule;
import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSBackendMetaData;
import com.kingsrook.qqq.backend.module.rdbms.model.metadata.RDBMSTableBackendDetails;
import com.kingsrook.qqq.middleware.javalin.specs.v1.LogoutSpecV1;
import com.kingsrook.qqq.middleware.javalin.specs.v1.MiddlewareVersionV1;
import io.javalin.Javalin;
import io.javalin.apibuilder.ApiBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -219,8 +202,6 @@ class MobileScannersTest
{
MobilePermissions.REQUEST_DEVICE.remove();
SessionMutator.hook = null;
QSessionStoreRegistry.getInstance().clear();
RecordingAuthenticationModule.LOGGED_OUT.clear();
QContext.clear();
}
@@ -1636,267 +1617,4 @@ class MobileScannersTest
{
return new HashMap<>(Map.of("eventId", UUID.randomUUID().toString(), "barcode", "00001234", "symbology", "CODE128", "scanSource", "datawedge", "capturedAt", "2026-10-29T12:00:00Z"));
}
/***************************************************************************
** Mock authentication that records every core session the logout executor ends.
***************************************************************************/
public static class RecordingAuthenticationModule extends MockAuthenticationModule
{
static final List<String> LOGGED_OUT = Collections.synchronizedList(new ArrayList<>());
/***************************************************************************
** Provider logout removes the stored core session, as the OAuth2 module does.
***************************************************************************/
@Override
public void logout(QInstance qInstance, String sessionUUID)
{
LOGGED_OUT.add(sessionUUID);
QSessionStoreHelper.removeSession(sessionUUID);
}
}
/***************************************************************************
** In-memory core session store that records removals in order.
***************************************************************************/
private static final class RecordingSessionStore implements QSessionStoreProviderInterface
{
private final Map<String, QSession> sessions = new ConcurrentHashMap<>();
private final List<String> removed = Collections.synchronizedList(new ArrayList<>());
/***************************************************************************
**
***************************************************************************/
@Override
public void store(String sessionUuid, QSession session, Duration ttl)
{
sessions.put(sessionUuid, session);
}
/***************************************************************************
**
***************************************************************************/
@Override
public Optional<QSession> load(String sessionUuid)
{
return Optional.ofNullable(sessions.get(sessionUuid));
}
/***************************************************************************
**
***************************************************************************/
@Override
public void remove(String sessionUuid)
{
removed.add(sessionUuid);
sessions.remove(sessionUuid);
}
/***************************************************************************
**
***************************************************************************/
@Override
public void touch(String sessionUuid)
{
}
/***************************************************************************
**
***************************************************************************/
@Override
public Duration getDefaultTtl()
{
return Duration.ofHours(1);
}
}
/***************************************************************************
** What the core logout handler found when it started handling one request.
***************************************************************************/
private record CoreLogoutObservation(boolean coreSessionPresent, int removalsBefore, int logoutsBefore)
{
}
/***************************************************************************
** Install the recording authentication module and core session store.
***************************************************************************/
private void recordCoreLogouts(RecordingSessionStore store)
{
instance.registerAuthenticationProvider(AuthScope.instanceDefault(), new QAuthenticationMetaData().withName("recording")
.withType(QAuthenticationType.CUSTOM).withModuleCodeReference(new QCodeReference(RecordingAuthenticationModule.class)));
QSessionStoreRegistry.getInstance().register(store);
}
/***************************************************************************
** The real route chain: scanner pre-handler, an observer, then core LogoutSpecV1.
***************************************************************************/
private Javalin logoutServer(RecordingSessionStore store, List<CoreLogoutObservation> observations)
{
recordCoreLogouts(store);
MobileScannersRouteProvider provider = new MobileScannersRouteProvider(instance);
return Javalin.create(config ->
{
config.jetty.host = "127.0.0.1";
config.routes.apiBuilder(provider.getJavalinEndpointGroup());
config.routes.apiBuilder(() ->
{
ApiBuilder.before("/qqq/v1/logout", context -> observations.add(new CoreLogoutObservation(
store.load(context.cookie("sessionUUID")).isPresent(), store.removed.size(), RecordingAuthenticationModule.LOGGED_OUT.size())));
LogoutSpecV1 logout = new LogoutSpecV1();
logout.setQInstance(instance);
logout.defineRoute(new MiddlewareVersionV1(), "v1");
});
}).start(0);
}
/***************************************************************************
** POST the core logout with the given session cookie.
***************************************************************************/
private HttpResponse<String> postLogout(Javalin server, String uuid, String body) throws Exception
{
HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:" + server.port() + "/qqq/v1/logout"))
.timeout(Duration.ofSeconds(10)).header("Cookie", "sessionUUID=" + uuid).header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body)).build();
return HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
}
/***************************************************************************
** Start an active heartbeat session whose core session is in the store.
***************************************************************************/
private String activeSession(RecordingSessionStore store) throws Exception
{
bind(approvedDevice());
String sessionId = (String) MobileSessionService.heartbeat(Map.of("foreground", true, "screenAvailable", true)).get("sessionId");
store.store(scanner.getUuid(), scanner, Duration.ofHours(1));
assertEquals("ACTIVE", MobileService.get(MobileScannersQBitProducer.SESSION, sessionId).getValueString("status"));
return sessionId;
}
/***************************************************************************
** Provider sign-out: the pre-handler tombstones the row but leaves the core
** session to the core handler, which prepares native logout data before
** ending it. Previously the pre-handler ended the core session first.
***************************************************************************/
@Test
void coreLogoutWithNativeLogoutKeepsCoreSessionUntilCoreHandlerRuns() throws Exception
{
RecordingSessionStore store = new RecordingSessionStore();
List<CoreLogoutObservation> observations = Collections.synchronizedList(new ArrayList<>());
Javalin server = logoutServer(store, observations);
try
{
String sessionId = activeSession(store);
var response = postLogout(server, scanner.getUuid(), "{\"nativeLogout\":{\"postLogoutRedirectUri\":\"qqq-mobile://logout\"}}");
assertEquals(200, response.statusCode());
assertEquals(1, observations.size());
assertTrue(observations.getFirst().coreSessionPresent(), "the pre-handler must not remove the core session");
assertEquals(0, observations.getFirst().removalsBefore());
assertEquals(0, observations.getFirst().logoutsBefore());
assertEquals(List.of(scanner.getUuid()), RecordingAuthenticationModule.LOGGED_OUT);
assertEquals(List.of(scanner.getUuid()), store.removed);
assertTrue(store.load(scanner.getUuid()).isEmpty());
QRecord session = MobileService.get(MobileScannersQBitProducer.SESSION, sessionId);
assertEquals("ENDED", session.getValueString("status"));
assertEquals("SIGN_OUT", session.getValueString("endReason"));
assertEquals("DELEGATED", session.getValueString("authCleanupStatus"));
assertNotNull(session.getValueInstant("authCleanupAt"));
assertNotNull(session.getValueInstant("endedAt"));
assertFalse(session.getValueBoolean("screenAvailable"));
assertFalse(session.getValueBoolean("foreground"));
assertThrows(QException.class, MobileSessionService::requireNotEnded);
}
finally
{
server.stop();
}
}
/***************************************************************************
** Ending the current session directly still runs the core logout itself.
***************************************************************************/
@Test
void endCurrentStillPerformsCoreLogout() throws Exception
{
RecordingSessionStore store = new RecordingSessionStore();
recordCoreLogouts(store);
String sessionId = activeSession(store);
Map<String, Object> ended = MobileSessionService.endCurrent(Map.of("reason", "SIGN_OUT"));
assertEquals(sessionId, ended.get("sessionId"));
assertEquals("ENDED", ended.get("status"));
assertEquals(List.of(scanner.getUuid()), RecordingAuthenticationModule.LOGGED_OUT);
// The provider logout and the service's own removal both clear the store; neither is skipped.
assertEquals(List.of(scanner.getUuid(), scanner.getUuid()), store.removed);
assertTrue(store.load(scanner.getUuid()).isEmpty());
QRecord session = MobileService.get(MobileScannersQBitProducer.SESSION, sessionId);
assertEquals("SIGN_OUT", session.getValueString("endReason"));
assertEquals("REQUESTED", session.getValueString("authCleanupStatus"));
assertNotNull(session.getValueInstant("authCleanupAt"));
assertThrows(QException.class, MobileSessionService::requireNotEnded);
}
/***************************************************************************
** Ordinary logout ends the mobile row and the core session exactly once, and
** an unbound cookie still reaches the core handler.
***************************************************************************/
@Test
void plainCoreLogoutEndsMobileRowAndCoreSessionOnce() throws Exception
{
RecordingSessionStore store = new RecordingSessionStore();
List<CoreLogoutObservation> observations = Collections.synchronizedList(new ArrayList<>());
Javalin server = logoutServer(store, observations);
try
{
String sessionId = activeSession(store);
var response = postLogout(server, scanner.getUuid(), "");
assertEquals(200, response.statusCode());
assertTrue(observations.getFirst().coreSessionPresent());
assertEquals(List.of(scanner.getUuid()), RecordingAuthenticationModule.LOGGED_OUT);
assertEquals(List.of(scanner.getUuid()), store.removed);
QRecord session = MobileService.get(MobileScannersQBitProducer.SESSION, sessionId);
assertEquals("ENDED", session.getValueString("status"));
assertEquals("SIGN_OUT", session.getValueString("endReason"));
assertEquals("DELEGATED", session.getValueString("authCleanupStatus"));
assertThrows(QException.class, MobileSessionService::requireNotEnded);
String unbound = UUID.randomUUID().toString();
assertEquals(200, postLogout(server, unbound, "").statusCode());
assertEquals(List.of(scanner.getUuid(), unbound), RecordingAuthenticationModule.LOGGED_OUT);
assertEquals("DELEGATED", MobileService.get(MobileScannersQBitProducer.SESSION, sessionId).getValueString("authCleanupStatus"));
}
finally
{
server.stop();
}
}
}
+3 -3
View File
@@ -7,7 +7,7 @@
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<qqq.version>4.1.0-RC.21</qqq.version>
<qqq.version>4.1.0-RC.26</qqq.version>
</properties>
<dependencyManagement>
<dependencies>
@@ -34,7 +34,7 @@
<dependency>
<groupId>com.kingsrook.qqq</groupId>
<artifactId>qqq-frontend-next</artifactId>
<version>1.0.0-RC.35</version>
<version>1.0.0-RC.38</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
@@ -78,7 +78,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
<version>3.5.6</version>
<configuration>
<systemPropertyVariables>
<qqq.logger.logSessionId.disabled>true</qqq.logger.logSessionId.disabled>
+2 -2
View File
@@ -39,9 +39,9 @@ Limits: the file store is the single-host demo adapter and the database is the d
## Session cleanup status
Ending a session (`MobileSessionService`) first persists the ended state with `authCleanupStatus = PENDING`. Cleanup then sets `REQUESTED` (with `authCleanupAt`) **before** calling the logout executor and removing the stored core session. If that call throws a `QException`, the status becomes `RETRY_NEEDED`. So `REQUESTED` means cleanup was attempted and no failure was reported; it is not independent proof that the provider session is gone. Cleanup is skipped when a binding does not exist, and for a single end inside an open transaction; a status left at `PENDING` also needs a retry. The bulk End Session process commits all tombstones first and runs cleanup afterwards. A sign-out through the core `POST /qqq/v1/logout` route sets `DELEGATED` (with `authCleanupAt`) instead: the scanner only tombstones the row, and the core logout handler in the same request prepares any native provider logout data and then ends the core session itself (the scanner no longer runs that logout first, which had removed the session before the core handler could read it). `DELEGATED` therefore means the core handler owned the cleanup; it needs no retry unless that core request failed.
Ending a session (`MobileSessionService`) first persists the ended state with `authCleanupStatus = PENDING`. Cleanup then sets `REQUESTED` (with `authCleanupAt`) **before** calling the logout executor and removing the stored core session. If that call throws a `QException`, the status becomes `RETRY_NEEDED`. So `REQUESTED` means cleanup was attempted and no failure was reported; it is not independent proof that the provider session is gone. Cleanup is skipped when a binding does not exist, and for a single end inside an open transaction; a status left at `PENDING` also needs a retry. The bulk End Session process commits all tombstones first and runs cleanup afterwards.
To retry: find sessions with `authCleanupStatus` of `RETRY_NEEDED` or `PENDING` (admin view of the session table), then run End Session again for them (that administrator end runs cleanup itself, also for a `DELEGATED` row whose core request failed). Ending an already ended session does not change its end time and reruns cleanup when a binding exists. Confirm the status reaches `REQUESTED`. There is no automatic monitor in this repository; the operator must check for these statuses.
To retry: find sessions with `authCleanupStatus` of `RETRY_NEEDED` or `PENDING` (admin view of the session table), then run End Session again for them. Ending an already ended session does not change its end time and reruns cleanup when a binding exists. Confirm the status reaches `REQUESTED`. There is no automatic monitor in this repository; the operator must check for these statuses.
## Retention
-1
View File
@@ -28,7 +28,6 @@ The [local demo](LOCAL-DEMO.md) source defaults remain QQQ `4.1.0-RC.21` and Pri
## Verification
- **Provider sign-out fix (2026-11-07, branch `fix/logout-keep-core-session-for-native-logout`).** On a physical MC9400 with the production 1.0.2 APK against a real Authentik fixture, company sign-out never received `nativeLogoutData` from `POST /qqq/v1/logout {"nativeLogout":...}` while a mobile session was active: the scanner's `/qqq/v1/logout` pre-handler ran the core logout executor and removed the stored core session before the core handler could prepare native logout data. The pre-handler now only tombstones the mobile session (`ENDED`, `SIGN_OUT`, `authCleanupStatus = DELEGATED`, see [OPERATIONS](OPERATIONS.md#session-cleanup-status)) and leaves the provider logout and session removal to the core handler in the same request. `/sessions/current/end` and administrator ends are unchanged. Three focused tests drive the real route chain (scanner pre-handler, then core `LogoutSpecV1`) with a recording authentication module and core session store. The OpenAPI contract and extension version are unchanged. Native Authentik sign-out on the device still needs a rerun with a build that includes this fix.
- Photo/admin change set (root-reported, not rerun in this review): 69 owner tests and 197 scanner/Echo tests passed (runs of 31, 158 and 8), 13 focused Android tests passed, and the relevant Checkstyle passed. These groupings differ from the module split below, so no per-module counts are claimed. Public immutable dependency qualification is still pending.
- Live evidence: a fresh synthetic gallery PNG uploaded from the production-signed MC9400 app returned "Saved photo", and the server showed `AVAILABLE` with the exact parent, type, size and SHA-256. An older photo's Available state, thumbnail and Preview control were observed. The new photo's full preview was not clicked because ADB disconnected. No camera-hardware or full-preview proof is claimed.
- The earlier combined five-module `verify` (2026-11-05, base `9e8685f` plus the storage fixes) passed **196 server tests** with zero failures, errors and skips and zero Checkstyle violations: scanner 53, base demo 8, mobile Record Files 22, Echo 74, Echo demo 39. It used qualified private owner dependencies; there is no public-dependency or physical-output qualification, and the gate must be repeated when the public cohort is adopted. The new build parent's report-only schema-location/contract-test findings remain visible.
+7 -7
View File
@@ -16,15 +16,15 @@
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<qqq.version>4.1.0-RC.21</qqq.version>
<qqq.version>4.1.0-RC.26</qqq.version>
<mobile.version>0.1.0-SNAPSHOT</mobile.version>
<echo.version>0.1.0-SNAPSHOT</echo.version>
<generation.version>0.1.0-SNAPSHOT</generation.version>
<generation.version>1.1.0-RC.1</generation.version>
<renderer.version>${generation.version}</renderer.version>
<printing.version>1.0.0</printing.version>
<recordfiles.version>0.1.0-SNAPSHOT</recordfiles.version>
<printing.version>1.2.0-RC.1</printing.version>
<recordfiles.version>0.4.0-RC.1</recordfiles.version>
<mobilerecordfiles.version>0.1.0-SNAPSHOT</mobilerecordfiles.version>
<collaboration.version>0.1.0-record-files-SNAPSHOT</collaboration.version>
<collaboration.version>1.2.0-RC.1</collaboration.version>
</properties>
<dependencyManagement><dependencies>
<dependency><groupId>com.kingsrook.qqq</groupId><artifactId>qqq-bom-pom</artifactId><version>${qqq.version}</version><type>pom</type><scope>import</scope></dependency>
@@ -40,14 +40,14 @@
<dependency><groupId>com.kingsrook.qbits</groupId><artifactId>qbit-mobile-scanners-record-files</artifactId><version>${mobilerecordfiles.version}</version></dependency>
<dependency><groupId>com.kingsrook.qbits</groupId><artifactId>qbit-collaboration</artifactId><version>${collaboration.version}</version></dependency>
<dependency><groupId>com.kingsrook.qqq</groupId><artifactId>qqq-backend-module-rdbms</artifactId></dependency>
<dependency><groupId>com.kingsrook.qqq</groupId><artifactId>qqq-frontend-next</artifactId><version>1.0.0-RC.35</version></dependency>
<dependency><groupId>com.kingsrook.qqq</groupId><artifactId>qqq-frontend-next</artifactId><version>1.0.0-RC.38</version></dependency>
<dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><version>2.2.224</version></dependency>
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>6.0.2</version><scope>test</scope></dependency>
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>6.0.2</version><scope>test</scope></dependency>
</dependencies>
<build><plugins>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.13.0</version><configuration><showWarnings>true</showWarnings><failOnWarning>true</failOnWarning><proc>none</proc><compilerArgs><arg>-Xlint:deprecation</arg><arg>-Xlint:unchecked</arg><arg>-Werror</arg></compilerArgs></configuration></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.2</version><configuration><systemPropertyVariables><qqq.logger.logSessionId.disabled>true</qqq.logger.logSessionId.disabled></systemPropertyVariables></configuration></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.6</version><configuration><systemPropertyVariables><qqq.logger.logSessionId.disabled>true</qqq.logger.logSessionId.disabled></systemPropertyVariables></configuration></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><version>3.8.1</version></plugin>
<plugin><groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>3.5.0</version><configuration><mainClass>com.kingsrook.examples.echo.demo.EchoDemo</mainClass></configuration></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-checkstyle-plugin</artifactId><version>3.6.0</version><dependencies><dependency><groupId>com.puppycrawl.tools</groupId><artifactId>checkstyle</artifactId><version>14.3.0</version></dependency></dependencies><configuration><configLocation>${project.basedir}/../../../checkstyle/checkstyle.xml</configLocation><includeTestSourceDirectory>true</includeTestSourceDirectory><failOnViolation>true</failOnViolation><violationSeverity>warning</violationSeverity></configuration><executions><execution><phase>validate</phase><goals><goal>check</goal></goals></execution></executions></plugin>
+5 -5
View File
@@ -16,15 +16,15 @@
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<qqq.version>4.1.0-RC.21</qqq.version>
<qqq.version>4.1.0-RC.26</qqq.version>
<mobile.version>0.1.0-SNAPSHOT</mobile.version>
<!-- Echo's copies per scan needs a Generation build with the print-copies change (appended copies on
DocumentGenerationService.Request and GenerationPorts.PrintRequest, supportsCopies on the printing bridge,
migration 20261102-print-copies-h2.sql). Printing 1.0.0 is released and qualified; only the Generation
cohort still needs a coherent published input. Until that is published at this coordinate, override
generation.version with a coherent build that has it; no private build is named here. -->
<generation.version>0.1.0-SNAPSHOT</generation.version>
<printing.version>1.0.0</printing.version>
<generation.version>1.1.0-RC.1</generation.version>
<printing.version>1.2.0-RC.1</printing.version>
</properties>
<dependencyManagement><dependencies>
<dependency><groupId>com.kingsrook.qqq</groupId><artifactId>qqq-bom-pom</artifactId><version>${qqq.version}</version><type>pom</type><scope>import</scope></dependency>
@@ -40,12 +40,12 @@
<dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><version>42.7.8</version><scope>test</scope></dependency>
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>6.0.2</version><scope>test</scope></dependency>
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>6.0.2</version><scope>test</scope></dependency>
<dependency><groupId>com.kingsrook.qqq</groupId><artifactId>qqq-frontend-next</artifactId><version>1.0.0-RC.35</version><scope>test</scope></dependency>
<dependency><groupId>com.kingsrook.qqq</groupId><artifactId>qqq-frontend-next</artifactId><version>1.0.0-RC.38</version><scope>test</scope></dependency>
<dependency><groupId>com.kingsrook.qbits</groupId><artifactId>qbit-mobile-scanners-demo</artifactId><version>${mobile.version}</version><scope>test</scope></dependency>
</dependencies>
<build><resources><resource><directory>src/main/resources</directory><filtering>false</filtering></resource><resource><directory>${project.basedir}/../..</directory><filtering>false</filtering><includes><include>LICENSE</include><include>NOTICE</include></includes><targetPath>META-INF/qqq-echo</targetPath></resource></resources><plugins>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.13.0</version><configuration><showWarnings>true</showWarnings><failOnWarning>true</failOnWarning><proc>none</proc><compilerArgs><arg>-Xlint:deprecation</arg><arg>-Xlint:unchecked</arg><arg>-Werror</arg></compilerArgs></configuration></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.2</version></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.6</version></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-checkstyle-plugin</artifactId><version>3.6.0</version><dependencies><dependency><groupId>com.puppycrawl.tools</groupId><artifactId>checkstyle</artifactId><version>14.3.0</version></dependency></dependencies><configuration><configLocation>${project.basedir}/../../checkstyle/checkstyle.xml</configLocation><includeTestSourceDirectory>true</includeTestSourceDirectory><failOnViolation>true</failOnViolation><violationSeverity>warning</violationSeverity></configuration><executions><execution><phase>validate</phase><goals><goal>check</goal></goals></execution></executions></plugin>
</plugins></build>
</project>
+3 -3
View File
@@ -30,8 +30,8 @@
<properties>
<!-- the base module is built in the same reactor; the others are published releases from the Gitea registry -->
<mobile.version>${project.version}</mobile.version>
<recordfiles.version>0.1.0-RC.1</recordfiles.version>
<collaboration.version>1.1.0-RC.1</collaboration.version>
<recordfiles.version>0.4.0-RC.1</recordfiles.version>
<collaboration.version>1.2.0-RC.1</collaboration.version>
</properties>
<dependencyManagement><dependencies>
<dependency><groupId>com.kingsrook.qqq</groupId><artifactId>qqq-bom-pom</artifactId><version>${qqq.version}</version><type>pom</type><scope>import</scope></dependency>
@@ -49,7 +49,7 @@
</dependencies>
<build><plugins>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.13.0</version></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.2</version><configuration><systemPropertyVariables><qqq.logger.logSessionId.disabled>true</qqq.logger.logSessionId.disabled></systemPropertyVariables></configuration></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.5.6</version><configuration><systemPropertyVariables><qqq.logger.logSessionId.disabled>true</qqq.logger.logSessionId.disabled></systemPropertyVariables></configuration></plugin>
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-checkstyle-plugin</artifactId><version>3.6.0</version>
<dependencies><dependency><groupId>com.puppycrawl.tools</groupId><artifactId>checkstyle</artifactId><version>14.3.0</version></dependency></dependencies>
<configuration><configLocation>${maven.multiModuleProjectDirectory}/checkstyle/checkstyle.xml</configLocation><includeTestSourceDirectory>true</includeTestSourceDirectory><failOnViolation>true</failOnViolation><violationSeverity>warning</violationSeverity></configuration>
+3 -3
View File
@@ -6,7 +6,7 @@
<parent>
<groupId>com.kingsrook</groupId>
<artifactId>qbit-build-parent</artifactId>
<version>2.1.0</version>
<version>2.2.1</version>
<relativePath />
</parent>
<groupId>com.kingsrook.qbits</groupId>
@@ -34,10 +34,10 @@
</license>
</licenses>
<properties>
<revision>0.5.0-SNAPSHOT</revision>
<revision>0.6.0-SNAPSHOT</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<qqq.version>4.1.0-RC.22</qqq.version>
<qqq.version>4.1.0-RC.26</qqq.version>
</properties>
<!-- Every published module, so one root deploy builds every GAV. demo/ and examples/ are runnable demonstrations with their own coordinates and are intentionally
not part of this reactor. Build a subset with -pl <module> -am. -->