[Sprng 3.1] 다음 코드가 왜 문제인지…

이 설정은 스프링 3.1을 사용해서 web.xml 없이 Servlet 3.0 기반 자바 웹 애플리케이션을 배포하는데 필요한 스프링 설정이다.

여기서 중간에 있는 servletContext.addListner()를 사용하는 코드에 무슨 문제(버그는 아니고..)가 있는지 알려면 Servlet 3.0 API 중에 두 개를 알아야 이해할 수 있다.

http://docs.oracle.com/javaee/6/api/javax/servlet/annotation/HandlesTypes.html

http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html

자세하고 친절한 설명은 토스3 개정판을 기대하시라…

[Spring 3.1] EmbeddedDatabaseBuilder

빌더 패턴이 꽤 유용하다는 걸 알게 됐다. 외울 수 밖에 없던 API가 외우지 않아도 되는 API로 변모하는 모습을 보게 됐다. 물론 자바가 static 타입 언어이고, IDE 지원이 빠방하다는 것도 한 몫 했을 것이다.

오늘도 예제를 만들다가 문득.. 이전에 만들었던 EmbeddedDatabaseFactory 코드를 찾아보게 되었다. 메모리 DB는 예제용으로 사용하기 정말 좋다. 별다른 DB 설정 없이 예제를 바로 실행할 수 있기 때문이다.

이전에 블로깅했던 EmbeddedDB 설정은 다음과 같은 과정을 거쳐야 한다.

  1. EDF 객체 생성
  2. EDF 객체에 DB 이름과 DB 종류 설정
  3. RDP(ResourceDatabasePopulator) 객체 생성
  4. RDP에 스프링 Resource 추상화 사용해서 스크립트 추가
  5. EDF에 RDP 객체 설정
  6. EDF.getDatabase() 호출

족히 6~7 라인은 필요한 과정이다. 코드는 이전 글에 있으니까 생략. 게다가 외우고 있어야 하는 API가 최소 세개 등장한다. EDF, RDP, Resource 게다가 마지막에 getDatabase() 메서드 호출까지.. 알고 이어야 한다.

빌더 패턴으로 바뀌면 다 필요 없고, EDB(EmbeddedDatabaseBuilder)만 알면 된다. 그런 다음 네 가지 작업만 하면 된다.

  1. DB 이름 설정
  2. DB 종류 설정
  3. 스크립트 추가
  4. build()

코드는 다음과 같다.
[java]@Bean(destroyMethod = "shutdown")
public DataSource dataSource(){
return new EmbeddedDatabaseBuilder()
.setName("bookDB")
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:whiteship/book-schema.sql")
.build();
}[/java]

[SpringOne 2011] 봄싹 스웨거 책걸이 세미나

11월 26일 이번달 마지막 주 토요일에 SpringOne 2011 특집 세미나로 봄싹 스웨거 스터디를 종료합니다.

일시 : 2011년 11월 26일 10:10 ~ 16:00
장소 : 가락시장역 정보통신산업진흥원(NIPA) 5층 강당(http://www.nipa.kr/intro/
directions.it?menuNo=16)
참가비 : 5,000원, 20600204206291 국민은행 김정우
– 점심 샌드위치, 음료 구입에 사용됩니다.
– 참가비는 22일까지 입금되어야 합니다.
– 입금 시 이름을 봄싹에 등록한 이름으로 보내주세요. (가능하다면 한글 이름을 사용해주세요.)
– 24일 이후에는 환불이 안됩니다. (샌드위치 예약에 따른 조취)
시간표 :
10:10~      – 접수
10:30~10:50 – 봄싹 스웨거를 이야기…
11:00~12:00 – SpringOne 2011 키노트 요약 – 백기선
12:00~13:00 – 점심 시간
13:00~13:50 – 스프링 어디까지 써봤니? – 박용권
14:00~14:50 – Spring Data – 백기선
15:00~15:30 – Spring Social – 박용권
15:40~16:00 – 스웨거를 보내며…
내용 :
SpringOne 2011 키노트 요약
   SpringOne 2011에서 SpringSource CTO인 아드리안 콜리어와 Spring Security 및 Spring Roo를 개발한 벤 알렉스의 키노트를 간략하게 요약해서 시간을 갖겠습니다. 키노트 중에 Spring Social, Spring Data, Spring Adroid, CloudFoundry 등 다양한 시연이 있었는데, 저는 Spring 3.1 최신 기능과 CloudFoundry 시연을 보여드리겠습니다.
