Whiteship's Note


Spring + Ajax with DWR (Revolution)



이전 글의 예제 코드는 DWR을 그대로 사용했을 뿐, Spring은 사용하지 않았습니다. 다시말하면, Spring Container로 부터 bean을 가져온 것이 아니라, new라는 생성기를 사용하여 자바스크립트를 생성했습니다.

스프링 컨테이너가 관리하는 bean으로 자바스크립트를 생성하는 방법은 두 가지가 있습니다.
1. spring 생성기 사용하기.
2. 스프링 설정 파일에서 dwr 네임스페이스 사용하기.(스프링 2.0 이상에서 사용가능)

1. spring 생성기 사용하기.

dwr.xml을 다음과 같이 수정합니다.
new 생성기 대신 spring 생성기 사용하도록 수정.
class 송성 대신 beanName이라는 속성에 bean의 이름을 설정합니다.

<dwr>
    <allow>
        <convert converter="bean" match="whiteship.domain.Member" />
        <create creator="spring" javascript="MemberService">
            <param name="beanName" value="memberService" />
        </create>
    </allow>
</dwr>

그리고 Spring 설정 파일에 memberService라는 bean을 등록해야겠죠. 이 전 예제에서는 등록하지 않았었습니다.

    <bean id="memberService" class="whiteship.service.MemberServiceImpl" />

