Whiteship's Note


[Spring Web Flow] booking 예제 분석 3 - webmvc-config.xml 설정

Spring Web Flow/etc : 2009.10.16 20:28


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <!-- Scans for application @Components to deploy -->
    <context:component-scan base-package="org.springframework.webflow.samples.booking" />

    <!-- Imports the configurations of the different infrastructure systems of the application -->
    <import resource="webmvc-config.xml" />
    <import resource="webflow-config.xml" />
    <import resource="data-access-config.xml" />
    <import resource="security-config.xml" />

</beans>

web.xml에 유일하게 등록되어 있는 빈 설정파일이었는데, 열어보니 네 개의 다른 빈 설정 파일들을 import 하고 있습니다. 이 중에서 webmvc-config.xml 파일을 보겠습니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <!-- Maps request paths to flows in the flowRegistry; e.g. a path of /hotels/booking looks for a flow with id "hotels/booking" -->
    <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
        <property name="order" value="0" />
    </bean>

    <!-- Maps request paths to @Controller classes; e.g. a path of /hotels looks for a controller named HotelsController -->
    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
        <property name="order" value="1" />
        <property name="defaultHandler">
            <!-- If no @Controller match, map path to a view to render; e.g. the "/intro" path would map to the view named "intro" -->   
            <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
        </property>
    </bean>

    <!-- Resolves logical view names returned by Controllers to Tiles; a view name to resolve is treated as the name of a tiles definition -->
    <bean id="tilesViewResolver" class="org.springframework.js.ajax.AjaxUrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.webflow.mvc.view.FlowAjaxTilesView"/>
    </bean>

    <!-- Configures the Tiles layout system -->
    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/layouts/layouts.xml</value>
                <value>/WEB-INF/views.xml</value>
                <value>/WEB-INF/hotels/views.xml</value>
                <value>/WEB-INF/hotels/booking/views.xml</value>
            </list>
        </property>
    </bean>
   
    <!-- Dispatches requests mapped to POJO @Controllers implementations -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

    <!-- Dispatches requests mapped to org.springframework.web.servlet.mvc.Controller implementations -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />

    <!-- Dispatches requests mapped to flows to FlowHandler implementations -->
    <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
        <property name="flowExecutor" ref="flowExecutor"/>
    </bean>

    <!-- Custom FlowHandler for the hotel booking flow -->
    <bean name="hotels/booking" class="org.springframework.webflow.samples.booking.BookingFlowHandler" />   
       
</beans>

1. org.springframework.webflow.mvc.servlet.FlowHandlerMapping

이 클래스는 (FlowUrlHandler를 사용하여) URL을 분석하여 해당 URL을 처리할 FlowHandler를 찾아서 반환해주는 역할을 합니다.

먼저, ApplicationContext에서 찾고, 다음은 FlowRegistry에서 찾아보고, 그래도 없으면 null을 반환합니다. 그럼 이제 이 다음 핸들러 맵핑 체인을 타게 되겠죠.

따라서 이 클래스에 설정할 수 있는 주요 속성은 FlowUrlHandler와 FlowRegistry입니다. 하지만 이중에서 FlowUrlHandler는 스프링이 기본으로 제공하는 DefaultFlowHandler를 사용하는게 일반적일 것 같군요.

2. org.springframework.webflow.mvc.servlet.FlowHandlerAdapter

이 녀석은 FlowHandler가 담당하기로 한 요청을 FlowExecutor를 이용해서 처리하는 일련의 워크 플로우에 따라 실행시켜주는 곳입니다. 실질적인 작업들은 상당 부분을 위임하고 있으면서 그 골격을 만들어둔 곳입니다.

플로우 id에 해당하는 플로우 정의를 가져오고, 플로우 정의로 플로우 실행 객체(FlowExecution)을 만들고, FlowUrlHandler로 필요한 execution 매개변수도 만들는 등.. 한 번의 코드리뷰로 파악하기에는 분량이 많더군요. 특히 FlowExecutor 쪽으로 들어가면.. 크헉.. 클래스가 팍팍 늘어납니다.

3. org.springframework.webflow.mvc.servlet.FlowHandler

특정 플로우 정의에 접근하는 것을 커스터마이징 할 때 이 녀석을 구현한다고 합니다.
- Launch executions of that flow with data in the execution input map
- 플로우 결과는 맘대로 처리하고 싶을 때.
- 플로우에서 다루지 않은 예외를 맘대로 다루고 싶을 때.

위 예제에서 BookingFlowHandler 이녀석이 구현한 건 두 개.
- String handleExecutionOutcome: 실행이 끝났을 때 갈 위치
- String handleException: 에러가 발생했을 때 갈 위치



top

Write a comment.


[JUnit] @Rule TemporaryFolder 사용하기

모하니?/Coding : 2009.10.16 16:26


public class DBUnitSupportTest {
   
    DBUnitSupport dbUnitSupport;

    @Rule public TemporaryFolder folder = new TemporaryFolder();
    @Autowired DataSource dataSource;
    File tempFile;
   
    @Before
    public void setUp() throws Exception{
        dbUnitSupport = new DBUnitSupport(dataSource);
    }
   
    @Test
    public void exportXls() throws Exception {
        tempFile = folder.newFile("temp.xls");
        dbUnitSupport.setExportedFile(tempFile);
        assertThat(tempFile.length(), is(0L));
        dbUnitSupport.exportXlsFrom("code", "item", "users", "role", "users_role");
        assertThat(tempFile.length(), not(0L));
    }
   
