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를 줌으로서 어떤 보안상에 문제가 발생하는지는 좀더 알아봐야겠네요.

Maven - maven 과 eclipse WTP 연동하기

Published on: 2011. 1. 10. 13:55 by louis.dev

많은 분들이 자바 웹 프로젝트를 진행할때 이클립스 IDE를 사용합니다. 물론 저도 그렇구요. 이클립스는 WTP라는 아주 훌륭한 플랫폼이 있어서 웹개발시에 작업하고 서버에 deploy하지 않고도 이클립스상에서 서버를 껐다 키고, 서버의 임시 deploy 디렉토리에 배포하여 빠르게 개발할수 있습니다.

하지만 Maven을 통해 프로젝트를 생성하면 바로 WTP를 사용할 수가 없습니다. 인터넷에 검색해보면 여러가지 적용방법이 있는데 그중 가장 간단한 방법인 이클립스의 m2eclipse plugin과 m2eclipse Extras plugin을 통해서 간단하게 WTP용 Maven 프로젝트를 생성해 보겠습니다.

전체적으로 3단계로 나눌수 있겠는데요.
첫째. 이클립스 플러그인인 m2eclipse 를 설치한다.
(maven이 설치 되었다는 가정하에 진행하겠습니다.)
둘째. 이클립스 플러그인인 m2eclipse Extras 를 설치한다.
셋째. maven 프로젝트를 생성한다.

이정도 쯤으로 간단하게 WTP와 maven을 연동할수 있습니다.

그럼 지금부터 시작해 보도록 하겠습니다.

1. m2eclipse 플러그인을 설치합니다.
Help >> Install New Software >> Add버튼을 누르고 다음 url을 입력해 줍니다.
http://m2eclipse.sonatype.org/sites/m2e


위와 같이 Maven Integration for Eclipse를 선택하시고 Next >> Next >> I accept the terms of the license argreement 선택하시고 Finish 누르시면 설치가 시작됩니다.

2. m2eclipse Extras 플러그인을 설치합니다. 위와같이 Help >> Install New Software >> Add버튼을 누르고 다음 url을 입력해 줍니다.
http://m2eclipse.sonatype.org/sites/m2e-extras

위와 같이 Maven Integration for Eclipse Extras와 Maven Integration for Eclipse WTP를 선택하시고 설치하시면 됩니다.

위의 4개를 보두 선택하셔도 상관없지만 좀더 빠른 설치를 위해서 필요한것만 설치했습니다.

3. Maven Project를 생성합니다.
File >> New >> Other >> Maven >> Maven Project 를 선택합니다.
Use default Workspace location 을 선택하고 Next를 눌러줍니다.


다음 창에서 artifact Id가 maven-archetype-webapp를 선택합니다.

Group Id : 이 프로젝트를 구별하기 위한 일종의 ID입니다. 보통 package 와 똑같이 지정합니다.
Artifact Id : Project 이름입니다.
Package : 프로젝트에서 사용할 package이름입니다.

위와 같이 프로젝트를 생성하면 Dynamic Web Project가 생성됩니다.

지금부터 약간의 설정을 해야합니다.

새로 만들어진 프로젝트를 선택한후 오른쪽 마우스 클릭 >> Properties >> Project Facets를 선택합니다.
이곳에서 바꾸어야 할것은 3가지 입니다.

1. Dynamic Web Module의 버전
2. Dynamic Web Project의 Webroot 위치
3. Java 버전 변경
입니다.

먼저 첫번째를 수정하려면 다음과 같이 진행해야 합니다.
Dynamic Web Module의 체크를 풀어준다 >> Apply 버튼을 누른다 >> Dynamic Web Module을 Version을 알맞게 변경한다.(저는 참고로 2.5로 변경하겠습니다.) >> Dynamic WebModule의 체크를 다시 한다

두번째 webroot의 위치를 변경하겠습니다.
위사진의 (3번)을 선택한다. >> 다음창에서 Context root는 프로젝트 이름으로(기본적으로 프로젝트 이름이고 바꾸고 싶은것으로 바꾸어도 됩니다. 하지만 전 default로 두겠습니다.) 설정하고 directory는 /src/main/webapp 로 세팅합니다.

이렇게 세팅하면 기존의 Dynamic Web Project의 webroot가 WebContent에서 /src/main/webapp로 변경됩니다.

세번째 Java Version을 변경합니다. 저는 1.6 버전을 사용할 것이기 때문에 1.6으로 선택하고 OK를 누르겠습니다.


