본문 바로가기

프로그래밍/Spring

전자정부 프레임워크를 Java Config 방식으로 설정해보자(context-idgen.xml, context-properties.xml, context-validator.xml 변환)

지난 글에서는 트랜잭션 관련 설정 파일인 context-transaction.xml 파일을 Java Config 방식으로 바꾸는 작업에 대하여 설명하였다. 이번에는 나머지 Root Context 관련 환경 파일인 context-idgen.xml, context-properties.xml, context-validator.xml 파일을 Java Config 방식으로 바꾸는 작업에 대해 설명하도록 하겠다.

 

여기 이 글에서는 context-idgen.xml과 context-properties.xml, context-validator.xml 파일에 설정된 bean의 설명에 대해서는 언급하지 않도록 하겠다. 다만 각 xml 파일들이 어떤 기능을 환경설정하는지를 간략하게 설명하자면 context-idgen.xml에서 하는 것은 테이블별 고유 ID 값을 관리하는 테이블(또는 시퀀스일수도 있다)을 이용하여 고유 Key를 생성하는 환경을 설정한다. 여기에는 특정 정책을 적용한 ID를 만들어서 적용할 수 있다. context-properties.xml은 특정 key와 그 key에 매핑되는 value를 입력하거나 또는 특정 key와 그 key에 매핑되는 value가 입력된 외부 파일을 적용하여 Property Service를 제공해준다. 마지막으로 context-validator.xml은 client에서 입력한 값 및 이러한 값이 전송된 server에서 사용자가 입력한 값의 검증 서비스를 제공해준다.

 

context-idgen.xml과 context-properties.xml을 Java Config 방식으로 변환하는 것에 대해서는 별다른 설명을 할 것이 없다. 그래서 이것은 각각 XML 파일 소스와 이를 Java Config 방식으로 바꾼 소스를 차례대로 보여주는 것으로 이를 대신 갈음하겠다.

 

<bean name="egovIdGnrService" class="egovframework.rte.fdl.idgnr.impl.EgovTableIdGnrServiceImpl" destroy-method="destroy">
	<property name="dataSource" ref="dataSource" />
	<property name="strategy" 	ref="mixPrefixSample" />
	<property name="blockSize" 	value="10"/>
	<property name="table"	   	value="IDS"/>
	<property name="tableName"	value="SAMPLE"/>
</bean>
<bean name="mixPrefixSample" class="egovframework.rte.fdl.idgnr.impl.strategy.EgovIdGnrStrategyImpl">
	<property name="prefix"   value="SAMPLE-" />
	<property name="cipers"   value="5" />
	<property name="fillChar" value="0" />
</bean>	

 

package egovframework.example.config.root;

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import egovframework.rte.fdl.idgnr.impl.EgovTableIdGnrServiceImpl;
import egovframework.rte.fdl.idgnr.impl.strategy.EgovIdGnrStrategyImpl;

@Configuration
public class ContextIdgen {

	@Bean(destroyMethod="destroy")
	public EgovTableIdGnrServiceImpl egovIdGnrService(DataSource dataSource, EgovIdGnrStrategyImpl egovIdGnrStrategyImpl){
		EgovTableIdGnrServiceImpl egovTableIdGnrServiceImpl = new EgovTableIdGnrServiceImpl();
		egovTableIdGnrServiceImpl.setDataSource(dataSource);
		egovTableIdGnrServiceImpl.setStrategy(egovIdGnrStrategyImpl);
		egovTableIdGnrServiceImpl.setBlockSize(10);
		egovTableIdGnrServiceImpl.setTable("IDS");
		egovTableIdGnrServiceImpl.setTableName("SAMPLE");
		return egovTableIdGnrServiceImpl;
	}
	
	@Bean
	public EgovIdGnrStrategyImpl mixPrefixSample(){
		EgovIdGnrStrategyImpl egovIdGnrStrategyImpl = new EgovIdGnrStrategyImpl();
		egovIdGnrStrategyImpl.setPrefix("SAMPLE-");
		egovIdGnrStrategyImpl.setCipers(5);
		egovIdGnrStrategyImpl.setFillChar('0');
		return egovIdGnrStrategyImpl;
	}
}

 

<bean name="propertiesService" class="egovframework.rte.fdl.property.impl.EgovPropertyServiceImpl" destroy-method="destroy">
	<property name="properties">
		<map>
			<entry key="pageUnit" value="10"/>
			<entry key="pageSize" value="10"/>
		</map>
	</property>
</bean>

 

package egovframework.example.config.root;