스프링 어디까지 써봤니?
   스프링에서 다양한 기능들이 있습니다. 하지만 몇가지는 숨겨져있고, 또 몇가지는 드러나 있지만 실제로 어떤식으로 적용을 하는지를 몰라서 사용하지 않는 경우도 많은 것 같습니다. 지금까지 SpringFramework를 프로젝트에 적용해오면서 사용한 여러가지 방법들에 대해서 샘플 프로젝트를 가지고 다루어봅니다.
   대상 : Spring @MVC를 다루어본 초급 개발자 (여기서 초급이란 스프링에 대한 수준입니다.)
Spring Data
   DAO를 작성하다보면, 항상 반복적으로 CRUD 기능과 Paging 기능을 구현합니다. 그런 작업을 간편하게 해결해 줄 뿐 아니라 스프링 고유의 뛰어난 확작성 역시 제공하는 Spring Data 프로젝트를 소개하고 그 하위 프로젝트 중 하나인 Spring Data JPA와 Spring Data MongoDB 사용방법을 보여드리고, 그 동작 원리를 설명하겠습니다.
Spring Social
   요즘은 SNS에서 제공하는 Open API를 사용해서 자신의 애플리케이션에 SNS 기능을 접목시키는 서비스가 많습니다. 이런 서비스를 개발하다보면 각 SNS별로 통일지되 않는 다양한 방법이 제공되고 있어 개발자 입장에서는 상당히 귀찮고 괴로운 작업 이 많습니다. 이런 복잡한 SNS Open API를 쉽게 사용하기 위해서 스프링에서 내놓은 Spring Social 에 대해 소개를 하고 구조를 살펴보고, 데모와 함께 동작흐름을 살펴봅니다.

