Require setting DB kind for additional datasources (#41087)

* Require setting DB kind for additional datasources

Closes #41161

Signed-off-by: Martin Bartoš <mabartos@redhat.com>

* refining build time check for db kind to be tolerant of existing usage

Signed-off-by: Steve Hawkins <shawkins@redhat.com>

---------

Signed-off-by: Martin Bartoš <mabartos@redhat.com>
Signed-off-by: Steve Hawkins <shawkins@redhat.com>
Co-authored-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
Martin Bartoš 2025-07-29 14:48:28 +02:00 committed by GitHub
parent 71f510d115
commit 75ade9acef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 173 additions and 43 deletions

View File

@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer;
public class DatabaseOptions { public class DatabaseOptions {
@ -143,6 +144,13 @@ public class DatabaseOptions {
DatabaseOptions.DB_URL.getKey(), "-full" // db-url-full DatabaseOptions.DB_URL.getKey(), "-full" // db-url-full
); );
/**
* You can override some {@link OptionBuilder} methods for additional datasources in this map
*/
private static final Map<Option<?>, Consumer<OptionBuilder<?>>> DATASOURCES_OVERRIDES_OPTIONS = Map.of(
DatabaseOptions.DB, builder -> builder.defaultValue(Optional.empty()) // no default value for DB kind for datasources
);
private static final Map<String, Option<?>> cachedDatasourceOptions = new HashMap<>(); private static final Map<String, Option<?>> cachedDatasourceOptions = new HashMap<>();
@ -179,6 +187,12 @@ public class DatabaseOptions {
builder.description("Used for named <datasource>. " + parentOption.getDescription()); builder.description("Used for named <datasource>. " + parentOption.getDescription());
} }
// override some settings for options
var override = DATASOURCES_OVERRIDES_OPTIONS.get(parentOption);
if (override != null) {
override.accept(builder);
}
option = builder.build(); option = builder.build();
cachedDatasourceOptions.put(key.get(), option); cachedDatasourceOptions.put(key.get(), option);
} }

View File

@ -107,12 +107,15 @@ import org.keycloak.provider.Spi;
import org.keycloak.quarkus.runtime.Environment; import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.KeycloakRecorder; import org.keycloak.quarkus.runtime.KeycloakRecorder;
import org.keycloak.quarkus.runtime.cli.Picocli; import org.keycloak.quarkus.runtime.cli.Picocli;
import org.keycloak.quarkus.runtime.cli.PropertyException;
import org.keycloak.quarkus.runtime.configuration.Configuration; import org.keycloak.quarkus.runtime.configuration.Configuration;
import org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider; import org.keycloak.quarkus.runtime.configuration.KeycloakConfigSourceProvider;
import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider; import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider;
import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource; import org.keycloak.quarkus.runtime.configuration.PersistedConfigSource;
import org.keycloak.quarkus.runtime.configuration.PropertyMappingInterceptor;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper; import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper;
import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers; import org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers;
import org.keycloak.quarkus.runtime.configuration.mappers.WildcardPropertyMapper;
import org.keycloak.quarkus.runtime.integration.resteasy.KeycloakHandlerChainCustomizer; import org.keycloak.quarkus.runtime.integration.resteasy.KeycloakHandlerChainCustomizer;
import org.keycloak.quarkus.runtime.integration.resteasy.KeycloakTracingCustomizer; import org.keycloak.quarkus.runtime.integration.resteasy.KeycloakTracingCustomizer;
import org.keycloak.quarkus.runtime.logging.ClearMappedDiagnosticContextFilter; import org.keycloak.quarkus.runtime.logging.ClearMappedDiagnosticContextFilter;
@ -171,6 +174,7 @@ import static org.keycloak.quarkus.runtime.configuration.Configuration.getOption
import static org.keycloak.quarkus.runtime.configuration.Configuration.getOptionalKcValue; import static org.keycloak.quarkus.runtime.configuration.Configuration.getOptionalKcValue;
import static org.keycloak.quarkus.runtime.configuration.Configuration.getOptionalValue; import static org.keycloak.quarkus.runtime.configuration.Configuration.getOptionalValue;
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX; import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX;
import static org.keycloak.quarkus.runtime.storage.database.jpa.QuarkusJpaConnectionProviderFactory.DEFAULT_PERSISTENCE_UNIT;
import static org.keycloak.quarkus.runtime.storage.database.jpa.QuarkusJpaConnectionProviderFactory.QUERY_PROPERTY_PREFIX; import static org.keycloak.quarkus.runtime.storage.database.jpa.QuarkusJpaConnectionProviderFactory.QUERY_PROPERTY_PREFIX;
import static org.keycloak.representations.provider.ScriptProviderDescriptor.AUTHENTICATORS; import static org.keycloak.representations.provider.ScriptProviderDescriptor.AUTHENTICATORS;
import static org.keycloak.representations.provider.ScriptProviderDescriptor.MAPPERS; import static org.keycloak.representations.provider.ScriptProviderDescriptor.MAPPERS;
@ -370,6 +374,59 @@ class KeycloakProcessor {
recorder.setDefaultUserProfileConfiguration(configuration.getDefaultConfig()); recorder.setDefaultUserProfileConfiguration(configuration.getDefaultConfig());
} }
@BuildStep
@Produce(ValidatePersistenceUnitsBuildItem.class)
void checkPersistenceUnits(List<PersistenceXmlDescriptorBuildItem> descriptors) {
List<String> notSetPersistenceUnitsDBKinds = descriptors.stream()
.map(PersistenceXmlDescriptorBuildItem::getDescriptor)
.filter(descriptor -> !descriptor.getName().equals(DEFAULT_PERSISTENCE_UNIT)) // not default persistence unit
.map(KeycloakProcessor::getDatasourceNameFromPersistenceXml)
.filter(this::missingDbKind)
.map(datasourceName -> DatabaseOptions.getNamedKey(DatabaseOptions.DB, datasourceName).orElseThrow()).toList();
if (!notSetPersistenceUnitsDBKinds.isEmpty()) {
throwConfigError("Detected additional named datasources without a DB kind set, please specify: %s".formatted(String.join(",", notSetPersistenceUnitsDBKinds)));
}
}
/**
* Try to find if DB kind is specified for the descriptor name.
* <p>
* Check it in order:
* <ol>
* <li> {@code db-kind-<descriptorName}
* <li> {@code quarkus.datasource."<descriptorName>".db-kind}
* <li> {@code quarkus.datasource.<descriptorName>.db-kind}
* </ol>
*/
private boolean missingDbKind(String datasourceName) {
String key = NS_KEYCLOAK_PREFIX.concat(DatabaseOptions.getNamedKey(DatabaseOptions.DB, datasourceName).orElseThrow());
PropertyMappingInterceptor.disable();
try {
var from = Configuration.getConfigValue(key);
if (from.getValue() != null) {
return false; // user has directly specified
}
WildcardPropertyMapper<?> mapper = (WildcardPropertyMapper<?>)PropertyMappers.getMapper(key);
// quarkus properties
boolean missing = Configuration.getOptionalValue(mapper.getTo(datasourceName))
.or(() -> Configuration.getOptionalValue(mapper.getTo(datasourceName).replaceAll("\"", "")))
.isEmpty();
if (!missing) {
logger.warnf(
"You have set DB kind for '%s' datasource via a Quarkus property. This approach is deprecated and you should use the Keycloak 'db-kind-%s' property.",
datasourceName, datasourceName);
}
return missing;
} finally {
PropertyMappingInterceptor.enable();
}
}
/** /**
* Get datasource name obtained from the persistence.xml file based on this order: * Get datasource name obtained from the persistence.xml file based on this order:
* <ol> * <ol>
@ -423,6 +480,7 @@ class KeycloakProcessor {
* @param descriptors * @param descriptors
*/ */
@BuildStep @BuildStep
@Consume(ValidatePersistenceUnitsBuildItem.class)
@Record(ExecutionTime.RUNTIME_INIT) @Record(ExecutionTime.RUNTIME_INIT)
void configurePersistenceUnits(HibernateOrmConfig config, void configurePersistenceUnits(HibernateOrmConfig config,
List<PersistenceXmlDescriptorBuildItem> descriptors, List<PersistenceXmlDescriptorBuildItem> descriptors,
@ -437,7 +495,7 @@ class KeycloakProcessor {
for (PersistenceXmlDescriptorBuildItem item : descriptors) { for (PersistenceXmlDescriptorBuildItem item : descriptors) {
ParsedPersistenceXmlDescriptor descriptor = (ParsedPersistenceXmlDescriptor) item.getDescriptor(); ParsedPersistenceXmlDescriptor descriptor = (ParsedPersistenceXmlDescriptor) item.getDescriptor();
if ("keycloak-default".equals(descriptor.getName())) { if (DEFAULT_PERSISTENCE_UNIT.equals(descriptor.getName())) {
defaultUnitDescriptor = descriptor; defaultUnitDescriptor = descriptor;
configureDefaultPersistenceUnitProperties(defaultUnitDescriptor, config, getDefaultDataSource(jdbcDataSources)); configureDefaultPersistenceUnitProperties(defaultUnitDescriptor, config, getDefaultDataSource(jdbcDataSources));
runtimeConfigured.produce(new HibernateOrmIntegrationRuntimeConfiguredBuildItem("keycloak", defaultUnitDescriptor.getName()) runtimeConfigured.produce(new HibernateOrmIntegrationRuntimeConfiguredBuildItem("keycloak", defaultUnitDescriptor.getName())
@ -627,7 +685,7 @@ class KeycloakProcessor {
descriptors.stream() descriptors.stream()
.map(PersistenceXmlDescriptorBuildItem::getDescriptor) .map(PersistenceXmlDescriptorBuildItem::getDescriptor)
.map(PersistenceUnitDescriptor::getName) .map(PersistenceUnitDescriptor::getName)
.filter(Predicate.not("keycloak-default"::equals)) .filter(Predicate.not(DEFAULT_PERSISTENCE_UNIT::equals))
.forEach((String unitName) -> { .forEach((String unitName) -> {
NamedJpaConnectionProviderFactory factory = new NamedJpaConnectionProviderFactory(); NamedJpaConnectionProviderFactory factory = new NamedJpaConnectionProviderFactory();

View File

@ -0,0 +1,6 @@
package org.keycloak.quarkus.deployment;
import io.quarkus.builder.item.EmptyBuildItem;
public final class ValidatePersistenceUnitsBuildItem extends EmptyBuildItem {
}

View File

@ -24,16 +24,6 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Stream; import java.util.stream.Stream;
import io.agroal.api.AgroalDataSource;
import io.quarkus.agroal.DataSource;
import io.quarkus.arc.Arc;
import io.quarkus.arc.InstanceHandle;
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrationRuntimeInitListener;
import io.quarkus.runtime.annotations.Recorder;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import liquibase.Scope;
import liquibase.servicelocator.ServiceLocator;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.infinispan.protostream.SerializationContextInitializer; import org.infinispan.protostream.SerializationContextInitializer;
import org.keycloak.Config; import org.keycloak.Config;
@ -56,6 +46,17 @@ import org.keycloak.theme.ClasspathThemeProviderFactory;
import org.keycloak.truststore.TruststoreBuilder; import org.keycloak.truststore.TruststoreBuilder;
import org.keycloak.userprofile.DeclarativeUserProfileProviderFactory; import org.keycloak.userprofile.DeclarativeUserProfileProviderFactory;
import io.agroal.api.AgroalDataSource;
import io.quarkus.agroal.DataSource;
import io.quarkus.arc.Arc;
import io.quarkus.arc.InstanceHandle;
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrationRuntimeInitListener;
import io.quarkus.runtime.annotations.Recorder;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import liquibase.Scope;
import liquibase.servicelocator.ServiceLocator;
@Recorder @Recorder
public class KeycloakRecorder { public class KeycloakRecorder {

View File

@ -109,6 +109,7 @@ final class DatabasePropertyMappers {
return appendDatasourceMappers(mappers, Map.of( return appendDatasourceMappers(mappers, Map.of(
// Inherit options from the DB mappers // Inherit options from the DB mappers
DatabaseOptions.DB, PropertyMapper.Builder::removeMapFrom,
DatabaseOptions.DB_POOL_INITIAL_SIZE, mapper -> mapper.mapFrom(DatabaseOptions.DB_POOL_INITIAL_SIZE), DatabaseOptions.DB_POOL_INITIAL_SIZE, mapper -> mapper.mapFrom(DatabaseOptions.DB_POOL_INITIAL_SIZE),
DatabaseOptions.DB_POOL_MAX_SIZE, mapper -> mapper.mapFrom(DatabaseOptions.DB_POOL_MAX_SIZE) DatabaseOptions.DB_POOL_MAX_SIZE, mapper -> mapper.mapFrom(DatabaseOptions.DB_POOL_MAX_SIZE)
)); ));

View File

@ -379,6 +379,11 @@ public class PropertyMapper<T> {
return this; return this;
} }
public Builder<T> removeMapFrom() {
this.mapFrom = null;
return this;
}
public Builder<T> mapFrom(Option<?> mapFrom) { public Builder<T> mapFrom(Option<?> mapFrom) {
this.mapFrom = mapFrom.getKey(); this.mapFrom = mapFrom.getKey();
return this; return this;

View File

@ -66,7 +66,7 @@ public class WildcardPropertyMapper<T> extends PropertyMapper<T> {
return true; return true;
} }
String getTo(String wildcardKey) { public String getTo(String wildcardKey) {
return toPrefix + wildcardKey + toSuffix; return toPrefix + wildcardKey + toSuffix;
} }

View File

@ -61,6 +61,7 @@ import org.keycloak.quarkus.runtime.Environment;
public class QuarkusJpaConnectionProviderFactory extends AbstractJpaConnectionProviderFactory implements ServerInfoAwareProviderFactory { public class QuarkusJpaConnectionProviderFactory extends AbstractJpaConnectionProviderFactory implements ServerInfoAwareProviderFactory {
public static final String QUERY_PROPERTY_PREFIX = "kc.query."; public static final String QUERY_PROPERTY_PREFIX = "kc.query.";
public static final String DEFAULT_PERSISTENCE_UNIT = "keycloak-default";
private static final Logger logger = Logger.getLogger(QuarkusJpaConnectionProviderFactory.class); private static final Logger logger = Logger.getLogger(QuarkusJpaConnectionProviderFactory.class);
private static final String SQL_GET_LATEST_VERSION = "SELECT ID, VERSION FROM %sMIGRATION_MODEL ORDER BY UPDATE_TIME DESC"; private static final String SQL_GET_LATEST_VERSION = "SELECT ID, VERSION FROM %sMIGRATION_MODEL ORDER BY UPDATE_TIME DESC";
@ -165,7 +166,7 @@ public class QuarkusJpaConnectionProviderFactory extends AbstractJpaConnectionPr
return instance.get(); return instance.get();
} }
return getEntityManagerFactory("keycloak-default").orElseThrow(() -> new IllegalStateException("Failed to resolve the default entity manager factory")); return getEntityManagerFactory(DEFAULT_PERSISTENCE_UNIT).orElseThrow(() -> new IllegalStateException("Failed to resolve the default entity manager factory"));
} }
@Override @Override

View File

@ -235,8 +235,8 @@ public class DatasourcesConfigurationTest extends AbstractConfigurationTest {
ConfigArgsConfigSource.setCliArgs(""); ConfigArgsConfigSource.setCliArgs("");
initConfig(); initConfig();
assertConfig("db-dialect-clients", H2Dialect.class.getName()); assertConfigNull("db-dialect-clients");
assertExternalConfig("quarkus.datasource.\"clients\".jdbc.url", "jdbc:h2:file:test-dir/data/h2/keycloakdb-clients;;test=test;test1=test1;NON_KEYWORDS=VALUE;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=0"); assertConfigNull("quarkus.datasource.\"clients\".jdbc.url", true);
onAfter(); onAfter();
System.setProperty("kc.db-url-properties-users", "?test=test&test1=test1"); System.setProperty("kc.db-url-properties-users", "?test=test&test1=test1");
@ -293,6 +293,13 @@ public class DatasourcesConfigurationTest extends AbstractConfigurationTest {
ConfigArgsConfigSource.setCliArgs(""); ConfigArgsConfigSource.setCliArgs("");
initConfig(); initConfig();
assertConfigNull("db-pool-initial-size-clients");
assertConfigNull("db-pool-min-size-clients");
assertConfig("db-pool-max-size-clients", "100");
ConfigArgsConfigSource.setCliArgs("--db-kind-clients=dev-mem");
initConfig();
assertConfigNull("db-pool-initial-size-clients"); assertConfigNull("db-pool-initial-size-clients");
assertConfig(Map.of( assertConfig(Map.of(
"db-pool-min-size-clients", "1", "db-pool-min-size-clients", "1",
@ -326,6 +333,12 @@ public class DatasourcesConfigurationTest extends AbstractConfigurationTest {
ConfigArgsConfigSource.setCliArgs("--db-pool-initial-size-clients=10"); ConfigArgsConfigSource.setCliArgs("--db-pool-initial-size-clients=10");
initConfig(); initConfig();
assertConfigNull("db-pool-min-size-clients");
assertConfig("db-pool-initial-size-clients", "10");
onAfter();
ConfigArgsConfigSource.setCliArgs("--db-pool-initial-size-clients=10", "--db-kind-clients=dev-file");
initConfig();
assertConfig(Map.of( assertConfig(Map.of(
"db-pool-min-size-clients", "1", // set 1 for H2 "db-pool-min-size-clients", "1", // set 1 for H2
"db-pool-initial-size-clients", "10" "db-pool-initial-size-clients", "10"

View File

@ -20,14 +20,19 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.0"> version="3.0">
<persistence-unit name="user-store" transaction-type="JTA"> <persistence-unit name="new-user-store" transaction-type="JTA">
<class>com.acme.provider.legacy.jpa.entity.Realm</class> <class>com.acme.provider.legacy.jpa.entity.Realm</class>
<properties> <properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" /> <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<!-- Sets the name of the datasource to be the same as the datasource name in quarkus.properties--> <property name="jakarta.persistence.jtaDataSource" value="new-user-store" />
<property name="jakarta.persistence.jtaDataSource" value="user-store" />
<property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="false" /> <property name="hibernate.show_sql" value="false" />
</properties> </properties>
</persistence-unit> </persistence-unit>
<persistence-unit name="client-store" transaction-type="JTA">
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
</properties>
</persistence-unit>
</persistence> </persistence>

View File

@ -15,7 +15,4 @@
# limitations under the License. # limitations under the License.
# #
quarkus.datasource.user-store.db-kind=h2 quarkus.datasource.client-store.db-kind=h2
quarkus.datasource.user-store.username=sa
quarkus.datasource.user-store.jdbc.url=jdbc:h2:mem:user-store;DB_CLOSE_DELAY=-1
quarkus.datasource.user-store.jdbc.transactions=xa

View File

@ -26,19 +26,44 @@ import org.keycloak.it.junit5.extension.TestProvider;
import com.acme.provider.legacy.jpa.entity.CustomJpaEntityProvider; import com.acme.provider.legacy.jpa.entity.CustomJpaEntityProvider;
import io.quarkus.test.junit.main.Launch; import io.quarkus.test.junit.main.Launch;
import org.keycloak.it.utils.KeycloakDistribution;
@DistributionTest @DistributionTest
@RawDistOnly(reason = "Containers are immutable") @RawDistOnly(reason = "Containers are immutable")
@Tag(DistributionTest.SMOKE) @Tag(DistributionTest.SMOKE)
@TestProvider(CustomJpaEntityProvider.class)
public class CustomJpaEntityProviderDistTest { public class CustomJpaEntityProviderDistTest {
@Test @Test
@TestProvider(CustomJpaEntityProvider.class) void dbKindSpecifiedInBuildTime(KeycloakDistribution dist) {
@Launch({ "start-dev", "--log-level=org.hibernate.jpa.internal.util.LogHelper:debug,org.keycloak.quarkus.deployment.KeycloakProcessor:debug" }) var result = dist.run("build", "--db=dev-file", "--db-kind-new-user-store=dev-mem");
result.assertMessage("Multiple datasources are specified: <default>, client-store, new-user-store");
result.assertMessage("You have set DB kind for 'client-store' datasource via a Quarkus property. This approach is deprecated and you should use the Keycloak 'db-kind-client-store' property.");
result.assertBuild();
result = dist.run("start", "--optimized", "--http-enabled=true", "--hostname-strict=false");
result.assertNoError("Detected additional named datasources. You need to explicitly set the DB kind for the datasource(s) to properly work as: db-kind-user-store");
// Remove once https://github.com/keycloak/keycloak/pull/41026 is solved
result.assertError("Datasource 'new-user-store' was deactivated automatically because its URL is not set");
}
@Test
@Launch({"start-dev", "--db=dev-file"})
void notSpecifiedDbKind(CLIResult cliResult) {
// it is printed at build time and the check done at runtime
cliResult.assertNoMessage("Multiple datasources are specified: <default>, client-store, user-store");
cliResult.assertError("Detected additional named datasources without a DB kind set, please specify: db-kind-new-user-store");
}
@Test
@Launch({"start-dev", "--db=dev-file", "--log-level=org.hibernate.jpa.internal.util.LogHelper:debug,org.keycloak.quarkus.deployment.KeycloakProcessor:debug", "--db-kind-new-user-store=dev-mem", "--db-kind-client-store=dev-mem"})
void testUserManagedEntityNotAddedToDefaultPU(CLIResult cliResult) { void testUserManagedEntityNotAddedToDefaultPU(CLIResult cliResult) {
cliResult.assertMessage("Multiple datasources are specified: <default>, user-store"); cliResult.assertMessage("Multiple datasources are specified: <default>, client-store, new-user-store");
cliResult.assertMessage("Datasource name 'user-store' is obtained from the 'jakarta.persistence.jtaDataSource' configuration property in persistence.xml file. Use 'user-store' name for datasource options like 'db-kind-user-store'."); cliResult.assertMessage("Datasource name 'client-store' is obtained from the 'Persistence unit name' configuration property in persistence.xml file. Use 'client-store' name for datasource options like 'db-kind-client-store'.");
cliResult.assertStringCount("name: user-store", 1); cliResult.assertMessage("Datasource name 'new-user-store' is obtained from the 'jakarta.persistence.jtaDataSource' configuration property in persistence.xml file. Use 'new-user-store' name for datasource options like 'db-kind-new-user-store'.");
cliResult.assertStringCount("name: new-user-store", 1);
cliResult.assertStringCount("name: client-store", 1);
cliResult.assertStringCount("com.acme.provider.legacy.jpa.entity.Realm", 1); cliResult.assertStringCount("com.acme.provider.legacy.jpa.entity.Realm", 1);
cliResult.assertStartedDevMode(); cliResult.assertStartedDevMode();
} }

View File

@ -85,7 +85,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -87,7 +87,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -36,7 +36,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
Transaction: Transaction:

View File

@ -80,7 +80,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -80,7 +80,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -80,7 +80,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -80,7 +80,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -122,7 +122,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -189,7 +189,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -170,7 +170,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -190,7 +190,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -169,7 +169,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -189,7 +189,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -167,7 +167,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -187,7 +187,7 @@ Database - additional datasources (Preview):
Preview: Used for named <datasource>. The database vendor. In production mode Preview: Used for named <datasource>. The database vendor. In production mode
the default value of 'dev-file' is deprecated, you should explicitly specify the default value of 'dev-file' is deprecated, you should explicitly specify
the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql, the db instead. Possible values are: dev-file, dev-mem, mariadb, mssql,
mysql, oracle, postgres. Default: dev-file. mysql, oracle, postgres.
--db-log-slow-queries-threshold-<datasource> <milliseconds> --db-log-slow-queries-threshold-<datasource> <milliseconds>
Preview: Used for named <datasource>. Log SQL statements slower than the Preview: Used for named <datasource>. Log SQL statements slower than the
configured threshold with logger org.hibernate.SQL_SLOW and log-level info. configured threshold with logger org.hibernate.SQL_SLOW and log-level info.

View File

@ -85,6 +85,10 @@ public interface CLIResult extends LaunchResult {
getErrorOutput(), not(containsString(msg))); getErrorOutput(), not(containsString(msg)));
} }
default void assertWarning(String msg) {
assertError(msg); //seems that warnings are printed on stderr
}
default void assertExitCode(int code) { default void assertExitCode(int code) {
assertThat("Exit codes do not match: ", exitCode(), is(code)); assertThat("Exit codes do not match: ", exitCode(), is(code));
} }