= Spring Config

SDL 6.0에서는 모든 Spring 설정이 Java Config로 되어 있다. com.samsung.config 패지키에 있다.
기본적인 설정파일들은 아래와 같다.
[source, text]
----
com.samsung.config
    |- CacheConfig <1>
    |- DbcpDataSourceConfig <2>
    |- JasyptConfig <3>
    |- JpaDatasourceConfig <4>
    |- KnoxSyncBatchConfig <5>
    |- QuartzClusteringConfig <6>
    |- QuartzConfig <7>
    |- RedisConfig <8>
    |- SpringConfig <9>
    |- SpringWebConfig <10>
    |- SwaggerConfig <11>
    |- SysUseLogBatchConfig <12>
    |- TemplateConfig <13>
    |- UserBatchConfig <14>
    |- WebClientConfig <15>
----
<1> 캐시 설정 (Simple Provider)
<2> 데이터 소스 설정
<3> 프로퍼티 값 암호화를 위한 Jasypt 설정
<4> Jndi 데이터 소스 설정
<5> 결재동기화 배치 쿼츠(Quartz) job/trigger 설정
<6> Quartz 클러스터링 설정 (JDBC Jobstore)
<7> Quartz 설정 (RAM Jobstore)
<8> 캐시 설정 (Redis)
<9> Spring 설정
<10> Spring WebApplicationContext 설정
<11> Swagger 설정
<12> 시스템 로그 배치 쿼츠(Quartz) job/trigger 설정
<13> Thymeleaf 템플릿 엔진 설정
<14> 사용자 관련 배치 쿼츠(Quartz) job/trigger 설정
<15> WebClient 설정

== SpringConfig

Spring 설정 중에 가장 기본이 된다. Transaction, MessageSource 를 사용 할수 있도록
Spring Container 에 등록한다.

* @Configuration

Configuration Annotation은 Spring Container에게 해당 클래스가 Bean들을 등록하는 클래스라는 것을 알려주기 위한 Annotation이다.
프로젝트에서 Bean을 등록 할때는 클래스에 Configuration Annotation을 설정하도록 한다.

* @EnableTransactionManagement

EnableTransactionManagement annotation을 사용하면 Spring에서 @Transactional 을 사용해 Transaction을 관리 할 수 있다.

.xml 설정
[source, xml]
----
<tx:annotation-driven transaction-manager="txManager" />
----

@Transactional 에 대한 세부적인 내용은 Spring
link:https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-declarative-attransactional-settings[Transactional Settings]
를 참고 한다.

* PropertySource

property 파일을 읽기 위해 사용한다. SDL에서는 <<_config_properties, config.properties>>파일과 <<_knox_properties,knox.properties>> 파일을 기본으로 로딩한다.
PropertySource에 등록된 값은 Spring Bean에서 사용할 수 있다.

** Value Injection +
@Value를 사용해 PropertySource의 값을 Injection 한다.

** Environment Injection +
org.springframework.core.env.Environment를 Injection 하고 getProperty("key")를 이용해 값을 얻는다.

.Value Injeciton
[source, java]
----
@Value("${security.access.limit.timeout:30}")
private int limitTimeout;

@Value("${security.check.access.timeout:false}")
private boolean checkTimeout;
----
.Environment Injection
[source, java]
----
String functionUrl = environment.getProperty(KNOX_EMP_SERVICE) + "/employees";
----

* ComponentScan

com.samsung 패키지에 속해 있는 @Service, @Repository, @Component 의 Bean만 찾아서 등록한다.

[source, java]
----
@ComponentScan(basePackages = "com.samsung", useDefaultFilters = false, includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Service.class), @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Repository.class), @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Component.class)})
----

CAUTION: @Controller Baen은 SpringConfig가 아닌 SpringWebConfig에서 Scan한다.

* MessageSource

다국어 적용을 위해 MessageSource 를 사용한다. Backend 에서는 MessageSourceAccessor나 MessageSource를 이용해 다국어를 적용한다.
특히 velocity엔진 템플릿에서 다국어를 사용하기 위해서는 반드시 MessageSourceAccessor를 사용하도록 한다.

IMPORTANT: Frontend 가 처음 로딩 될 때 서버에서 "/noauth/messages/all" API를 호출해 시스템의 모든 메세지 리소스를 받는다. MessageBundleService에서는 config.properties 에 설정된 language-set에 해당하는 Message Properties 파일을 읽어 JSON으로 만들어 리턴한다.


== SpringWebConfig
Spring WebApplicationContext 설정을 위한 파일이다. WebMvcConfigurer를 구현하고 있으며,
Formatter, MessageConverter 등을 재정의 할 수 있다.

.xml
[source, xml]
----
<mvc:annotation-driven/>
----

@Configuration, @EnableWebMvc 를 선언하는 것으로 대체될 수 있다.

.java
[source, xml]
----
@Configuration
@EnableWebMvc
public class SpringWebConfig implements WebMvcConfigurer {
}
----

* ComponentScan

[source, java]
----
@ComponentScan(basePackages = "com.samsung", useDefaultFilters = false, includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class), @ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableSwagger2.class)})
----

@Controller, @EnableSwagger2 로 선언된 Bean을 Scan한다.

* addResourceHandlers

정적 리소스를 관리하는 ResourceHandlerRegistry에 pathPatterns와 리소스 위치를 등록한다.

[source, java]
----
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("index.html").
            addResourceLocations(webResourceRoot);
    registry.addResourceHandler("favicon.ico").
            addResourceLocations(webResourceRoot + "static/");
    registry.addResourceHandler("static/**")
            .addResourceLocations(webResourceRoot + "static/");
    registry.addResourceHandler("swagger-ui.html")
            .addResourceLocations("classpath:/META-INF/resources/");
    registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
}
----

* MultipartResolver

Multipart 요청에 대한 처리를 담당하는 Resolver다. 파일업로드의 최대 크기 등을 설정한다.
[source, java]
----
    @Value("${common.upload.max-request-size:-1}")
    private long maxRequestSize;
    @Value("${common.upload.max-file-size:-1}")
    private long maxFileSize;


    @Bean
    public MultipartResolver multipartResolver() {
        return new StandardServletMultipartResolver();
    }

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        factory.setMaxRequestSize(DataSize.ofBytes(maxRequestSize));
        factory.setMaxFileSize(DataSize.ofBytes(maxFileSize));

        return factory.createMultipartConfig();
    }
----

config.properties에 설정한 multipart/form-data 최대 사이즈, 전체 업로드 파일의 최대 용량을 참조한다.