마지막으로 DWR이 스프링의 설정 파일을 알 수 있도록 설정해야 하는데, 기본으로 ContextLoaderListener를 통해 읽어오려고 합니다. 따라서 web.xml에 다음과 같이 설정되어 있다면, dwr.xml에 별도로 설정해 주지 않아도 됩니다.

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/**Context.xml</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>



2. 스프링 설정 파일에서 dwr 네임스페이스 사용하기.

이번에는 dwr.xml 파일 처럼 별도의 DWR 파일을 사용하지 않고, 스프링 설정 파일로만, DWR로 사용할 bean을 지정해 주는 방벙입니다.

먼저, web.xml에서 등록했던 DwrServlet을 DwrSpringServlet으로 변경합니다.(이제 dwr.xml은 삭제해도 됩니다.)
그럼 다음, 스프링 설정 파일에 dwr 네임스페이스를 추가합니다.
마지막으로, 자바스크립트로 노출시킬 bean 내부에 <dwr:remote> 엘리먼트를 사용하여 설정합니다. 그리고 기본 타입이 아닌 데이터를 변환하기 위해 사용했던 convertor를 등록합니다.

    <servlet>
        <servlet-name>dwr</servlet-name>
        <servlet-class>
            org.directwebremoting.spring.DwrSpringServlet
        </servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>

<?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:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd
http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd"
    default-autowire="byName">

    <bean id="memberService" class="whiteship.service.MemberServiceImpl">
        <dwr:remote javascript="MemberService" />
    </bean>

    <dwr:configuration>
        <dwr:convert type="bean" class="whiteship.domain.Member" />
    </dwr:configuration>

</beans>


클라이언트 코드는 수정할 것이 없습니다.

이렇게 하면, 스프링의 DI와 AOP를 적용한 자바 객체를 자바스크립트 형태로 변환해주고(DWR이), 이것을 클라이언트 자바스크립트에서 호출할 수 있게 됩니다.

2007/11/08 - [Spring In Action/16. Integrating with other web frameworks] - Spring + Ajax with DWR (Coding)
2007/11/08 - [Spring In Action/16. Integrating with other web frameworks] - Spring + Ajax with DWR


top

  1. 굴돌 2008.03.02 23:49 PERM. MOD/DEL REPLY

    생각보다 간단하군요!
    좋은자료 고맙습니다. :)
    링크 퍼갈께요~

    Favicon of http://whiteship.tistory.com BlogIcon 기선 2008.03.03 12:20 PERM MOD/DEL

    넹. :)

  2. 초보 2008.03.11 18:02 PERM. MOD/DEL REPLY

    여기 예제를 보고 따라보았는데요..

    1번째 Spring+DWR 은 에러는 안나는데 URL 에서 /dwr 확인시 .js 가 생성이 안되어 정상적으로
    실행을 해볼수 없었구요.
    2, 3 번 소스 다운받아 해보았는데 제대로 안되네요.. tomcat 뜰때 에러 뜨네요..경로 문제인지.
    경로 문제면 1번할때도 문제가 생겨야 하는데..2,3번은 톰캣 구동시 오류가 나서 볼수조차 없구요.
    무엇이 문제인지 모르겠네요.

    Favicon of http://whiteship.tistory.com BlogIcon 기선 2008.03.11 18:10 PERM MOD/DEL

    흠.. /dwr에 js는 런타임 시에 DwrServlet이 동적으로 생성해 줍니다. 만약.. 그게 생성이 안되었다면.. 무언가 설정이 잘 못 되었을텐데요.

    예제 코드를 실행해보시려면요. Run As Server 메뉴를 클릭하구요. Manually define a new server를 선택하신 다음에 돌려보세요.

    전 방금 확인해봤더니.. 잘 돌아가는데요.. 훔;;

  3. 초보 2008.03.11 19:05 PERM. MOD/DEL REPLY

    이거 어제부터 2틀재 돌려보는중인데요..방금 리플 달아주셨네요..
    원인을 알아보니..
    springContext.xml 에서

    <bean id="memberService"
    class="whiteship.service.MemberServiceImpl">
    <dwr:remote javascript="MemberService"/>
    </bean>

    이 부분만 들어가면 tomcat 로그에
    심각: Error listenerStart
    2008. 3. 11 오후 6:57:17 org.apache.catalina.core.StandardContext start
    심각: Context [/SpringAjax3] startup failed due to previous errors

    이렇게 찍히면서 안되네요..
    경로 문제일까요??
    참고로 저는 톰캣5.5 를 따로 두고 ant로 빌드로 톰캣에 war로 넣어줍니다.. 혹시 이거 때문에..

    Favicon of https://whiteship.tistory.com BlogIcon 기선 2008.03.11 23:02 신고 PERM MOD/DEL

    에러로그 전부를 제 이메일로 보내주세요.

    저는 이클리스에서만 실행시켜봤지, WAR로 묶어서 배포해보진 않아서 어떤 상황인지 예측이 안 되네요.

    아마도 배포 문제인듯 싶은데요. 로그에 보니까 previous errors 때문에 톰캣을 못 띄웠다고 되어 있는데.. 에러 로그를 전부 보고 싶습니다. :)

  4. 초보 2008.03.12 08:56 PERM. MOD/DEL REPLY

    에러 내용은 제가 올렸던 저 내용이 전부입니다. 톰캣 구동시 카탈리라 로그에서 이 로그만 뿌려주고는
    해당 웹app가 뜨지 않습니다.

    에러내용

    2008. 3. 11 오후 7:11:38 org.apache.catalina.core.StandardContext start
    심각: Error listenerStart
    2008. 3. 11 오후 7:11:38 org.apache.catalina.core.StandardContext start
    심각: Context [/SpringAjax3] startup failed due to previous errors

    위와 같은 문제로 struts + Spring 연결 설정시에도 한번 났었는데...web.xml 에서 경로패스가
    조금 틀려서 그렇더군요..
    이번에도 그런듯싶어 경로를 이것저것 수정해보았는데...

    결론은

    <bean id="memberService"
    class="whiteship.service.MemberServiceImpl">
    <dwr:remote javascript="MemberService"/>
    </bean>

    web.xml 에서 이 부분만 만나면 에러를 떨어뜨립니다.

    Favicon of http://whiteship.tistory.com BlogIcon 기선 2008.03.12 10:52 PERM MOD/DEL

    저는 잘 돌아가는데요;;

    의심스러워 하시는 부분에는 전~혀 문제가 없습니다. 그냥 일반적인 스프링 설정일 뿐입니다.

    그냥 이클립스에서 돌려보시죠; 이클립스 프로젝트를 그냥 압축한거니까 이클립스에선 잘 돌아갈겁니다. ^^;;

  5. 꿀냥 2011.08.25 20:37 PERM. MOD/DEL REPLY

    질문이 있습니다.

    DWR 관련하여 프로젝트를 만들고
    압축파일을 복사 했습니다..

    화면까지는 나오는데
    텍스트 입력창에 글을 쓰기만 하면

    session error라고 경고 창이 뜨네요..
    세션 설정은 안보이는거 같은데요...

    이상하네요;;

  6. 따뜻한호빵 2012.02.01 11:20 PERM. MOD/DEL REPLY

    꿀냥님. web.xml 에서 dwr servlet 설정에서

    <init-param>
    <param-name>crossDomainSessionSecurity</param-name>
    <param-value>false</param-value>
    </init-param>

    추가하시면 될 거 같네요.

Write a comment.


Spring + Ajax with DWR (Coding)



다음의 순서대로 코딩을 할 수 있습니다.(꼭 이 순서를 지켜야 하는 것은 아닙니다.)
0. POJO로 Ajax (자바스크립트로 노출시킬) 서비스 구현.
1. web.xml에 DWR Servlet 등록하기.
2. dwr.xml 작성하기.
3. 클라이언트 코드 작성하기.
    3-1. 자바스크립트 등록하기.
    3-2. 요청하기.
    3-3. 요청 처리하기.

0. POJO로 Ajax (자바스크립트로 노출시킬) 서비스 구현.
사용자 삽입 이미지
매우 단순하게 구현했으며, MemberService 인터페이스에서는 Member의 이름으로 회원을 검색하여 결과를 리스트 형태로 반환하는 메소드를 가지고 있습니다.

1. web.xml에 DWR Servlet 등록하기.

web.xml에 다음과 같은 코드를 추가합니다.
    <servlet>
        <servlet-name>dwr</servlet-name>
        <servlet-class>
            org.directwebremoting.servlet.DwrServlet
        </servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dwr</servlet-name>
        <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

/dwr/ 로 시작하는 모든 요청을 DwrServlet이 처리하도록 설정하였습니다.

2. dwr.xml 작성하기.

WEB-INF/ 폴더에 dwr.xml 파일을 다음과 같이 작성합니다.
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">

<dwr>
    <allow>
        <convert converter="bean" match="whiteship.domain.Member" />
        <create creator="new" javascript="MemberService">
            <param name="class"
                value="whiteship.service.MemberServiceImpl" />
        </create>
    </allow>
</dwr>

Member 타입으로 캐스팅 할 수 있도록, converter를 등록해줍니다.
new 생성기를 사용하여, MemberService라는 이름의 자바스크립트를 생성합니다. 이 자바스크립트는 MemberServiceImpl 자바 클래스를 가지고 작성합니다.

=================================================================================
이제 서버쪽에서 설정해야 할 내용은 끝입니다. 이것으로 클라이언트 쪽에서 자바 객체의 메소드를 자바스크립트에서 호출할 수 있습니다. 어떻게 호출하는지 살펴보겠습니다.

3. 클라이언트 코드 작성하기.

3-1. 자바스크립트 등록하기.

View에서 사용할 자바스크립트를 등록합니다.
<script type='text/javascript' src='dwr/engine.js'></script>
<script type='text/javascript' src='dwr/interface/MemberService.js'></script>
<script type='text/javascript' src='dwr/util.js'></script>

맨 아래 한 줄은 옵션입니다. 위의 두 줄은 필수이며, 위의 자바스크립트 파일들이 없다고 걱정하시지 않아도 됩니다. web.xml에서 설정한 dwr/ 경로를 통해 DwrServlet이 알아서 처리할 것입니다.

두 번째 자바스크립트 파일의 이름은 dwr.xml에서 자바 클래스를 자바스크립트로 변환할 때 사용하기로 한 이름으로 설정해주시면 됩니다.

3-2. 요청하기.

폼에서 다음과 같은 input 엘리먼트가 있고, 해당 엘리먼트에서 자바스크립트를 호출합니다.
<form name="memberForm">
    <input type="text" name="name" maxlength="10" onkeyup="inputChanged();" />
</form>

function inputChanged() {
    var name = document.memberForm.name.value;
    if(name.length > 1) {
        MemberService.get(name, updateTable);
    } else {
        DWRUtil.removeAllRows("memberTable");
    }
}


3-3. 요청 처리하기.

위의 자바스크립트에서 updateTable이 바로 요청의 결과를 처리할 자바스크립트 입니다. 다음과 같이 작성합니다.

function updateTable(results) {
    DWRUtil.removeAllRows("memberTable");
    DWRUtil.addRows("memberTable", results, cellFuncs);
}

var cellFuncs = [
    function(data) { return data.name; },
    function(data) { return data.email; }
];

요청의 결과를 가져와서 테이블을 채워줄 때 해당 데이터에서 어떤 필드로 테이블을 채워야 하는지 정의하기 위해 cellFuncs 라는 구조체(?)를 정의해 주었습니다.

참조 : Spring In Action 16장
top

Write a comment.


Spring + Ajax with DWR



DWR은 Direct Web Remoting의 약어로 자바 객체를 기반으로 자바스크립트 코드를 생성하여, 클라이언트 자바스크립트에서 (생성한 자바스크립트를 사용하여) 서버쪽 자바 객체의 메소드를 호출할 수 있도록 해주는 프레임워크입니다.

수많은 Ajax 프레임워크 중에서 DWR이 Spring와 밀접한 관계가 된 것은 DWR 자체에서 Spring을 지원하는 기능을 구현했기 때문입니다. 따라서 매우 간단하게 Spring와 연동하여 사용할 수 있습니다. 연동한다는 의미를 좀 더 구체적으로 서술하면, Spring Container가 관리하는 bean을 DWR을 사용하여 자바스크립트로 노출시킬 수 있다는 것입니다.

Spring MVC를 사용하든, Spring Web Flow를 사용하든 관계가 없습니다. 어차피 요청은 자바스크립트에서 할 것이고, 이 요청을 처리하는 녀석은 DWR Servlet이지, Spring의 Dispatcher Servlet이 아닙니다. 특정 요청들을 한 곳으로 집중한다는 측면에서 둘은 비슷하지만, View Resolving, Hadler Mapping 까지 관장하는 Spring의 Dispatcher Servlet과는 전혀 다른 일을 합니다. DWR Servlet에 등록되어 있는 자바 객체를 바탕으로 요청을 처리할 자바스크립 코드를 생성하고, 그것으로 처리한 결과를 다시 (클라이언트)웹브라우저에게 돌려주는 역할을 합니다.

사용자 삽입 이미지

클라이언트 자바스크립트에서 특정 요청을 호출하면, 해당 요청을 Dwr Servlet이 받아들이고, Dwr Servlet은 drm.xml에 설정된 정보를 바탕으로 해당 요청을 처리할 자바 객체의 자바스크립트(DWR이 알아서 생성합니다.)를 호출하고 그 결과를 다시 돌려주게 됩니다. 그럼 돌려받은 정보로 비동기식으로 화면에 보여주는 것은 클라이언트쪽에서 알아서 하겠죠.

위 그림에서 Spring이 낑겨들어가는 쪽은 바로 녹색 네모 둘을 연결한 빨간 선입니다. creator는 자바스크립트 생성기를 말하는데, 자바스크립트 코드로 생성할 자바 객체를 지정해 주는데, 이 객체를 Spring Container에 있는 bean을 가져와서 생성할 수 있도록 설정할 수 있습니다.

왜? 스프링 컨테이너가 관리하는 bean으로 설정하려고 할까요? 스프링이 제공하는 DI와 AOP와 같은 기능을 사용할 수 있기 때문입니다. 그런 기능들을 사용하지 못한다면, 자바스크립트로 노출하고 싶어하는 자바 객체 내부에 해당 객체가 필요로 하는 모든 것들이 들어있어야합니다.(new를 많이 사용해서 코딩했겠죠.) 스프링을 사용한다면, 그럴 필요가 없어집니다. 이 말은 더욱 유연하고 유지관리하기 편리한 객체를 자바스크립트로 노출 시킬 수 있다는 뜻입니다.

설명은 이만하고, 다음 글에서 코딩을 해보겠습니다.
top

  1. Favicon of http://blog.paran.com/devbada BlogIcon xsitherx 2011.06.15 16:15 PERM. MOD/DEL REPLY

    안녕하세요!

    DWR에 대해 검색하던 중 찾게 되었습니다.

    쉽게 잘 설명을 해주셨네요~ ^^;;

    다름이 아니라 이 글의 일부를 조금 퍼가도 될런지 해서~ 댓글 남깁니다 :D


    그럼 수고하세요! ^^

Write a comment.