이렇게 세팅하고 OK를 눌러 빠져나옵니다. 만약 위와같이 설정한뒤 프로젝트에 에러가 발생하면 아마 거의 대부분은 위에서 설정한 Java버전과 Build Path의 java버전과 맞지 않았을때 에러가 날것입니다. 당연히 Build Path의 자바 버전도 변경해 주면 에러는 없어집니다.

기본적인 설정은 여기 까지입니다. 하지만 메이븐을 많이 사용하신 분들이라면 뭔가 이상함을 느끼실 겁니다.

패키지 이름이 이상합니다..ㅜㅜ

보통 메이븐은 4가지 정도로 분리가 됩니다.
1) src/main/java --> back end를 구성할 java 파일을 작성합니다.
2) src/main/resources --> 프로젝트의 설정파일을 저장합니다.
3) src/test/java --> 테스트를 하기위한 테스트 케이스를 작성합니다.
4) src/test/resources --> 테스트를 하기위한 설정파일을 작성합니다.

이렇게 4가지가 있어야 하는데 지금은 src/main/resources 밖에 없습니다.
그렇다면 직접 만들어 주는 수밖에 없겠네요..

탐색기를 통해 해당 웹프로젝트 디렉토리로 이동합니다.
다음과 같은 디렉토리를 만듭니다.

1) src/main/java
2) src/test 생성후
               /java
              /resources

이런 구조로 만들어 주시면 됩니다.

그리고 이클립스로 돌아오셔서 상단의 Navigator를 선택하시면 다음과 같은 구조를 보실수 있습니다.
(Navigator가 없으시면 Window >> Show View >> Navigator 를 선택하시면 됩니다)

이중에 수정해야 할 파일은 2가지 입니다.
.settings/org.eclipse.wst.common.component

.classpath 파일입니다.

먼저 .settings/org.eclipse.wst.common.component를 열고 다음을 추가합니다.

빨간 3줄을 추가해 줍니다.

다음으로 .classpath입니다.


위의 3줄을 추가해주고 그 아래 한줄을 수정해 줍니다.

이로서 maven + WTP의 통합 과정이 끝났습니다. 이제 불편하게 maven package를 만들어서 테스트 서버에 배포할 필요없이 바로 사용할 수 있습니다.
Maven
국내도서>컴퓨터/인터넷
저자 : Sonatype Company / 장선진역
출판 : 지앤선(지&선) 2010.09.06
상세보기

자바 프로젝트 필수 유틸리티
국내도서>컴퓨터/인터넷
저자 : 박재성
출판 : 한빛미디어 2009.02.28
상세보기





MyBatis - MyBatis를 사용하자 (MyBatis 초기 설정)

Published on: 2011. 1. 8. 02:50 by louis.dev


기존의 아파치프로젝트로 존재하던 iBatis가 2.xx 버전에서 3.xx로 버전을 업그레이드 뒤, 아파치 프로젝트에서 코드 구글로 이동하면서 이름도 MyBatis로 변경되었습니다. 제가 직접 사용해 본 결과 iBatis와 비교해 보았을때 많은 부분이 변경되어 튜토리얼을 작성하게 되었습니다. ( 기존에 ibatis를 많이 사용해 보셨던 분이라면 무난하게 세팅하고 사용하실수 있을테지만 처음 접하는 분들을 위해 초기설정을 해보도록 하겠습니다.)

저는 eclipse와 mysql 5.5를 통해 튜토리얼을 진행해 보겠습니다.