import java.util.HashMap;
import java.util.Map;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import egovframework.rte.fdl.cmmn.exception.FdlException;
import egovframework.rte.fdl.property.impl.EgovPropertyServiceImpl;

@Configuration
public class ContextProperties {

	@Bean(destroyMethod="destroy")
	public EgovPropertyServiceImpl propertiesService() throws FdlException{
		Map<String, String> properties = new HashMap<string, string="">();
		properties.put("pageUnit", "10");
		properties.put("pageSize", "10");
		
		EgovPropertyServiceImpl egovPropertyServiceImpl = new EgovPropertyServiceImpl();
		egovPropertyServiceImpl.setProperties(properties);
		
		return egovPropertyServiceImpl;
		
	}
}
</string,>

 

context-validator.xml 파일도 이를 Java Config 파일로 변환하는 것에 대해서는 별다른 설명을 할 것이 없다. 그러나 여기에서는 Resource를 얻어오는 부분에 대해 이전에 ibatis, Mybatis 설정을 Java Config 방식으로 바꿀때 사용했던 PathMatchingResourcePatternResolver 클래스를 사용할 수 없기 때문에 이 부분에 대한 설명을 하도록 하겠다. 먼저 context-validator.xml의 <bean> 태그 설정을 보도록 하자.

 

<bean id="beanValidator" class="org.springmodules.validation.commons.DefaultBeanValidator">
	<property name="validatorFactory" ref="validatorFactory"/>
</bean>

<bean id="validatorFactory" class="org.springmodules.validation.commons.DefaultValidatorFactory">
	<property name="validationConfigLocations">
		<list>
			<value>/WEB-INF/config/egovframework/validator/validator-rules.xml</value>
			<value>/WEB-INF/config/egovframework/validator/validator.xml</value>
		</list>
	</property>
</bean>

 

<bean> 태그 설정을 보면 DefaultBeanValidator 클래스와 DefaultValidatorFactory 클래스를 bean으로 설정하고 있다. 여기까지는 별다른 내용이 없다. 다만 DefaultValidatorFactory 클래스의 validationConfigLocations 속성을 설정하는 부분을 Java Config 방식으로 바꿀려고 하면 ibatis, Mybatis 연동 설명때 사용했던 PathMatchingResourcePatternResolver 클래스를 이용해서 이를 Resource 인터페이스를 구현한 클래스 객체로 받아서 이를 설정해야 한다. 그러나 이 부분을 PathMatchingResourcePatternResolver 클래스를 이용해서 이러한 작업을 진행하면 다음의 에러가 발생한다(애러를 전부 보여주지는 않고 핵심적인 내용만 보여주도록 하겠다)

 

Caused by: java.io.FileNotFoundException: class path resource [WEB-INF/config/egovframework/validator/validator-rules.xml] cannot be opened because it does not exist

at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)

at org.springmodules.validation.commons.DefaultValidatorFactory.setValidationConfigLocations(DefaultValidatorFactory.java:85)

... 49 more

 

예외를 던진 내용을 보면 FileNotFoundException 예외가 발생한다. 근데 살펴보면 파일이 없는게 아니다. 파일이 존재하는데 정작 FileNotFoundException 예외가 발생하고 있는 것이다. 왜 그럴까? 여기서 우리는 위의 에러 로그에서 진한 파란색 글씨로 되어 있는 부분에 주목할 필요가 있다. 에러 로그를 보면 이 경로를 class path resource로 인식하고 있으며, 예외를 던지는 클래스 또한 ClassPathResource 클래스가 던지고 있다. 그러면 이 시점에서 생각해야 할 부분이 있다. 우리가 알고 있는 WEB-INF가 classpath에 속하는가?

 

WEB-INF는 classpath가 아니기 때문에(WEB-INF/classes 폴더는 classpath에 속한다) classpath에서 찾으면 안된다. 근데 접두어 classpath를 붙이지 않았는데 왜 classpath에서 찾는건가? ibatis, Mybatis 연동 설정 관련 글에서 Resource 인터페이스를 구현하는 클래스 객체를 만드는데 관여하는 클래스가 구현해야 할 ResourceLoader 인터페이스에 대해 설명했을 당시에 접두어를 붙이지 않으면 ResourceLoader 인터페이스의 구현에 따라 입력한 경로를 찾아 이를 Resource 인터페이스를 구현한 클래스 객체로 구현한다고 설명했다. 이 부분을 염두해두고 PathMatchingResourcePatternResolver 클래스에 대해 설명하겠다. PathMatchingResourcePatternResolver 클래스 또한 이러한 Resource를 찾기 위한 ResourceLoader를 가지고 있다. 근데 별도로 ResourceLoader를 지정하지 않으면 PathMatchingResourcePatternResolver는 DefaultResourceLoader 클래스를 ResourceLoader로 사용하게 된다. 근데 이 DefaultResourceLoader 클래스가 Resource를 찾는 기준은 classpath를 기준으로 Resource를 찾게 된다. 그래서 이처럼 접두어를 붙이지 않고  PathMatchingResourcePatternResolver 클래스를 사용하면 내부적으로는 classpath 기반에서 찾기 때문에 위와 같은 문제가 발생하게 되는 것이다. 그러면 이것을 어디에서 찾아야 하는 것인가? 이 WEB-INF 폴더는 WebApplication 기반의 Context에서는 접근할 수 있는 자원이다. 그리고 예전에 한번 설명했지만 Spring의 ApplicationContext 인터페이스가 ResourceLoader 인터페이스의 자손 인터페이스(이 두 인터페이스 중간에 ResourcePatternResolver 인터페이스가 있기 때문에 자손이란 표현을 사용했다)이기 때문에 ApplicationContext 인터페이스를 구현한 Context 클래스는 ResourceLoader 인터페이스의 메소드를 구현해야 한다. 그래서 WEB-INF 폴더 자원을 찾을때는 Context에서 찾으면 된다. 다음과 같이 말이다.

 

@Autowired
ApplicationContext ac;

@Bean
public DefaultValidatorFactory validatorFactory(){
	DefaultValidatorFactory defaultValidatorFactory = new DefaultValidatorFactory();
	
	defaultValidatorFactory.setValidationConfigLocations(new Resource[]{
			ac.getResource("/WEB-INF/config/egovframework/validator/validator-rules.xml")
			, ac.getResource("/WEB-INF/config/egovframework/validator/validator.xml")
		});
	
	return defaultValidatorFactory;
}

 

Injection 받는 ApplicationContext는 실제로는 AnnotationConfigWebApplicationContext 클래스 객체가 Injection이 된다. WebApplication 기반 Context를 받기 때문에 WEB-INF에 대한 접근이 가능하다. 그래서 ApplicationContext에서 getResource 메소드를 이용해서 파라미터로 입력한 내용을 Resource 인터페이스를 구현한 객체를 가져온다(실제로는 ServletContextResource 클래스 객체가 가져온다)

 

이러한 내용을 숙지하길 바라며 마지막으로 context-validator.xml 설정파일을 Java Config 방식으로 변경한 ContextValidator 클래스 소스를 보여주면서 이 글을 마무리 하겠다.

 

package egovframework.example.config.root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springmodules.validation.commons.DefaultBeanValidator;
import org.springmodules.validation.commons.DefaultValidatorFactory;
import org.springmodules.validation.commons.ValidatorFactory;

@Configuration
public class ContextValidator {
	
	@Autowired
	ApplicationContext ac;
	
	@Bean
	public DefaultBeanValidator beanValidator(ValidatorFactory validatorFactory){
		DefaultBeanValidator defaultBeanValidator = new DefaultBeanValidator();
		defaultBeanValidator.setValidatorFactory(validatorFactory);
		return defaultBeanValidator;
	}
	
	@Bean
	public DefaultValidatorFactory validatorFactory(){
		DefaultValidatorFactory defaultValidatorFactory = new DefaultValidatorFactory();
		
		defaultValidatorFactory.setValidationConfigLocations(new Resource[]{
				ac.getResource("/WEB-INF/config/egovframework/validator/validator-rules.xml")
				, ac.getResource("/WEB-INF/config/egovframework/validator/validator.xml")
			});
		
		return defaultValidatorFactory;
	}
}

 

 

목     차

 1. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(환경구축)

 2. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(기초)

 3. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(context-aspect.xml 변환)

 4. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(context-common.xml 변환)

 5. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(context-datasource.xml 변환)

 6. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(context-sqlMap.xml, context-mapper.xml 변환)

 7. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(context-transaction.xml 변환)

 8. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(context-idgen.xml, context-properties.xml, context-validator.xml 변환)

 9. 작성된 Java Config 클래스 파일들을 실제 등록해보자(RootContext 클래스 제작)

 10. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(dispatcher-servlet.xml 변환) - 1

 11. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(dispatcher-servlet.xml 변환) - 2

 12. 전자정부 프레임워크를 Java Config 방식으로 설정해보자(dispatcher-servlet.xml 변환) - 3