    @After
    public void after(){
        assertFalse(tempFile.exists());
    }

흠.. 좋군요!! 파일이 생겨나는 테스트를 하고 나서 매번 수동이든 코드로든 지워야 하는 번거로움이 없어졌습니다.

사실 파란색 코드는 지워도 그만인데, 아직은 TemporaryFolder Rule이 어떻게 동작하는지 확실하게 파악된 상태가 아니여서 남겨뒀습니다.

파일이 delete() 되지 않을 경우에 대비해서 말이죠. 사실 이 아래 글에 작성한 코드에는 치명적인 결함이 있었는데, 그 사실을 이번 테스트를 작성하다가 알게됐습니다. @_@;;

테스트 작성이 여러모로 도움을 주는군요.

참조: http://www.catosplace.net/blogs/personal/?p=116
top

  1. Favicon of http://decoder.tistory.com BlogIcon decoder 2009.10.16 17:08 PERM. MOD/DEL REPLY

    어후, 이거 좋네요. ^^
    매번 테스트 할때마다 디렉토리 만들고 지우고 난리도 아니었는데 ㅠㅠ;

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2009.10.16 20:28 신고 PERM MOD/DEL

    네 사용법도 간단하고 좋아요

Write a comment.


[DBUnit] 테이블 데이터를 엑셀로 export

모하니?/Coding : 2009.10.16 12:48


테스트
    @Test
    public void exportXls() throws Exception {
        dbUnitSupport.exportXlsFrom("code", "item", "users", "role", "users_role");
        assertTrue(new File(DBUnitSupport.EXPORTED_XLS_FILE).exists());
    }

구현
    protected void exportXlsFrom(String... tableNames) throws Exception {
        IDataSet dataSet = getConnection().createDataSet(tableNames);
        XlsDataSet.write(dataSet, new FileOutputStream(new File(EXPORTED_XLS_FILE)));
    }

흠.. 간단하네요. 간단 간단..

그런데. 테스트 할 때 생기는 파일들은 수동으로 지우기도 귀찮고.. 버전관리에 들어가면 더더욱 안 될 듯하고..
JUnit을 4.7로 올리고, @Rule 이라는 걸 써봐야겠습니다.
top

Write a comment.


[ToDo] 20091016

모하니?/Planning : 2009.10.16 10:24


1. 회사

1-1. DBUnit으로 현재 DB의 데이터를 Excel로 뽑아보기. (1시간) (1시간)
1-2. 기초 데이터 편집하기. (20분) (20분)
1-3. DBUnit으로 서버와 로컬 DB에 기초 데이터 넣기. (1시간) (1시간)

2. SWF

2-1. booking 예제 분석 및 정리 (2시간)
2-2. 봄싹에 적용 (2시간)

3. 번역

3-1. 하이버네이트 2장 (2시간)

4. 영어

4-1. Unit 2개 풀기 (2시간)
4-2. 동강 듣기 (1시간)

오늘도 달리자 달려!!!!!!!

1. 회사

- 소요 시간: 2시간 20분 (10시 30분 ~ 12시 50분)
- 예상 시간 적중.
- 스프링과 JUnit 라이브러리 업데이트와 테스트에 @Rule 적용하기는 번외로 추가.

@Rule 적용해 봅시다. ㄱㄱㄱㄱ!

5. 예외상황

- 소요 시간: 3시간 (1시 30분 ~ 4시 30분)
- 이클립스가 죽어버림. 젠장... 얼마나 됐나고..
- 이클립스 설치/플러긴 설치
- @Rule 적용

이제 SWF ㄱㄱ

2. SWF

- 소요 시간: 3시간(5시 ~ 8시)
- 뭘 했다고 시간이 이렇게 후딱 가버리지.. 아..

이제 집에가서 번역하고 영어만 하면 되나..
오늘은 영어부터 해야겠다.


'모하니? > Planning' 카테고리의 다른 글

백기선 2010 목표  (12) 2010.02.15
봄싹 Career Path  (6) 2009.12.17
이번주 토요일 IBM dW "웹 개발 다반사"  (2) 2009.12.03
봄싹을 알리러 갑니다.  (6) 2009.11.24
[Atlassian] 이직 계획  (2) 2009.11.02
[ToDo] 20091016  (0) 2009.10.16
[ToDo] 오늘 할 일 - 할일(예상 소요 시간)(실제 소요 시간)  (4) 2009.10.15
2009년 마무리로 할 일  (4) 2009.10.08
9월에 할 일 정리  (10) 2009.08.31
공부할 것 정리  (6) 2009.03.16
요즘 내 우선순위  (2) 2009.01.22
top

TAG TODO

Write a comment.


[JRebel] JRebel 설치 및 간단 사용법





참~ 쉽죠~
top

TAG JRebel
  1. Favicon of http://naucika.pe.kr BlogIcon naucika 2009.10.16 16:09 PERM. MOD/DEL REPLY

    그런데 이녀석 클래스량이 많아지면, PermGen 오류가 발생하는군요. jvm -XX:MaxPermSize=128m 정도로 조정해줘야 한다네요.~ 기존 WAS의 autoreloding 도 wtp 에서 꺼주는 센스.

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2009.10.16 16:29 신고 PERM MOD/DEL

    넹.. 톰캣에서는 오토로딩 몇 번 하면 작은 프로젝트인데도 메모리 부족해서 죽어버리기 일수인데,

    저 녀석을 사용하면 저장 버튼 누른 순간까지 변경된 클래스들과 관련있는 부분만 다시 읽어주기 때문에 꽤 좋은 것 같아요.

  2. Favicon of https://helols.tistory.com BlogIcon is윤군 2009.10.16 16:55 신고 PERM. MOD/DEL REPLY

    이따가 집에가서 ㄱㄱ 해볼끼요!!
    잘볼께요;;ㅋㅋ

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2009.10.16 20:28 신고 PERM MOD/DEL

    그랭. 해보고나서 말해. 선물 줄테니까 캬캬

Write a comment.