개요
SpringBoot 를 사용하지 않는 프로젝트로 환경 설정 값을 yaml 에 지정하고 싶었다.
따라서 순수 Java code 로 `application.yaml` 을 로드할 필요가 있었다.
방법
SnakeYaml + Map 방식
간단한 yaml 은 주로 아래와 같은 코드 스니펫으로 Map을 사용해서 파싱할 수 있다.
@Test
public void whenLoadYAML_thenLoadCorrectImplicitTypes() {
Yaml yaml = new Yaml();
Map<Object, Object> document = yaml.load("3.0: 2018-07-22");
assertNotNull(document);
assertEquals(1, document.size());
assertTrue(document.containsKey(3.0d));
}
문제점 - Map 방식의 한계
Nested object 로 depth 를 가지거나 배열 형태인 경우 파싱해서 쓰기 어렵다
1 depth 만 값을 확인할 수 있고 그 이상의 depth 는 deserialize 되지 않기 때문이다.
javascript / typescript 는 되던데?
javascript/typescript는 동적 타입캐스팅을 지원하나 Java 는 정적 타입언어로 동적으로 타입캐스팅을 지원하지 않는다.
따라서 컴파일 시점에 Deserialize 대상 클래스를 선언해야한다.
해결 - Custom Class
클래스 멤버 변수 타입을 미리 선언한다.
Snake는 생성자 주입이 아닌 필드 주입으로 config 값을 할당한다.
=> 따라서 setter 가 필요하다.
Configuration.java
@Getter @Setter
public class Configuration {
private BootStrap bootstrap;
private Security security;
private SASL sasl;
}
BootStrap.java
@Getter @Setter
public class BootStrap {
private String servers;
}
@Getter @Setter
public class Security {
private String protocol;
}
@Getter @Setter
public class SASL{
private JAAS jaas;
}
@Getter @Setter
public class JAAS {
private String config;
private String mechanism;
}
ConfigurationTest.java
class ConfigurationTest {
@Test
@DisplayName("Yaml loading with custom class")
public void loadYamlWithConfigClass() throws FileNotFoundException {
// given
Path resourceDirectory = Paths.get("src", "test", "resources", "application.yaml");
String yamlFileAbsolutePath = resourceDirectory.toFile().getAbsolutePath();
InputStream inputStream = new FileInputStream(yamlFileAbsolutePath);
// when
Yaml yaml = new Yaml();
Configuration configuration2 = yaml.loadAs(inputStream, Configuration.class);
// then
var bootStrap = configuration2.getBootstrap();
var security = configuration2.getSecurity();
var sasl = configuration2.getSasl();
assertThat(bootStrap.getServers()).isEqualTo("cluster.playground.cdkt.io:9092");
assertThat(security.getProtocol()).isEqualTo("SASL_SSL");
assertThat(sasl.getJaas().getConfig()).isEqualTo("secret");
assertThat(sasl.getJaas().getMechanism()).isEqualTo("PLAIN");
}
}
사실 이방식도 완벽하지 않다.
Configuration 에 주입되는 모든 값들이 필드주입으로 setter가 열려있기 때문이다.
Reference
https://www.baeldung.com/java-snake-yaml
'JVM > Java' 카테고리의 다른 글
[Java] Enum 에는 equals 대신 == 을 써라 (0) | 2023.11.22 |
---|---|
[Java & Kotlin] Stream (1) | 2023.10.09 |
Presentation - Business DTO를 분리시켜라 (0) | 2023.08.06 |
[Java] Data Transfer Object (DTO) (0) | 2023.01.27 |
[JAVA] JDK 11 'var' Type Inference (0) | 2020.11.03 |