신청자는 봄싹 사이트(http://www.springsprout.org/)의 스웨어 모임에서 하시면 됩니다.
참가신청은 ‘회원’만 가능하니 회원 가입 후 신청을 부탁드립니다.
참가신청 페이지 : http://www.springsprout.org/study/4494/meeting/6044

마지막을 화끈하게~ 스프링 최신기술로 불사지르고.. 내년엔 게릴라성 스터디를 할까 구상 중입니다.

거럼 26일에 뵙겠습니다.

[Spring 3.1] 자바 설정 예제

먼저, XML 설정부터 볼까나..

<bean id="userDao" class="chapter06.exercise.aop12.UserDaoJdbc">
    <property name="dataSource" ref="dataSource" />
</bean>

<tx:annotation-driven />

<bean id="userService" class="chapter06.exercise.aop12.UserServiceImpl">
    <property name="userDao" ref="userDao" />
    <property name="mailSender" ref="mailSender" />
</bean>

<bean id="testUserService"
    class="chapter06.exercise.aop12.UserServiceTest$TestUserServiceImpl"
    parent="userService" />

<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<jdbc:embedded-database type="HSQL" id="dataSource">
    <jdbc:script location="member_table_1.sql" />
</jdbc:embedded-database>

<bean id="mailSender" class="chapter06.exercise.aop12.DummyMailSender" />

이 설정은 내가 강의할 때 사용하는 예제 코드에 들어있는 코드로, 토스3에 있는 코드를 기반으로 작성한 샘플 코드다. jdbc:embedded를 사용하는 등, 실습하기 손쉽게 조금 고친 부분이 있다.

이 설정을 스프링 3.1 자바 설정으로 다음과 같이 변경할 수 있다.

@Configuration
@EnableTransactionManagement
public class TestDaoConfg {
   
    @Bean
    public UserDao userDao(DataSource dataSource) {
        UserDaoJdbc userDaoJdbc = new UserDaoJdbc();
        userDaoJdbc.setDataSource(dataSource);
        return userDaoJdbc;
    }
   
    @Bean
    public UserService userService(UserDao userDao, MailSender mailSender){
        UserServiceImpl userServiceImpl = new UserServiceImpl();
        userServiceImpl.setUserDao(userDao);
        userServiceImpl.setMailSender(mailSender);
        return userServiceImpl;
    }
   
    @Bean
    public UserService testUserService(UserDao userDao, MailSender mailSender){
        TestUserServiceImpl userServiceImpl = new TestUserServiceImpl();
        userServiceImpl.setUserDao(userDao);
        userServiceImpl.setMailSender(mailSender);
        return userServiceImpl;
    }
   
    @Bean
    public MailSender mailSender(){
        return new DummyMailSender();
    }
   
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
   
    @Bean(destroyMethod="shutdown")
    public DataSource dataSource(){
        EmbeddedDatabaseFactory factory = new EmbeddedDatabaseFactory();
        factory.setDatabaseName("sample");
        factory.setDatabaseType(EmbeddedDatabaseType.HSQL);
        ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
        populator.addScript(new ClassPathResource("member_table_1.sql"));
        factory.setDatabasePopulator(populator);
        return factory.getDatabase();
    }
   

}

뭐 대부분은 문제가 아닌데… jdbc 네임스페이스를 대체하는 코드는 도무지 외울 수가 없다.. XML이 더 편하게 느껴진다. 잘못해서 destroyMethod라도 설정하지 않으면 어쩔것인가…

@EnableXxx과 TestContext 연동으로 XML에서 자바 설정으로 넘어가지 위해 열심히 코딩해준 건 고맙지만.. 아직 2% 부족하게 느껴진다.

[스프링 3.1] cache:annotation-driven을 확장하고파…

스프링은 빈 설정을 간편히 하라고 네임스페이스를 많이 제공해주는데, 실제로 개발할 때 매우 편합니다. 그냥 스프링이 제공해주는 그.대.로. 사용할 때에만요. 스프링 캐시의 핵심 API는 다음과 같습니다.

CacheManager: EhCache의 CacheManager와 이름이 같지만, 이건 패키지가 다르고 스프링이 제공하는 캐시 추상화의 핵심 인터페이습니다.

Cacahe: 이건 CacheManager에서 get(“캐시 이름”)을 사용해서 가져올 수 있는 클래스고요.

KeyGenerator: 캐시 키값을 생성하는 방식을 Strategy Pattern화 시켜둔걸로 보시면 됩니다. 기본 구현체로는 해당 객체의 hashCode()를 사용하는 DefaultKeyGenerator를 사용하는데, 분산 환경에는 적절치 못할 겁니다.

사실 얘네들 정도를 확장하려면, 더 깊게 들어가지 않아도 됩니다. 그런데 저는 좀 더 필요한 경우를 보게 됐습니다; 보게 됐다? 요구 사항이 있었습니다;

아무튼 이런 것들을 이용해서 Cache AOP를 제공할 때의 주요 API는 다음과 같습니다.

CacheInterceptor: MethodInterceptor의 구현체로, 스프링 AOP에서 캐시 기능을 Advice를 구현하나 핵신 구현체입니다.

CacheOperationSource: 이건 CacheInterceptor에서 사용하는 인터페이스로, 특정 메서드에서 수행할 캐시 오퍼레이션이 무엇인지 알려주는 역할을 합니다. 기본 구현체로는 AnnotationCacheOperationSource를 사용합니다.

BeanFactoryCacheOperationSourceAdvisor: 스프링 AOP를 아시는 분들은 뭔지 잘 아시겠죠. Advisor니까 Advice와 Pointcut의 조합이구요. 이 안에 기본으로 CacheOperationSourcePoincut이 Pointcut으로 들어있습니다. 따라서 캐시 적용 가능한 메서드에만 포인트컷이 걸립니다.

이것들을 모두 이용하는게…

[xml]
<cache:annotation-driven/>
[/xml]

이 한줄입니다. 이걸 풀어서 적으면 이렇게 됩니다.

[xml]
<!– cache setup –>
<bean id="annotationCacheOperationSource" class="org.springframework.cache.annotation.AnnotationCacheOperationSource" />
<bean id="cacheInterceptor" class="org.springframework.cache.interceptor.CacheInterceptor">
<property name="cacheDefinitionSources" ref="annotationCacheOperationSource" />
<property name="cacheManager" ref="cacheManager"/>
</bean>
<bean id="cacheAdvisor" class="org.springframework.cache.interceptor.BeanFactoryCacheOperationSourceAdvisor">
<property name="cacheDefinitionSource" ref="annotationCacheOperationSource" />
<property name="advice" ref="cacheInterceptor" />
</bean>

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache" />
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="ehcache.xml"/>
[/xml]

이 중에서 원하는 객체를 확장해서 교체하면 되겠죠. 끝~