작업방법
1. MyBatis 라이브러리와 Mysql connector library를 다운받습니다.
자바 프로그래밍의 시작은 라이브러리의 추가입니다.(ㅎㅎ) 다음의 라이브러리를 다운 받습니다.
- mybatis-3.0.4 [다운로드]
- mysql-java-connector-5.1.14 [다운로드

2. eclipse에서 JavaProject를 생성합니다.
저는 간단하게 MyBatis만을 세팅하고 DB의 데이터를 긁어와 콘솔창에 뿌려주는 테스트를 할것임으로, Java Project를 생성하겠습니다. 목적에 따라서 Dynamic Web Project를 하셔도 상관이 없습니다.

3. 해당 프로젝트를 생성후 build path에 mybatis 라이브러리와 mysql connector 라이브러리를 추가해 줍니다.
위에서 다운받은 두개의 파일을 압축푸시면 jar파일이 나옵니다. 해당 jar파일을 build path에 추가해 줍니다.

4. 테이블을 생성합니다.
간단하게 테스트 하기 위해서 다음과 같은 쿼리로 테이블을 생성했습니다.

CREATE TABLE `mybatis` (
  `idx` int(10) NOT NULL AUTO_INCREMENT,
  `title` text,
  `contents` text,
  PRIMARY KEY (`idx`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;



5. MyBatis 세팅파일인 Configuration.xml파일을 생성합니다.
net.mybatis.tutorial.conf 패키지를 생성한후 아래와 같이 Configuration.xml 파일을 생성했습니다.

<?xml version="1.0" encoding="UTF-8" ?>
<!-- Valid 한 설정 xml을 만들기 위해 DTD를 추가해 줍니다. -->
<!DOCTYPE configuration
	PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!--
		properties : 해당위치의 properties파일을 참조하여 현재 xml내에서 
		${name} 으로 값을 사용할 수 있습니다.
		즉 properties에 선언된 db.properties에 username=xxxxx 라고 설정되어 있으면
		아래의 <property name="username" value="${username}"/> 부분의 value에 xxxx가
		치환되어 들어갑니다.
	-->
	<properties resource="net/mybatis/tutorial/conf/db.properties"/>
	<!--
		SQL이 선언되어 있는 xml( ibatis에서는 SqlMap이라고 불렀지만, myBatis에서는 
		mapper 라고 불리고 있습니다)에서 사용할 VO객체의 별명을 붙여 줍니다.

		기존의 ibatis에서는 해당설정이 SqlMap쪽에 존재 했던 반면 myBatis에서는 설정쪽으로
		이동한 것이 달라진 점이라 하겠네요~^^ 
	-->
	<typeAliases>
		<typeAlias alias="Mybatis" type="net.mybatis.tutorial.vo.MybatisVO"/>
	</typeAliases>
	<!-- 
		DB Connection을 맺기 위한 정보들을 입력해 줍니다. ${}는 위에 선언한 properties의 
		데이터로 치환됩니다.

		이부분에서 보아야 할부분은 dataSource 부분입니다. 지금은 type="POOLED"라고 설정되어
		있습니다. 이 설정은 Connection pool을 사용하겠다는 뜻입니다.
		이부분의 설정은 좀더 있지만 나중에 알아보도록 하겠습니다.
	-->
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${driver}" />
				<property name="url" value="${url}" />
				<property name="username" value="${username}" />
				<property name="password" value="${password}" />
			</dataSource>
		</environment>
	</environments>
	<!-- 
		위에서도 말했듯 mapper.xml은 실질적으로 query문이 선언되어 있는 부분입니다.
	-->
	<mappers>
		<mapper resource="net/mybatis/tutorial/mapper/MybatisMapper.xml" />
	</mappers>
</configuration>


6. properties 파일을 생성합니다.
위에서도 설정하였듯 해당 위치에 db.properties파일을 생성합니다.
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db이름
username=아이디
password=비밀번호

자신의 환경에 맞게 다음과 같이 설정합니다.

7. 실질적인 query문이 선언되어 있는 mapper.xml을 만들어 보겠습니다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 
	root 엘리먼트 이름은 mapper입니다. 
	ibatis에서는 SqlMap이었습니다.
	namespace는 지정을 해도 되고 안해도 됩니다. ibatis에서는 네임스페이스 사용여부를
	설정에서 명시적으로 선언해줘야 했지만, myBatis에서는 따로 설정할 필요가 없이, namespace attribute
	가 없으면 네임스페이스 안쓰는걸로, 있으면 쓰는걸로 자동으로 되는듯 싶습니다.
-->
<mapper namespace="net.mybatis.tutorial.mapper.MyBatisMapper">
	<!--
		select 태그를 사용하여 select 쿼리를 만듭니다.
		parameterType: iBatis의 parameterClass의 역할로 전달 인자의 타입을 선언합니다
		resultType : iBatis의 resultClass와 같은 역할로 처음 선언했던 Configuration.xml의 
		typeAlias를 나타냅니다.
	-->
	<select id="selectMybatis" parameterType="int" resultType="Mybatis">
		select * from mybatis where idx = #{idx}
	</select>
</mapper>


8. query를 실행하기 위해 myBatis의 핵심 인스턴스인 SqlSessionFactory 인스턴스를 생성하는 Util클래스를 작성합니다.
iBatis의 SqlMapClient클래스가 있다면 MyBatis에는 SqlSessionFactory라는 클래스가 있습니다. query를 실행하기 위해서는 SqlSessionFactory를 통해 SqlSession 객체를 생성하여 query를 실행 할 수 있습니다.

public class SqlSessionManager { public static SqlSessionFactory sqlSession; static { String resource = "net/mybatis/tutorial/conf/Configuration.xml"; Reader reader; try { reader = Resources.getResourceAsReader( resource ); sqlSession = new SqlSessionFactoryBuilder().build( reader ); } catch (IOException e) { e.printStackTrace(); } } public static SqlSessionFactory getSqlSession() { return sqlSession; } }



위와같이 Configuration.xml 을 읽어 SqlSessionFactory 인스턴스를 생성합니다. myBatis는 SqlSessionFactory를 싱글톤 패턴으로 단 하나의 인스턴스만 생성하게 해줍니다

9. DB에 접근할 DAO클래스를 생성합니다.
SqlSessionFactory를 통해 SqlSession을 얻어와서 SqlSession을 통해 query문을 실행합니다.
selectOne는 select query를 실행하여 하나의 Object를 가져오는 method입니다.
쿼리의 선택은 selectOne 첫번째 전달인자로 선택합니다. 첫번째 전달인자는 "mapper xml의 namespace" + "query id" 입니다. 두번째 전달인자는 해당 쿼리로 전달될 값입니다.
public class MybatisDAO {
	private SqlSessionFactory sqlSessionFactory = SqlSessionManager.getSqlSession();
	public MybatisVO getMyBatis( int id ){
		SqlSession session = sqlSessionFactory.openSession();
		try {
			MybatisVO mybatis = ( MybatisVO ) session.selectOne( "net.mybatis.tutorial.mapper.MyBatisMapper.selectMybatis" , id );
			return mybatis;
		} finally {
			session.close();
		}
	}
}


테스트케이스를 작성하신후 junit으로 실행을 하시던, main method를 하나 만들어 테스트를 하시던 데이터를 잘 가져오는것을 확인 할 수 있습니다.

위와 같은 설정이 default입니다.

위의 5, 7번 설정과 같이 Configuration.xml, mapper.xml 과 같이 설정과 query문을 xml로 선언합니다. 하지만 프레임웍을 처음 써보시는 분이나, xml설정방법이 익숙하지 않으신 분들, 그리고 저렇게 복잡한 설정을 거치지 않아도 되는 쿼리를 실행해야 하는 분들은 5, 7번 단계를 only java로 대체할수가 있습니다

1. only java로 설정하실 분들은 5번 단계를 뛰어넘고 8번 단계에서 다음과 같은 class를 작성합니다.

public class SqlSessionManager {
	public static SqlSessionFactory sqlSession;
	static {
		DataSource dataSource = new PooledDataSource("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/디비이름","아이디","비밀번호");
		TransactionFactory transactionFactory = new JdbcTransactionFactory();
		Environment environment = new Environment( "development", transactionFactory, dataSource );
		Configuration configuration = new Configuration( environment );
		//아래의 2번에 설정된 인터페이스를 지정합니다.
		configuration.addMapper( MybatisMapper.class );
		sqlSession = new SqlSessionFactoryBuilder().build( configuration );
	}
	public static SqlSessionFactory getSqlSession() {
		return sqlSession;
	}
}


2. mapper.xml도 xml대신 java interface로 대체합니다.
아래와 같이 어노테이션을 통해 간단한 쿼리 문을 대체 합니다.
public interface MybatisMapper {
	@Select("SELECT * FROM mybatis WHERE idx = #{idx}")
	MybatisVO getMybatis( int id );
}


3. dao를 작성합니다.
public class MybatisDAO {
	private SqlSessionFactory sqlSessionFactory = SqlSessionManager.getSqlSession();
	public MybatisVO getMyBatis( int id ){
		SqlSession session = sqlSessionFactory.openSession();
		try {
			MybatisMapper mapper = session.getMapper( MybatisMapper.class );
			MybatisVO mybatis = mapper.getMybatis( id );
			return mybatis;
		} finally {
			session.close();
		}
	}
}


위와 같이 작성하시면 설정 xml없이 myBatis를 사용할수 있습니다.

이상으로 myBatis의 기본설정을 알아봤습니다.

다음에 기회가 된다면 좀더 알아봐야 겠네요~^^

iBATIS 인 액션
국내도서>컴퓨터/인터넷
저자 : 브랜든구딘,클린턴비긴,래리메도스,손권남 / 이동국역
출판 : 위키북스 2007.05.22
상세보기


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를 통해 자바 클래스로 파라미터를 던지는 법을 알아 보겠습니다.