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>
280 lines
23 KiB
Plaintext
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 }
|