Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/analysis-finding-a05-f031.txt
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.

Follows the import procedure in README.md.

  source/     the originating repository verbatim — 78 documents, 28 SVGs,
              8 manifests, plus .source-revision recording the commit
  final/      the SSOT
    document.md   729 lines written from the 29 experiment documents, not
                  concatenated: what was predicted, what was measured, and
                  where the measurement itself was wrong
    evidence/raw    125 outputs, flattened to <experiment>__<file> because
                    the originals collided (01-baseline.txt appeared three
                    times) and the audit only globs the top level
    evidence/meta   one per raw file; command and exitCode are null and the
                    README says why rather than inventing them
    evidence/browser  22 captures
    assets/       three diagrams through techviz
    .techviz/     their VizSpecs

A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.

Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.

verify-pipeline.py passes. audit-records.py reports no issues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 22:51:59 +09:00

280 lines
23 KiB
Plaintext

# 그 타입이 약속하는 것
PersistenceVendorSettings.java:1 package dev.caskeleton.adapter.outbound.persistence.config;
PersistenceVendorSettings.java:2
PersistenceVendorSettings.java:3 import org.springframework.boot.context.properties.ConfigurationProperties;
PersistenceVendorSettings.java:4
PersistenceVendorSettings.java:5 /**
PersistenceVendorSettings.java:6 * Selects which RDBMS vendor composition this deployment runs.
PersistenceVendorSettings.java:7 *
PersistenceVendorSettings.java:8 * <p>The selector is a property rather than a profile name because the vendor is a property of the
PersistenceVendorSettings.java:9 * datastore, not of the environment that happens to use it. A fork that runs PostgreSQL under a
PersistenceVendorSettings.java:10 * profile named something other than {@code dev}/{@code prod}, or that wants H2 in a throwaway
PersistenceVendorSettings.java:11 * demo, sets this key; it does not have to rename its profiles or edit a condition.
PersistenceVendorSettings.java:12 *
PersistenceVendorSettings.java:13 * <p>Binding to an enum is what makes an unknown vendor a startup failure. With a raw string the
PersistenceVendorSettings.java:14 * two {@code @ConditionalOnProperty} vendor configurations would both stay off, and the first
PersistenceVendorSettings.java:15 * missing SPI bean would surface as a {@code NoSuchBeanDefinitionException} naming {@code
PersistenceVendorSettings.java:16 * OutboxClaimRepository} — a symptom several layers away from the misspelled value that caused it.
PersistenceVendorSettings.java:17 */
PersistenceVendorSettings.java:18 @ConfigurationProperties(prefix = PersistenceVendorSettings.PREFIX)
PersistenceVendorSettings.java:19 public record PersistenceVendorSettings(Vendor vendor) {
PersistenceVendorSettings.java:20
PersistenceVendorSettings.java:21 public static final String PREFIX = "ca-skeleton.persistence";
PersistenceVendorSettings.java:22 public static final String VENDOR_PROPERTY = PREFIX + ".vendor";
PersistenceVendorSettings.java:23
PersistenceVendorSettings.java:24 /** The RDBMS vendors this repository composes a persistence adapter for. */
PersistenceVendorSettings.java:25 public enum Vendor {
PersistenceVendorSettings.java:26 POSTGRESQL,
PersistenceVendorSettings.java:27 H2
PersistenceVendorSettings.java:28 }
PersistenceVendorSettings.java:29
PersistenceVendorSettings.java:30 public PersistenceVendorSettings {
PersistenceVendorSettings.java:31 // Absent means PostgreSQL: the vendor every deployment before this selector existed ran, so an
PersistenceVendorSettings.java:32 // upgrade that does not set the key keeps its datastore.
PersistenceVendorSettings.java:33 vendor = vendor == null ? Vendor.POSTGRESQL : vendor;
PersistenceVendorSettings.java:34 }
PersistenceVendorSettings.java:35 }
# 그 타입을 빈으로 등록하는 자리
EnableConfigurationProperties 가 이 타입을 담은 main 줄 : 0 개
ConfigurationPropertiesScan 애너테이션이 붙은 main 자리 (주석 제외) :
app-bootstrap · CaSkeletonApplication.java:58 @ConfigurationPropertiesScan(
sample-portfolio · SamplePortfolioApplication.java:46 @ConfigurationPropertiesScan(basePackages = "dev.caskeleton")
이 타입이 나오는 자리 전부 :
adapter/outbound/persistence-jpa · main · PersistenceVendorSettings.java:18 @ConfigurationProperties(prefix = PersistenceVendorSettings.PREFIX)
adapter/outbound/persistence-jpa · main · PersistenceVendorSettings.java:19 public record PersistenceVendorSettings(Vendor vendor) {
adapter/outbound/persistence-jpa · main · PersistenceVendorSettings.java:30 public PersistenceVendorSettings {
adapter/outbound/persistence-jpa · main · H2PersistenceConfig.java:4 import dev.caskeleton.adapter.outbound.persistence.config.PersistenceVendorSettings;
adapter/outbound/persistence-jpa · main · H2PersistenceConfig.java:42 prefix = PersistenceVendorSettings.PREFIX,
adapter/outbound/persistence-jpa · main · PostgreSqlPersistenceConfig.java:5 import dev.caskeleton.adapter.outbound.persistence.config.PersistenceVendorSettings;
adapter/outbound/persistence-jpa · main · PostgreSqlPersistenceConfig.java:29 * PersistenceVendorSettings} back from {@code config} — so the composition root names both vendor
adapter/outbound/persistence-jpa · main · PostgreSqlPersistenceConfig.java:33 * unconditional before {@link PersistenceVendorSettings} existed, and a deployment that never sets
adapter/outbound/persistence-jpa · main · PostgreSqlPersistenceConfig.java:39 prefix = PersistenceVendorSettings.PREFIX,
adapter/outbound/persistence-jpa · test · PersistenceVendorSelectionTest.java:5 import dev.caskeleton.adapter.outbound.persistence.config.PersistenceVendorSettings.Vendor;
adapter/outbound/persistence-jpa · test · PersistenceVendorSelectionTest.java:34 .withPropertyValues(PersistenceVendorSettings.VENDOR_PROPERTY + "=" + value)
adapter/outbound/persistence-jpa · test · PersistenceVendorSelectionTest.java:38 assertThat(context.getBean(PersistenceVendorSettings.class).vendor())
adapter/outbound/persistence-jpa · test · PersistenceVendorSelectionTest.java:47 assertThat(context.getBean(PersistenceVendorSettings.class).vendor())
adapter/outbound/persistence-jpa · test · PersistenceVendorSelectionTest.java:54 .withPropertyValues(PersistenceVendorSettings.VENDOR_PROPERTY + "=mysql")
adapter/outbound/persistence-jpa · test · PersistenceVendorSelectionTest.java:59 .hasStackTraceContaining(PersistenceVendorSettings.VENDOR_PROPERTY);
adapter/outbound/persistence-jpa · test · PersistenceVendorSelectionTest.java:69 assertThat(condition.prefix()).isEqualTo(PersistenceVendorSettings.PREFIX);
adapter/outbound/persistence-jpa · test · PersistenceVendorSelectionTest.java:83 assertThat(condition.prefix()).isEqualTo(PersistenceVendorSettings.PREFIX);
adapter/outbound/persistence-jpa · test · PersistenceVendorSelectionTest.java:92 @EnableConfigurationProperties(PersistenceVendorSettings.class)
app-bootstrap · main · PersistenceJpaRootAutoConfiguration.java:4 import dev.caskeleton.adapter.outbound.persistence.config.PersistenceVendorSettings;
app-bootstrap · main · PersistenceJpaRootAutoConfiguration.java:86 * PersistenceVendorSettings}, because that type is not a registered bean here: the composition
app-bootstrap · main · PersistenceJpaRootAutoConfiguration.java:112 environment.getProperty(PersistenceVendorSettings.VENDOR_PROPERTY, "postgresql").trim();
# 두 애플리케이션의 스캔 범위가 다르다
CaSkeletonApplication.java:58 @ConfigurationPropertiesScan(
CaSkeletonApplication.java:59 basePackages = {
CaSkeletonApplication.java:60 "dev.caskeleton.bootstrap.async",
CaSkeletonApplication.java:61 "dev.caskeleton.bootstrap.autoconfigure.fileserver",
CaSkeletonApplication.java:62 "dev.caskeleton.bootstrap.autoconfigure.httpclient",
CaSkeletonApplication.java:63 "dev.caskeleton.bootstrap.concurrency",
CaSkeletonApplication.java:64 "dev.caskeleton.bootstrap.idempotency",
CaSkeletonApplication.java:65 "dev.caskeleton.bootstrap.outbox",
CaSkeletonApplication.java:66 "dev.caskeleton.bootstrap.redis",
CaSkeletonApplication.java:67 "dev.caskeleton.bootstrap.runtime",
CaSkeletonApplication.java:68 "dev.caskeleton.bootstrap.security",
CaSkeletonApplication.java:69 "dev.caskeleton.bootstrap.settings",
CaSkeletonApplication.java:70 "dev.caskeleton.bootstrap.tracing",
CaSkeletonApplication.java:71 "dev.caskeleton.adapter.inbound.grpc",
CaSkeletonApplication.java:72 "dev.caskeleton.adapter.inbound.web",
CaSkeletonApplication.java:73 "dev.caskeleton.adapter.inbound.websocket",
CaSkeletonApplication.java:74 "dev.caskeleton.adapter.outbound.cache.redis",
CaSkeletonApplication.java:75 "dev.caskeleton.adapter.outbound.fileserver",
CaSkeletonApplication.java:76 "dev.caskeleton.adapter.outbound.objectstorage",
CaSkeletonApplication.java:77 "dev.caskeleton.application",
CaSkeletonApplication.java:78 "dev.caskeleton.domain",
CaSkeletonApplication.java:79 "dev.caskeleton.shared"
CaSkeletonApplication.java:80 })
SamplePortfolioApplication.java:44 classes = TestEnclosedConfigurationFilter.class)
SamplePortfolioApplication.java:45 })
SamplePortfolioApplication.java:46 @ConfigurationPropertiesScan(basePackages = "dev.caskeleton")
SamplePortfolioApplication.java:47 public class SamplePortfolioApplication {
SamplePortfolioApplication.java:48
sample-portfolio/build.gradle:37 implementation project(':adapter:outbound:persistence-jpa')
# 합성 루트가 그 자리에서 무엇을 하는가
PersistenceJpaRootAutoConfiguration.java:56 @AutoConfiguration
PersistenceJpaRootAutoConfiguration.java:57 @ConditionalOnProperty(
PersistenceJpaRootAutoConfiguration.java:58 prefix = "ca-skeleton.persistence-jpa",
PersistenceJpaRootAutoConfiguration.java:59 name = "enabled",
PersistenceJpaRootAutoConfiguration.java:60 havingValue = "true")
PersistenceJpaRootAutoConfiguration.java:61 @Import({
PersistenceJpaRootAutoConfiguration.java:62 JpaAdapterComponentsConfig.class,
PersistenceJpaRootAutoConfiguration.java:63 PostgreSqlPersistenceConfig.class,
PersistenceJpaRootAutoConfiguration.java:64 H2PersistenceConfig.class,
PersistenceJpaRootAutoConfiguration.java:65 FileserverJpaPersistenceConfig.class,
PersistenceJpaRootAutoConfiguration.java:66 NotificationJpaPersistenceFacade.class,
PersistenceJpaRootAutoConfiguration.java:67 MigrationStartupConfig.class,
PersistenceJpaRootAutoConfiguration.java:68 JpaPlatformRuntimeAutoConfiguration.class
PersistenceJpaRootAutoConfiguration.java:69 })
PersistenceJpaRootAutoConfiguration.java:70 public class PersistenceJpaRootAutoConfiguration {
PersistenceJpaRootAutoConfiguration.java:85 * <p>The vendor is read from the {@link Environment} rather than injected as {@code
PersistenceJpaRootAutoConfiguration.java:86 * PersistenceVendorSettings}, because that type is not a registered bean here: the composition
PersistenceJpaRootAutoConfiguration.java:87 * root's {@code @ConfigurationPropertiesScan} deliberately excludes the persistence package so an
PersistenceJpaRootAutoConfiguration.java:88 * optional capability cannot bind — or reject — its detail settings in a deployment that never
PersistenceJpaRootAutoConfiguration.java:89 * switched it on. The default matches {@code PostgreSqlPersistenceConfig}'s {@code matchIfMissing
PersistenceJpaRootAutoConfiguration.java:90 * = true}: an unset selector is PostgreSQL, which is the vendor this configuration was
PersistenceJpaRootAutoConfiguration.java:91 * unconditional about before the selector existed.
PersistenceJpaRootAutoConfiguration.java:92 *
PersistenceJpaRootAutoConfiguration.java:93 * <p>The validator is constructed here rather than injected. It is stateless, and the bean that
PersistenceJpaRootAutoConfiguration.java:94 * used to supply it comes from {@code JpaPlatformRuntimeAutoConfiguration}, which carries
PersistenceJpaRootAutoConfiguration.java:95 * {@code @ConditionalOnBean(DataSource.class)} on a plain {@code @Configuration} imported by this
PersistenceJpaRootAutoConfiguration.java:96 * root — a condition evaluated during configuration-class parsing, before the datasource bean
PersistenceJpaRootAutoConfiguration.java:97 * definition is registered. That class therefore drops out silently in the real application,
PersistenceJpaRootAutoConfiguration.java:98 * taking the whole JPA add-on layer with it. Depending on a bean from it would make this check
PersistenceJpaRootAutoConfiguration.java:99 * disappear for the same reason the thing it checks disappeared. The condition-ordering defect is
PersistenceJpaRootAutoConfiguration.java:100 * recorded separately; it is not this task's to fix quietly.
PersistenceJpaRootAutoConfiguration.java:101 *
PersistenceJpaRootAutoConfiguration.java:102 * @param dataSource the resolved datasource, injected so the database checked is the one in use
PersistenceJpaRootAutoConfiguration.java:103 * @param environment the resolved environment, for the vendor selector
PersistenceJpaRootAutoConfiguration.java:104 * @return the startup check
PersistenceJpaRootAutoConfiguration.java:105 */
PersistenceJpaRootAutoConfiguration.java:106 @Bean
PersistenceJpaRootAutoConfiguration.java:107 public InitializingBean jpaResolvedDataSourceCheck(
PersistenceJpaRootAutoConfiguration.java:108 DataSource dataSource, Environment environment) {
PersistenceJpaRootAutoConfiguration.java:109 JpaDataSourceProfileValidator validator =
PersistenceJpaRootAutoConfiguration.java:110 new JpaDataSourceProfileValidator(new PostgreSqlVersionPolicy());
PersistenceJpaRootAutoConfiguration.java:111 String vendor =
PersistenceJpaRootAutoConfiguration.java:112 environment.getProperty(PersistenceVendorSettings.VENDOR_PROPERTY, "postgresql").trim();
PersistenceJpaRootAutoConfiguration.java:113 return () -> validator.validateResolved(dataSource, "postgresql".equalsIgnoreCase(vendor));
PersistenceJpaRootAutoConfiguration.java:114 }
PersistenceJpaRootAutoConfiguration.java:115 }
# 그 불린을 받는 쪽
JpaDataSourceProfileValidator.java:44 * vendor.
JpaDataSourceProfileValidator.java:45 *
JpaDataSourceProfileValidator.java:46 * @param dataSource the resolved datasource
JpaDataSourceProfileValidator.java:47 * @param requirePostgreSql whether the vendor selector chose PostgreSQL
JpaDataSourceProfileValidator.java:48 * @throws IllegalStateException naming what was unsupported or unreachable
JpaDataSourceProfileValidator.java:49 */
JpaDataSourceProfileValidator.java:50 public void validateResolved(DataSource dataSource, boolean requirePostgreSql) {
JpaDataSourceProfileValidator.java:51 Objects.requireNonNull(dataSource, "dataSource");
JpaDataSourceProfileValidator.java:52 if (!requirePostgreSql) {
JpaDataSourceProfileValidator.java:53 // Local development runs H2 by design, and PersistenceVendorProdSafetyValidator is what keeps
JpaDataSourceProfileValidator.java:54 // that out of production. Demanding PostgreSQL here as well would refuse every laptop.
JpaDataSourceProfileValidator.java:55 return;
JpaDataSourceProfileValidator.java:56 }
JpaDataSourceProfileValidator.java:57 try (Connection connection = dataSource.getConnection()) {
JpaDataSourceProfileValidator.java:58 versionPolicy.requireStable(connection.getMetaData());
JpaDataSourceProfileValidator.java:59 } catch (SQLException unreachable) {
JpaDataSourceProfileValidator.java:60 throw new IllegalStateException(
# 오타 난 벤더가 무엇을 무너뜨리는가 — 조립 경로
JpaAdapterComponentsConfig.java:55 * what is inside them. They need enabling at all because {@code @ConfigurationPropertiesScan}
JpaAdapterComponentsConfig.java:56 * excludes this tree as deliberately as {@code @ComponentScan} does.
JpaAdapterComponentsConfig.java:57 */
JpaAdapterComponentsConfig.java:58 @Configuration(proxyBeanMethods = false)
JpaAdapterComponentsConfig.java:59 @ComponentScan(
JpaAdapterComponentsConfig.java:60 basePackages = {
JpaAdapterComponentsConfig.java:61 "dev.caskeleton.adapter.outbound.persistence.audit",
JpaAdapterComponentsConfig.java:62 "dev.caskeleton.adapter.outbound.persistence.failure",
JpaAdapterComponentsConfig.java:63 "dev.caskeleton.adapter.outbound.persistence.idempotency",
JpaAdapterComponentsConfig.java:64 "dev.caskeleton.adapter.outbound.persistence.lock",
JpaAdapterComponentsConfig.java:65 "dev.caskeleton.adapter.outbound.persistence.outbox",
JpaAdapterComponentsConfig.java:66 "dev.caskeleton.adapter.outbound.persistence.transaction"
JpaAdapterComponentsConfig.java:67 })
JpaAdapterComponentsConfig.java:68 public class JpaAdapterComponentsConfig {}
OutboxStoreAdapter.java:20 * {@code @Transactional} of their own; {@link #claimBatch} delegates the vendor claim to {@link
OutboxStoreAdapter.java:21 * OutboxClaimRepository}. See README "outbox" for the append/claim/no-@Transactional contracts.
OutboxStoreAdapter.java:22 */
OutboxStoreAdapter.java:23 @Repository
OutboxStoreAdapter.java:24 public class OutboxStoreAdapter implements OutboxAppendPort, OutboxStorePort {
OutboxStoreAdapter.java:25
OutboxStoreAdapter.java:26 private final OutboxEventJpaRepository repository;
OutboxStoreAdapter.java:27 private final OutboxClaimRepository claimRepository;
OutboxStoreAdapter.java:28
OutboxStoreAdapter.java:29 public OutboxStoreAdapter(
OutboxStoreAdapter.java:30 OutboxEventJpaRepository repository, OutboxClaimRepository claimRepository) {
OutboxStoreAdapter.java:31 this.repository = repository;
OutboxStoreAdapter.java:32 this.claimRepository = claimRepository;
OutboxStoreAdapter.java:33 }
# 그 값을 실제로 넣고 돌린 결과
프로브 : /tmp/probe-vendor/VendorProbe.java · ApplicationContextRunner 세 조립
VendorProbe.java:36 /** OutboxStoreAdapter 는 JpaAdapterComponentsConfig 가 스캔하는 패키지의 @Repository 다. */
VendorProbe.java:37 @Configuration(proxyBeanMethods = false)
VendorProbe.java:38 static class OutboxConsumer {
VendorProbe.java:39 @Bean OutboxEventJpaRepository events() { return stub(OutboxEventJpaRepository.class); }
VendorProbe.java:40 @Bean OutboxStoreAdapter adapter(OutboxEventJpaRepository e, OutboxClaimRepository c) {
VendorProbe.java:41 return new OutboxStoreAdapter(e, c);
VendorProbe.java:42 }
VendorProbe.java:43 }
VendorProbe.java:44
VendorProbe.java:45 @Configuration(proxyBeanMethods = false)
VendorProbe.java:46 @EnableConfigurationProperties(PersistenceVendorSettings.class)
VendorProbe.java:47 static class BoundSettings {}
VendorProbe.java:74 public static void main(String[] args) {
VendorProbe.java:75 run("두 벤더 설정만 ", "mysql", PostgreSqlPersistenceConfig.class, H2PersistenceConfig.class);
VendorProbe.java:76 for (String v : new String[] {"mysql", "postgresq1"}) {
VendorProbe.java:77 run("SPI 소비자를 더해", v,
VendorProbe.java:78 OutboxConsumer.class, PostgreSqlPersistenceConfig.class, H2PersistenceConfig.class);
VendorProbe.java:79 }
VendorProbe.java:80 run("그 타입을 켜고 ", "mysql", BoundSettings.class);
VendorProbe.java:81 }
두 벤더 설정만 vendor=mysql
기동 실패 : false
OutboxClaimRepository 빈 : 0
SPI 소비자를 더해 vendor=mysql
기동 실패 : true
ca-skeleton.persistence.vendor 를 지목 : false
OutboxClaimRepository 지목 : true
맨 앞 예외 : UnsatisfiedDependencyException: Error creating bean with name 'adapter' defined in VendorProbe$OutboxConsumer: Unsatisfied dependency expressed throug
SPI 소비자를 더해 vendor=postgresq1
기동 실패 : true
ca-skeleton.persistence.vendor 를 지목 : false
OutboxClaimRepository 지목 : true
맨 앞 예외 : UnsatisfiedDependencyException: Error creating bean with name 'adapter' defined in VendorProbe$OutboxConsumer: Unsatisfied dependency expressed throug
그 타입을 켜고 vendor=mysql
기동 실패 : true
ca-skeleton.persistence.vendor 를 지목 : true
OutboxClaimRepository 지목 : false
맨 앞 예외 : ConfigurationPropertiesBindException: Error creating bean with name 'ca-skeleton.persistence-dev.caskeleton.adapter.outbound.persistence.config.Persis
# 시험은 그 타입을 켜고 돌린다
PersistenceVendorSelectionTest.java:28 new ApplicationContextRunner().withUserConfiguration(VendorSettings.class);
PersistenceVendorSelectionTest.java:29
PersistenceVendorSelectionTest.java:30 @ParameterizedTest
PersistenceVendorSelectionTest.java:31 @ValueSource(strings = {"postgresql", "POSTGRESQL", "h2", "H2"})
PersistenceVendorSelectionTest.java:32 void bindsTheSupportedVendorsCaseInsensitively(String value) {
PersistenceVendorSelectionTest.java:33 runner
PersistenceVendorSelectionTest.java:34 .withPropertyValues(PersistenceVendorSettings.VENDOR_PROPERTY + "=" + value)
PersistenceVendorSelectionTest.java:35 .run(
PersistenceVendorSelectionTest.java:36 context -> {
PersistenceVendorSelectionTest.java:37 assertThat(context).hasNotFailed();
PersistenceVendorSelectionTest.java:38 assertThat(context.getBean(PersistenceVendorSettings.class).vendor())
PersistenceVendorSelectionTest.java:39 .isEqualTo(Vendor.valueOf(value.toUpperCase(java.util.Locale.ROOT)));
PersistenceVendorSelectionTest.java:40 });
PersistenceVendorSelectionTest.java:41 }
PersistenceVendorSelectionTest.java:42
PersistenceVendorSelectionTest.java:43 @Test
PersistenceVendorSelectionTest.java:44 void defaultsToPostgreSqlWhenTheSelectorIsAbsent() {
PersistenceVendorSelectionTest.java:45 runner.run(
PersistenceVendorSelectionTest.java:46 context ->
PersistenceVendorSelectionTest.java:47 assertThat(context.getBean(PersistenceVendorSettings.class).vendor())
PersistenceVendorSelectionTest.java:48 .isEqualTo(Vendor.POSTGRESQL));
PersistenceVendorSelectionTest.java:49 }
PersistenceVendorSelectionTest.java:50
PersistenceVendorSelectionTest.java:51 @Test
PersistenceVendorSelectionTest.java:52 void rejectsAnUnknownVendorAtStartupRatherThanComposingNothing() {
PersistenceVendorSelectionTest.java:53 runner
PersistenceVendorSelectionTest.java:54 .withPropertyValues(PersistenceVendorSettings.VENDOR_PROPERTY + "=mysql")
PersistenceVendorSelectionTest.java:55 .run(
PersistenceVendorSelectionTest.java:56 context -> {
PersistenceVendorSelectionTest.java:57 assertThat(context).hasFailed();
PersistenceVendorSelectionTest.java:58 assertThat(context.getStartupFailure())
PersistenceVendorSelectionTest.java:59 .hasStackTraceContaining(PersistenceVendorSettings.VENDOR_PROPERTY);
PersistenceVendorSelectionTest.java:60 });
PersistenceVendorSelectionTest.java:61 }
PersistenceVendorSelectionTest.java:62
PersistenceVendorSelectionTest.java:88 .isFalse();
PersistenceVendorSelectionTest.java:89 }
PersistenceVendorSelectionTest.java:90
PersistenceVendorSelectionTest.java:91 @Configuration(proxyBeanMethods = false)
PersistenceVendorSelectionTest.java:92 @EnableConfigurationProperties(PersistenceVendorSettings.class)
PersistenceVendorSelectionTest.java:93 static class VendorSettings {}
PersistenceVendorSelectionTest.java:94 }