Additional datasources now require XA (#32403)
* Additional datasources now require XA Closes #32402 Signed-off-by: Václav Muzikář <vmuzikar@redhat.com> * Apply suggestions from code review Co-authored-by: Steven Hawkins <shawkins@redhat.com> Signed-off-by: Václav Muzikář <vaclav@muzikari.cz> * Relax validation Signed-off-by: Václav Muzikář <vmuzikar@redhat.com> * Added a note on recovery Signed-off-by: Václav Muzikář <vmuzikar@redhat.com> * Fix `CustomJpaEntityProviderDistTest` Signed-off-by: Václav Muzikář <vmuzikar@redhat.com> --------- Signed-off-by: Václav Muzikář <vmuzikar@redhat.com> Signed-off-by: Václav Muzikář <vaclav@muzikari.cz> Co-authored-by: Steven Hawkins <shawkins@redhat.com>
This commit is contained in:
parent
2a64caf3fd
commit
7d3dcae96e
5 changed files with 86 additions and 6 deletions
|
@ -190,6 +190,15 @@ Additionally, the following resources have been removed from the `common` theme:
|
|||
|
||||
If you previously used any of the removed resources in your theme, make sure to add them to your own theme resources instead.
|
||||
|
||||
= Additional datasources now require using XA
|
||||
|
||||
{project_name} by default does not use XA datasources. However, this is considered unsafe if more than one datasource is used.
|
||||
Starting with this release, you need to use XA datasources if you are adding additional datasources to {project_name}.
|
||||
If the default datasource supports XA, you can do this by setting the `--transaction-xa-enabled=true` option. For additional datasources, you need to use
|
||||
the `quarkus.datasource.<your-datasource-name>.jdbc.transactions=xa` option in your `quarkus.properties` file.
|
||||
At most one datasource can be non-XA.
|
||||
Recovery isn't supported when you don't have persistent storage for the transaction store.
|
||||
|
||||
= Hostname v1 feature removed
|
||||
|
||||
The deprecated hostname v1 feature was removed. This feature was deprecated in {project_name} 25 and replaced by hostname v2. If you are still using this feature, you must migrate to hostname v2. For more details, see the https://www.keycloak.org/server/hostname[Configuring the hostname (v2)] and https://www.keycloak.org/docs/latest/upgrading/#new-hostname-options[the initial migration guide].
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.quarkus.deployment;
|
||||
|
||||
import io.quarkus.builder.item.EmptyBuildItem;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class CheckMultipleDatasourcesBuildStep extends EmptyBuildItem {}
|
|
@ -17,13 +17,17 @@
|
|||
|
||||
package org.keycloak.quarkus.deployment;
|
||||
|
||||
import io.quarkus.agroal.runtime.DataSourcesJdbcBuildTimeConfig;
|
||||
import io.quarkus.agroal.runtime.TransactionIntegration;
|
||||
import io.quarkus.agroal.runtime.health.DataSourceHealthCheck;
|
||||
import io.quarkus.agroal.spi.JdbcDataSourceBuildItem;
|
||||
import io.quarkus.agroal.spi.JdbcDriverBuildItem;
|
||||
import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem;
|
||||
import io.quarkus.arc.deployment.BuildTimeConditionBuildItem;
|
||||
import io.quarkus.bootstrap.logging.InitialConfigurator;
|
||||
import io.quarkus.builder.item.EmptyBuildItem;
|
||||
import io.quarkus.datasource.deployment.spi.DevServicesDatasourceResultBuildItem;
|
||||
import io.quarkus.datasource.runtime.DataSourcesBuildTimeConfig;
|
||||
import io.quarkus.deployment.IsDevelopment;
|
||||
import io.quarkus.deployment.annotations.BuildProducer;
|
||||
import io.quarkus.deployment.annotations.BuildStep;
|
||||
|
@ -267,13 +271,33 @@ class KeycloakProcessor {
|
|||
// We do not want to initialize the JDBC driver class
|
||||
Class.forName(dbDriver.get(), false, Thread.currentThread().getContextClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Ignore queued TRACE and DEBUG messages for not initialized log handlers
|
||||
InitialConfigurator.DELAYED_HANDLER.setBuildTimeHandlers(new Handler[]{});
|
||||
throw new ConfigurationException(String.format("Unable to find the JDBC driver (%s). You need to install it.", dbDriver.get()));
|
||||
throwConfigError(String.format("Unable to find the JDBC driver (%s). You need to install it.", dbDriver.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inspired by AgroalProcessor
|
||||
@BuildStep
|
||||
@Produce(CheckMultipleDatasourcesBuildStep.class)
|
||||
void checkMultipleDatasourcesUseXA(DataSourcesBuildTimeConfig dataSourcesConfig, DataSourcesJdbcBuildTimeConfig jdbcConfig) {
|
||||
long nonXADatasourcesCount = dataSourcesConfig.dataSources().keySet().stream()
|
||||
.map(ds -> jdbcConfig.dataSources().get(ds).jdbc())
|
||||
.filter(jdbc -> jdbc.enabled() && jdbc.transactions() != TransactionIntegration.XA)
|
||||
.count();
|
||||
if (nonXADatasourcesCount > 1) {
|
||||
throwConfigError("Multiple datasources are configured but more than 1 is using non-XA transactions. " +
|
||||
"All the datasources except one must must be XA to be able to use Last Resource Commit Optimization (LRCO). " +
|
||||
"Please update your configuration by setting --transaction-xa-enabled=true " +
|
||||
"and/or quarkus.datasource.<your-datasource-name>.jdbc.transactions=xa.");
|
||||
}
|
||||
}
|
||||
|
||||
private void throwConfigError(String msg) {
|
||||
// Ignore queued TRACE and DEBUG messages for not initialized log handlers
|
||||
InitialConfigurator.DELAYED_HANDLER.setBuildTimeHandlers(new Handler[]{});
|
||||
throw new ConfigurationException(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the default configuration for the User Profile provider
|
||||
*/
|
||||
|
@ -344,6 +368,7 @@ class KeycloakProcessor {
|
|||
|
||||
@BuildStep
|
||||
@Consume(CheckJdbcBuildStep.class)
|
||||
@Consume(CheckMultipleDatasourcesBuildStep.class)
|
||||
void produceDefaultPersistenceUnit(BuildProducer<PersistenceXmlDescriptorBuildItem> producer) {
|
||||
ParsedPersistenceXmlDescriptor descriptor = PersistenceXmlParser.locateIndividualPersistenceUnit(
|
||||
Thread.currentThread().getContextClassLoader().getResource("default-persistence.xml"));
|
||||
|
|
|
@ -17,4 +17,5 @@
|
|||
|
||||
quarkus.datasource.user-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.url=jdbc:h2:mem:user-store;DB_CLOSE_DELAY=-1
|
||||
quarkus.datasource.user-store.jdbc.transactions=xa
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package org.keycloak.it.cli.dist;
|
||||
|
||||
import static io.restassured.RestAssured.when;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
@ -114,6 +113,15 @@ public class QuarkusPropertiesAutoBuildDistTest {
|
|||
cliResult.assertStarted();
|
||||
}
|
||||
|
||||
@Test
|
||||
@BeforeStartDistribution(AddNonXADatasource.class)
|
||||
@Launch({ "start" })
|
||||
@Order(9)
|
||||
void nonXADatasourceFailsToStart(LaunchResult result) {
|
||||
CLIResult cliResult = (CLIResult) result;
|
||||
cliResult.assertError("Multiple datasources are configured but more than 1 is using non-XA transactions.");
|
||||
}
|
||||
|
||||
public static class UpdateConsoleLogLevelToWarn implements Consumer<KeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
|
@ -135,6 +143,7 @@ public class QuarkusPropertiesAutoBuildDistTest {
|
|||
distribution.setQuarkusProperty("quarkus.datasource.user-store.db-kind", "h2");
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store.username","sa");
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store.jdbc.url","jdbc:h2:mem:user-store;DB_CLOSE_DELAY=-1");
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store.jdbc.transactions", "xa");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,6 +154,17 @@ public class QuarkusPropertiesAutoBuildDistTest {
|
|||
distribution.setQuarkusProperty("quarkus.datasource.user-store2.db-transactions", "enabled");
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store2.username","sa");
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store2.jdbc.url","jdbc:h2:mem:user-store2;DB_CLOSE_DELAY=-1");
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store2.jdbc.transactions", "xa");
|
||||
}
|
||||
}
|
||||
|
||||
public static class AddNonXADatasource implements Consumer<KeycloakDistribution> {
|
||||
@Override
|
||||
public void accept(KeycloakDistribution distribution) {
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store3.db-kind", "h2");
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store3.db-transactions", "enabled");
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store3.username","sa");
|
||||
distribution.setQuarkusProperty("quarkus.datasource.user-store3.jdbc.url","jdbc:h2:mem:user-store2;DB_CLOSE_DELAY=-1");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,4 +189,4 @@ public class QuarkusPropertiesAutoBuildDistTest {
|
|||
distribution.setQuarkusProperty("quarkus.datasource.db-kind", "postgres");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue