Spring Annotation Driven 일때 DWR세팅

Published on: 2011. 8. 24. 18:58 by louis.dev

DWR - DWR 실행시 Alert창으로 Session Error란 에러가 발생될때

Published on: 2011. 1. 31. 12:13 by louis.dev

서버에 올린후 테스트하려고 하니 DWR에러가 나더군요. log를 확인해 보니
A request has been denied as a potential CSRF attack.
란 에러를 뿌리며 에러가 발생합니다.

이런에러가 발생할 때는 web.xml의 DWR 설정에 init-param 설정으로 간단하게 처리할 수 있습니다.


 <servlet>
  <servlet-name>dwr-invoker</servlet-name>
  <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
  <init-param>
   <param-name>debug</param-name>
   <param-value>true</param-value>
  </init-param>
  <init-param>
   <param-name>crossDomainSessionSecurity</param-name>
   <param-value>false</param-value>
  </init-param>
  </servlet>
 <servlet-mapping>
  <servlet-name>dwr-invoker</servlet-name>
  <url-pattern>/dwr/*</url-pattern>
 </servlet-mapping>

위와 같이 crossDomainSessionSecrurity를 false로 주면 됩니다. 이 옵션을 false를 줌으로서 어떤 보안상에 문제가 발생하는지는 좀더 알아봐야겠네요.

DWR - (3) DWR에서 자바 VO 객체 사용하여 파라미터 전달하기

Published on: 2010. 12. 29. 16:36 by louis.dev

DWRTutorial.war


지난 두번째의 튜토리얼에서는 자바 메소드를 호출할때 전달 파라미터 값으로 간단한 String만 파라미터로 전달했습니다.

이런 방식은 간단한 메소드 호출시에 사용하지만 실제로 프로젝트를 진행하다보면 전달인자가 하나인 경우는 거의 없습니다. 그리고 전달인자가 많아지면 적당한 VO객체를 만들어서 객체안에 데이터를 넣고 파라미터로 던집니다.
자바에서 이렇게 작업하듯 DWR에도 위와 같이 작업할 수 있습니다.

 예)  DwrVO vo = new DwrVO();
       vo.setTitle("테스트용");
       vo.setName("전근재");

       testMethod( vo );



1. 먼저 VO class를 만들겠습니다.
package net.tutorial.dwr.vo;

public class DwrVO {
	private String title;
	private String name;
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "DwrVO [name=" + name + ", title=" + title + "]";
	}
	
	
}


2. 전달 파라미터를 DwrVO로 받는 테스트 method를 만듭니다.

package net.tutorial.dwr;

import net.tutorial.dwr.vo.DwrVO;

public class TutorialDWR {
	public String testDWR( String param ){
		return "parameter : " + param; 
	}
	public String paramTestDWR( DwrVO paramVO ) {
		return "Dwr VO : " + paramVO.getTitle() + " " + paramVO.getName();
	}
}


위와 같이 paramTestDWR 같은 메소드를 작성합니다. 이 메소드는 전달 파라미터로 DwrVO를 받고 그 내용을 출력하는 간단한 메소드 입니다.

3. dwr.xml에 convert 엘리먼트를 통해 VO로 사용할 클래스를 등록합니다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC 
	"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" 
	"http://getahead.org/dwr/dwr20.dtd">

<dwr>
	<allow>
  		<create creator="new" javascript="Tutorial">
  			<param name="class" value="net.tutorial.dwr.TutorialDWR"/>
  		</create>
  		<!-- 이와 같이 DwrVO를 bean으로 등록해 둡니다. -->
  	  	<convert converter="bean" match="net.tutorial.dwr.vo.DwrVO"/>
  	</allow>
</dwr>


4. html을 작성합니다.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
<script type='text/javascript' src='/DWRTutorial/dwr/interface/Tutorial.js'></script><!-- 반드시 작성자에 맞게 추가되어야 합니다. -->
<script type='text/javascript' src='/DWRTutorial/dwr/engine.js'></script>
<script type="text/javascript">
	function testDWR() {
		var name = document.getElementById("name").value;
		var title = document.getElementById("title").value;
		//이렇게 위에 convert로 사용한 vo class의 같은 field이름으로 json object를 만든다
		var obj = { "name" : name, "title": title}
		//이렇게 만든 json object를 파라미터로 던지면 DWR이 자동으로 jsonObject를 컨버팅하여
		//자바 class에서 DwrVO 를 사용할 수 있게 해준다
		Tutorial.paramTestDWR( obj, function( data ) {
			alert( data );
		});
		
	}
</script>

</head>
<body>
	<input type="text" id="name"/><br/>
	<input type="text" id="title"/><br/>
	<button onclick="testDWR()">테스트</button>
</body>
</html>


5. 결과


이렇게 간단하게 스크립트의 Json과 자바 VO 객체간의 convert 설정을 통해 맵핑을 시켰습니다.
이렇게 간단한 경우도 있지만, VO가 다른 VO를 가지고 있다거나, VO가 List형의 VO를 가지고 있다거나 할때는 어떻게 해야 할까요?
이것도 위와 같이 dwr.xml에 convert 설정을 해준뒤 Json형태로 변환하면 자동으로 자바 VO에 저장되게 되어있습니다.

dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC 
	"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" 
	"http://getahead.org/dwr/dwr20.dtd">

<dwr>
	<allow>
  		<create creator="new" javascript="Tutorial">
  			<param name="class" value="net.tutorial.dwr.TutorialDWR"/>
  		</create>
  		<!-- 이와 같이 DwrVO를 bean으로 등록해 둡니다. -->
  	  	<convert converter="bean" match="net.tutorial.dwr.vo.DwrVO"/>
  		<convert converter="bean" match="net.tutorial.dwr.vo.InnerDwrVO"/>
  		<convert converter="bean" match="net.tutorial.dwr.vo.DwrListTestVO"/>
  		<convert converter="bean" match="net.tutorial.dwr.vo.DwrListVO"/>
  	</allow>
</dwr>


이렇게 해당 VO를 convert 설정을 통해 등록해 둡니다.

만약 VO가 VO를 가지고 있는 경우라면.
package net.tutorial.dwr.vo;

public class DwrVO {
	private String title;
	private String name;
	
	InnerDwrVO innerDwrVO;
	
	public DwrVO() {
		this.innerDwrVO = new InnerDwrVO();
	}
	//getter setter method 생략합니다.
}

위와 같이 DwrVO가 InnerDwrVO라는 VO를 가지고 있다면, json은 다음과 같이 만들어 주면 됩니다.
<script type="text/javascript">
	function testDWR() {
		var name = document.getElementById("name").value;
		var title = document.getElementById("title").value;

		var obj = { "name" : name, "title": title, "innerDwrVO" : {
				"innerName" : "전근재", "innerAddress" : "지구어딘가"
			} };

		Tutorial.paramTestDWR( obj, function( data ) {
			alert( data );
		});
		
	}
</script>

이런식으로 자바의 VO와 똑같은 구조로 만들면 됩니다.

또 다른 경우로 VO 가 List VO를 가지고 있는 경우라면
public class DwrListTestVO {
	List<DwrListVO> persons;
	public DwrListTestVO() {
		persons = new ArrayList<DwrListVO>();
	}
}
class DwrListVO {
	private String name;
	private int age;
}
//getter setter 추가해야합니다.

이런 구조라면 dwr.xml에 해당 VO들을 convert로 추가해 주고 json은 이렇게 만들어 주면 됩니다.
<script type="text/javascript">
	function testDWR() {
		//JSON 배열로 선언
		var obj = {"persons" : [ {"name" : "전근재",age : 27},{"name" : "d",age : 50}] };

		Tutorial.listTestDWR( obj, function( data ) {
			alert( data );
		});
		
	}
</script>


이렇게 하면 됩니다. 참 간단하죠?^^;;

DWR - (2) JSP + Eclipse를 통해 DWR 사용하기

Published on: 2010. 12. 29. 11:52 by louis.dev
이번시간에는 eclipse IDE에서 DWR을 사용하는 방법을 진행해 보겠습니다.
작업순서

1. eclipse를 실행시키고 DynamicWebProject를 선택하여 프로젝트를 생성합니다.

2. DWR라이브러리를 다운로드 받은 후 WebContent/WEB-INF/lib 디렉토리에 복사합니다.
DWR이 3. 버전까지 나왔지만 아직까지 3버전은 버그가 많은것 같아 2버전으로 진행하겠습니다.
그리고 DWR과 dependency관계인 apache의 commons-loggin 을 다운받아 이것도 lib에 풀어 넣습니다.

원래 jar파일 이름은 dwr.jar파일이지만, 나중에 프로젝트에 몇버전이 적용되어 있는지 확이하기 위해 라이브 러리 이름뒤에 버전을 붙여 두었습니다.

3. DWR에서 불러 올수 있는 클래스를 만듭니다.

아래의 코드와 같이 net.tutorial.dwr 패키지를 생성후 TutorialDWR 클래스를 생성합니다. 그후 testDWR이라는 메소드를 생성하고 다음과 같이 생성합니다.
>package net.tutorial.dwr;

public class TutorialDWR {
	public String testDWR( String param ){
		return "parameter : " + param; 
	}
}


view page에서 TutorialDWR의 testDWR을 콜해서 제대로 return값이 나오는지 확인하면 될겁니다.

4. 위에서 작성한 TutorialDWR클래스와 view page에서 사용할 자바스크립트 Object 이름과 맵핑을 시켜줍니다.
WEB-INF 디렉토리 아래에 dwr.xml을 만듭니다.(web.xml과 같은 위치입니다.)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC 
	"-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" 
	"http://getahead.org/dwr/dwr20.dtd">

<dwr>
	<allow>
  		<create creator="new" javascript="Tutorial">
  			<param name="class" value="net.tutorial.dwr.TutorialDWR"/>
  		</create>
  	</allow>
</dwr>

위와 같이 설정합니다.
1) create : Tutorial 이라는 이름으로 자바 Object를 생성합니다.
2) param : net.tutorial.dwr.TutorialDWR이라는 자바 클래스를 맵핑시키겠다는 뜻입니다. 즉 viewpage에서는 Tutorial.testDWR()로 method를 부르면 이와 매핑된 TutorialDWR이라는 클래스의 testDWR method가 실행 되는것입니다.

5. web.xml에 다음을 추가합니다.

<servlet>
  <servlet-name>dwr-invoker</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-invoker</servlet-name>
  <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>


이로서 DWR을 사용하기 위한 세팅은 모두 끝났습니다.

DWR은 편리하게 dwr에 매핑된 class가 제대로 동작하는지 알수 있게 테스트페이지를 자동으로 만들어줍니다. 테스트 페이지에 접속하여 제대로 해당 method가 작동중인지 확인해 보겠습니다.

1. 서버를 작동후 http://${domain}/${context}/dwr 로 접근하시면 됩니다. 보통 로컬에서 테스트함으로 저는 http://localhost:8080/DWRTutorial/dwr 로 접근해 보겠습니다.

 


다음과 같은 페이지가 뜨면 DWR세팅이 제대로 된것입니다. 다음과 같은 페이지가 뜨지 않는다면 DWR세팅이 잘못된 것이니 처음부터 차근차근 확인해 보세요~^^

위의 페이지에서 Tutorial이라는 글씨를 클릭합니다. 위 스샷에서 보실수 있듯이 Tutorial = net.tutorial.dwr.TutorialDWR 이 맵핑 되어 있는것을 알수가 있습니다. 

 


위와 같은 텍스트로 된 페이지를 확인 하실수 있습니다. 하단의 There are 10 declared methods 에 자바 클래스에 구현되어 있는 method 들이 리스트 되어 있습니다. ( 자바의 모든 class 는 Object Class를 상속받고 있기 때문에 Object에서 구현되어 있는 wait, equals, toString.. 메소스 들을 보실수 있습니다. 하지만 이 메소스들은 구현되어 있지 않기 때문에 빨간 글씨로 warning이 표시되면서 execute버튼을 눌러도 실행이 되지 않습니다.

이중 Warning이 뜨지 않은 testDWR 메소드에 파라미터로 아무거나 입력하고 Execute를 누르시면 해당 메소드를 실행후 리턴되는 값을 확인 할 수 있습니다.


이로서 DWR 테스트가 완료 되었습니다. 그럼 이제 실제 view page에서 DWR을 적용하여 사용해 보겠습니다.
DWR을 view Page에서 사용하려면 위 스크린샷의 빨간 칸이 쳐져 있는 js파일을 viewpage에 추가해야 합니다. (실제로 저 js파일들이 생성되는것은 아니고 dwr이 가상으로 만들어주는 js파일입니다. 필수는 Tutorial.js-사용자분이 등록한 이름의 js, engine.js이고 선택옵션은 utli.js입니다.)

eclipse의 WebContent밑에 test.html파일을 만들겠습니다.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
<script type='text/javascript' src='/DWRTutorial/dwr/interface/Tutorial.js'></script><!-- 반드시 작성자에 맞게 추가되어야 합니다. -->
<script type='text/javascript' src='/DWRTutorial/dwr/engine.js'></script>			
<script type="text/javascript">
	function buttonClick() {
		var text = document.getElementById("text1").value;
		Tutorial.testDWR( text, callbackFunction);		//TutorialDWR클래스와 매핑된 Tutorial Object를 
														//이용하여 testDWR 메소드를call 합니다.
		/*
			testDWR method를 정의할때 전달 파라미터로는  한개의 스트링만 전달하기로 했지만 실제 전달 파라미터는 text와 자바스크립트 함수 이름입니다.
			testDWR이 call된후 두째 파라미터로 전달된 자바스크립트이름을 통해 호출합니다.
			그리고 callback이 될 함수의 전달 파라미터( 여기에서는 data) 란 이름으로 자바 클래스에서 리턴한 결과값을 확인 할 수 있습니다.

			위와 같이 callback function의 이름을 정의해도 되지만 바로 선언 해도 됩니다.
			예) Tutorial.testDWR( text, function( returnData ) {
					alert( returnData ) ;
				});
			이렇게 작업해 주어도 상관이 없습니다.
		*/										
	}
	function callbackFunction( data ) {
		alert( data );
	}
		
</script>
</head>
<body>
	<input type="text" id="text1"/><br/>
	<button onclick="buttonClick()">DWR 버튼</button>
</body>
</html>


위와 같이 작업해 주시면 됩니다. 이전에도 말씀드렸듯이 util.js파일은 옵션사항이기 때문에 있어도 그만 없어도 그만입니다.( 주로 util성 method들이 추가 되어있습니다.)

이렇게 실행결과가 나오는 것을 확인 할 수 있습니다.



테스트용으로 구현한 testDWR 메소드는 parameter가 한개인 단순한 역할을 하는 데이터 입니다. 하지만 parameter가 여러개일 경우는 어떻게 해야 할까요? 이때 DWR은 JAVA class와 javascript jsonObject 간의 매핑을 지원해 줍니다.

다음엔 JsonObject를 통해 자바 클래스로 파라미터를 던지는 법을 알아 보겠습니다.

DWR - (1) DWR이란?

Published on: 2010. 12. 29. 11:41 by louis.dev
DWR은 DirectWebRemoting의 약자입니다.

DWR을 사용하기 전 비동기적 서버 통신은 Ajax를 통해서 비동기적인 request를 보내고 서버가 해당하는 데이터를 텍스트(json text도 가능)나, xml을 보내주면 javascript의 callback method를 통해 데이터 데이터를 parsing하여 view에 javascript로 뿌려주는 방식으로 사용하였습니다.

이렇게 web에서 가장 많이 사용하는 비동기 통신은 얼마전까지 ajax가 담당해 왔습니다. 하지만, Ajax를 구현해 보신 분은 아시겠지만, 비동기 통신을 하기 위해선 XMLHttpRequest라는 Object의 인스턴스를 생성해서( 이것도 브라우저마다 지원하는 XMLHttpRequest가 달라 브라우저마다 따로 구현을 해야 합니다.) request를 서버로 날리고 response로 받은 xml이나 text( ajax는 두종류의 return밖에 지원하지 않아요..ㅜㅜ)를 적절히 파싱후 html의 해당 영역에 꽂아 넣어야 하는 엄청 대박 불편한 루틴을 타야 합니다. 

그래서 나온것이 DWR입니다. 이 DWR이란 놈은 Ajax의 XMLHttpRequest를 만들필요 없이, 바로 비지니스로직을 처리하는 JAVA의 class로 직접 접근할 수 있습니다. 그렇기 때문에 request를 날리기 위해 XMLHttpReqeust를 만들 필요가 없을 뿐더러, view에서 자바 method를 call할때 전달 파라미터가 String형이 아닌 Object 형도 가능하다는 장점이 있습니다.

그럼 다음 post에는 실제 DWR을 구현해 보도록 하겠습니다~

*비동기적 통신? 
일반적으로 서버로 request를 보내게 되면 페이지가 이동하면서 서버가 응답을 보내올때까지 먹통이 되었다가,(서버가 응답을 리턴해 줄때까지 기다리다가) 서버가 리턴해준 응답을 통해 다음페이지를 보여주게 됩니다. 이러한 방식이 동기화 방식입니다. 
이와 반대로 비동기적 통신이란 페이지는 이동하지 않은 상태에서 request를 만들어 서버로 요청할수 있고, 그 반응이 올때까지 기다리지 않고 다른 작업을 하다 서버로 부터 응답이 오면 화면에 보여주는 방식을 비동기적이라고 합니다.

Ajax의 비동기 통신에 대해서 얘기 할때 보통 택배의 예를 많이 듭니다. 
만약 택배아저씨가 전달할 물건이 request이고 아저씨가 배달해야 할 집을 server라고 가정하겠습니다. 이때 동기적 통신은 처음 배달하려는 집에 찾아가 문을 두드리고 사람이 없으면 올때까지 기다리는 방식입니다. 정말 비효율 적이겠죠.
반대로 문을 두드렸으나 반응이 없음을 확인한 택배 아저씨는 현관문 앞에 쪽지로 친절하게 "집에 도착했을때 전화주세요" 라고 친절하게 자기의 전화번호를 남겨두고( 실제로 이런 분은 없죠..ㅜㅜ) 다른집의 택배를 열심히 배달하다가, 아까 집에 사람이 없던 곳의 주인이 집에 도착하여 "나 집에 왔어요~" 라고 전화를 주면 다시 택배아저씨는 그집으로 가서 택배를 전달을 합니다.

이처럼 페이지에서 사용자가 서버의 요청을 올때까지 멍하니 하얀 페이지를 보고 있는것이 아니라, 계속 다른 작업을 하면서 서버로부터 response가 도착했을때 처리하는 방식을 비동기적 통신이라고 합니다. (이해가 잘 되셨을지는 잘 모르겠네요..;;;)