넷빈(NetBeans)6.8에서 Wicket 사용하기-01-설치 및 샘플프로그램
Written on 오전 4:38 by 강여사(J.Y.Kang)
이번에는 Wicket 프레임워크를 사용하는 방법에 대해 알아 보고자 합니다.
Wicket은 Apache 프로젝트로, 마크업/로직 분리, POJO 데이터 모델,그리고 XML 을 최소로 함으로써,
웹 어플리케이션을 보다 단순화, 계층화 시켜주는 프레임워크입니다.
Wicket은 개념적으로 JavaServer Faces 나 Tapestry 와 비슷하게 자바 프로그래밍 언어를 위해 경량급의 콤포넌트 기반 웹 어플리케이션 프레임워크입니다.
각 컴포넌트들은 하나의 자바 클래스와 하나의 HTML 파일로 구성됩니다. 이러한 컴포넌트 기반 방식의 Wicket은 스트러츠, 스트링과 같은 XML 구성 파일에 의존하는 프레임워크와 달리, XML 구성 파일 대신 홈페이지 식별과 같은 어플리케이션-범위 설정을 위한 자바 클래스를 사용합니다.
웹 어플리케이션의 각 위젯은 하나의 자바 클래스에서 만들어지고 HTML 페이지에서 렌더됩니다. 따라서 자바 클래스와 HTML 페이지는 반드시 같은 이름을 가지고,또 같은 소스 구조에 존재해야 합니다.
현재 Apacke Wicket 은 1.4.9 가 릴리즈 되어 있고,(http://www.apache.org/dyn/closer.cgi/wicket/1.4.9 ) 새 버전은 메이븐 폼(pom)에 다음과 같이 업그레이드 해서 사용될 수도 있습니다.
================================================
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket</artifactId>
<version>1.4.9</version>
</dependency>
================================================
보다 자세한 내용은 아파치 Wicket 홈페이지에서 확인하시고, 이제 넷빈에서 Wicket을 사용하는 방법에 대해 본격적으로 알아 보겠습니다.
현재(이글 쓰는 시점)로 Wicket 플러그인이 넷빈 6.9에서는 정상 설치가 안되고 있습니다.
해서 넷빈 6.7에서 만들어지고 6.8까지 설치 가능한 플러그인으로 진행, 제목에서도 명시했다시피 넷빈 6.8에서 진행합니다.
본 게시물의 작업환경은 다음과 같습니다.
넷빈 6.8 (또는 6.7)
JDK 6 (저는 6up20 입니다. 그러나 JDK5에서도 돌아갑니다)
글래스피시 2.1 이상 (넷빈 6.8에 기본 설치되는 글래스피시로 작업했습니다) 혹은 톰캣 6.x
Wicket 플러그인 (최신버전다운로드 )
우선 바로 위 플러그인 링크에서 최신 버전을 다운로드 받습니다.
플러그인 설치를 위해 도구-플러그인 선택
다운로드 받은 플러그인 설치를 위해서는 다운로드 탭을 누르고 아래 플러그인 추가 버튼을 누릅니다.
그럼 팝업창이 뜨고 위에서 다운로드 받은 파일(3개)을 모두 선택하여 열기를 누릅니다
3개의 Wicket 모듈이 올라옵니다. 왼쪽 아래 설치를 눌러 설치를 진행합니다.
설치 진행은 지시사항에 따라 계속합니다. 다음
동의를 체크하고 설치
서명경고가 뜨지만 무시하고 계속
IDE 재시작 - 마침
IDE가 다시 시작되면 이제 컴포넌트 기반 Wicket 프로그램을 만듭니다. 프로젝트 창에서 마우스 오른쪽 클릭, 새 프로젝트
카테고리에서 Java Web, 프로젝트는 Web Application - 다음
프로젝트 이름은 HelloWicket , 경로는 적당히 - 다음
서버설정인데, 저는 그냥 기본설정으로 진행했습니다.
사실 Wicket 은 J2EE 1.4 , EE5 모두 지원하므로 어느 버전이나 그리고 톰캣이건 글래스피시건 아무거나 하셔도 됩니다. - 다음
프레임워크 설정인데 Wicket 1.4 를 체크합니다.
그럼 Wicket 1.4 구성 내용이 그림과 같이 설정됩니다.
참고로 Wicket Filter name 은 web.xml 에 정의된 필터 이름이고,
Wicket URL Pattern 은 web.xml 에 URL 패턴으로 정의된 서블릿 매핑이고,
Wicket Application Class 는 홈페이지처럼, 어플리케이션-범위 설정이 있는 클래스 이름을 지정합니다.
Wicket Home Page 는 홈페이지 이름을 지정하는데, 해당 이름의 파일은 XXX.java 와 XXX.html 2개로 구성되게 됩니다.
Main Package 는 위 사항들이 들어갈 자바 패키지 설정입니다 - 마침
IDE가 자동으로 만들어주는 파일들을 모두 자세히 살펴 보도록 합니다. 우선 HomePage.html 이 편집기 창에 제시됩니다.
이 Wicket 이 읽혀지기 위해서는 Wicket 의 유일한 xml 관련 파일인 web.xml 에 해당 설정이 있습니다. 프로젝트의 web.xml 을 열어 다음 내용을 확인합니다
-------------------------------------------------------
<filter>
<filter-name>WicketApplication</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>com.myapp.wicket.Application</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>WicketApplication</filter-name>
<url-pattern>/wicket/*</url-pattern>
</filter-mapping>
-------------------------------------------------------
위의 XML 에 보면 Wicket 필터가 com.myapp.wicket.Applciation 클래스를 파라미터 값으로 초기화하도록 되어 있습니다. 필터 매핑은 /wicket/* 이구요.
즉 이 자바 파일, Application.java 에 스트러츠의 struts-config.xml 나 JSF의 faces-config.xml 처럼 어플리케이션-wide 설정이 제공되게 됩니다.
파일을 보면 getHomePage() 메소드가 정의되어 있는데, 이 메소드가 어플리케이션-범위의 최고단위(필수)입니다. 간단히 말하자면 어플리케이션이 배포될 때 홈페이지(즉, 최초 페이지)를 지정하는 거죠.
그럼 다음으로 여기 return 되는 HomePage.java를 열어 봅시다.
HomePage.java 는 현재 비어 있습니다(기본).
나중에 이 파일의 생성자에 컴포넌트들을 추가하게 됩니다.
HomePage.java 와 같은 소스 구조에 같은 이름,즉 HomePage.html 파일에서 Wicket 위젯의 렌더링을 합니다.
HomePage.java는 BasePage를 상속받는데, HomePage.html 에서 wicket:id 속성은, 자바 파일에 의해 뭔가 만들어졌다는 걸 알려주는 표시자 입니다.
IDE에 의해 자동 생성된 CSS는 BasePage.java 에 참조(StyleSheetReference)되어 있습니다.
여기에 보면 아까 wicket:id 로 설정된 "mainNavigation" 이 헤더 패널로, 모든 웹 페이지에 동일한 헤더가 추가됨을 알 수 있습니다. 그럼 다음으로 HeaderPagel.java 에 대해 살펴봅시다.
HeaderPanel.java 를 열면 다음과 같이 되어 있습니다. 여기에 보면 Wicket Label 위젯이 추가되어 있습니다.
이렇게 자바에서 만들어진 위젯은, HTML 사이드에서 렌더됩니다. HeaderPanel.java 짝인 HeaderPanel.html 에 해당 내용이 나타나게 되는 거죠.
그럼 제시된 기본 내용을 조금 바꿔 보겠습니다. 기본으로 작성된 exampleTitle 대신 아래 내용으로 고칩니다.
=================================================
add(new Label("exampleTitle", "My Very First Component Based Application"));
=================================================
HeaderPanel.html 을 엽니다. 안의 내용을 보면 웹페이지의 HTML 로 렌더될 위젯이 지정되어 있음을 알 수 있습니다.
팁(Tip): 여기 <span wicket:id="exampleTitle"... 의 exampleTitle에 Ctrl 키를 누른채 마우스를 대면 하이퍼 링크 아이콘을 바뀝니다.(파란색으로), 이걸 클릭하면 해당 자바(HeaderPanel.java)로 페이지가 이동되고, 반대로 소스코드에서 HTML 페이지로 이동하려면 Alt+왼쪽화살표를 누르면 빠르게 이동할 수 있습니다 ^^;
파일을 저장하고, 프로젝트를 실행합니다. 프로젝트에서 마우스 오른쪽 클릭-실행
브라우저에 다음과 같은 내용이 표시됩니다.
********************************************************
이제 이번에는 여기에 새 위젯을 추가해보도록 하겠습니다.
하나의 위젯은 하나의 자바파일과 같은 이름, 같은 경로에 HTML 파일로 구성됩니다.
자바에서 위젯을 만들고, HTML 에서 위젯을 렌더합니다.
위의 팁에서 살펴봤듯이 이 둘 사이는 하이퍼링크 및 단축키 등으로 둘 사이를 빠르게 이동할 수 있구요 ^^;
HomePage.html 을 열어 다음 내용(굵은 글씨)를 추가합니다.
================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<link wicket:id='stylesheet'/>
</head>
<body>
<span wicket:id='mainNavigation'/>
<span wicket:id="message1">this text will be replaced</span>
</body>
</html>
================================================================
왼쪽 아래 네비게이터에서 Wicket Tag 목록을 누르면 아래 그림 처럼 태그 개요를 볼 수 있습니다. (3개)
이제 HomePage.java 를 열어, HTML 에 추가한 이름의(message1)의 라벨을 추가합니다. (굵은 글씨 참조)
==========================================================
public HomePage() {
setModel(new CompoundPropertyModel(this));
add(new Label("message1","Hello world!"));
}
==========================================================
그럼 새로 추가한 Label 의 임포트 문제때문에 오류가 뜨는데 해결 방법은 왼쪽 아이콘 모양을 누르면 제시안이 나옵니다. 여기서 org.apache.wicket.markup.html.basic.Label 을 임포트(가져오기 추가)를 클릭합니다.
그런 다음 프로젝트를 실행합니다. 프로젝트에서 마우스 오른쪽 클릭 - 실행(run)
브라우저에 Wicket Label인 Hello world! 가 나타납니다.
이 Hello world! 에 H2 태그를 적용하려면 HomePage.html 에 span 을 h2 태그로 감싸 프로젝트를 다시 배포하면 됩니다.
==================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<link wicket:id='stylesheet'/>
</head>
<body>
<span wicket:id='mainNavigation'/>
<H2>
<span wicket:id="message1">this text will be replaced</span>
</H2>
</body>
</html>
=================================================
프로젝트를 다시 실행시키면 아래 그림처럼 h2 태그가 적용되었음을 확인할 수 있습니다.
이와 같은 작업방식은 SPAN 태그와 같은 placeholder를 만들어, 이 HTML 파일을 웹 디자이너에게 넘기고, 여러분은 자바 사이드에서 해당 위젯을 독립적으로 만들면 된다는 뜻입니다. 이로써 Wicket의 철저한 "관심사 분리:separation of concerns" 라는 핵심 포커스가 이루어지는 거죠.
이번에는 Wicket 의 또다른 강점이라고 할 수 있는 "재사용 가능한 컴포넌트" 컨셉에 대해 살펴 보겠습니다.
이 작업에서는 Wicket 패널을 하나 만들어(하나라고는 하지만 해당 자바와 HTML 한 쌍이 만들어집니다) 헤더패널과 짝이 될 수 있는 풋터(FootPanel)을 만들어 헤더처럼 웹 사이트에 재사용될 수 있도록 페이지에 추가해보도록 하겠습니다.
우선 작업을 위해 새 파일을 만듭니다. 이때 패키지에서 마우스 오른쪽을 클릭해서 새파일을 만들게 되면 해당 경로가 자동 작업이 되기 때문에 경로 선택에 대한 수고를 덜 수 있죠.
패키지(com.myapp.wicket)에서 마우스 오른쪽 클릭 - 새파일
카테고리는 web, 파일 유형은 Wicket Panel 선택 - 다음
파일 이름을 FooterPanel 이라고 줍니다.
그럼 아래 그림에서 처럼 2개의 파일(FooterPanel.java 와 FooterPanel.html) 파일이 생성됩니다. - 마침
우선 FooterPanel.html 파일을 열어 기본 내용을 살펴 봅니다. 기본에는 span 태그가 주석을 감싸여 있는데, 이 주석을 제거 합니다.
그리고 FotterPanel.java로 이동하는데, 프로젝트 창에서 해당 파일을 직접 열거나, 아니면 아까 위에 팁에서 처럼 Wicket id 값(title)에서 Ctrl 버튼을 누른채 마우스를 대면 하이퍼링크가 나타나는데 그때 클릭하면 바로 자바 파일로 이동합니다.
FooterPanel.java 파일 기본 내용은 다음과 같습니다.
여기에 (super(id);) 아래 다음 내용(굵을 글씨)을 작성합니다.
=====================================================
package com.myapp.wicket;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
final class FooterPanel extends Panel {
FooterPanel(String id) {
super (id);
add(new Label("title","I am a reusable component!"));
}
}
=====================================================
아까와 마찬가지로 Label의 임포트 문제는 앞의 아이콘을 눌러 org.apache.wicket.markup.html.basic.Label 를 가져오기 추가를 선택합니다.
임포트 확인
이제 이 패널을 홈페이지에 추가하면 됩니다. 방법은 HomePage.java 를 열어 FooterPanel의 새 인스턴스를 추가해줍니다. 굵은 글씨 내용을 추가합니다.
============================================
...
public class HomePage extends BasePage {
public HomePage() {
add(new Label("message1", "Hello world!"));
add(new FooterPanel("footerPanel"));
}
}
============================================
자바에서 추가된 패널을 이번엔 HTML 에서 렌더해야 합니다. HomePage.html 을 열어 footerPanel에 대한 placeholder 를 추가합니다. (굵은 글씨 참고)
=================================================================
...
<body>
<span wicket:id='mainNavigation'/>
<h2>
<span wicket:id="message1">this text will be replaced</span>
</h2>
<span wicket:id='footerPanel'/>
</body>
...
=================================================================
파일을 저장하고 프로젝트를 실행합니다. 프로젝트에서 마우스 오른쪽 클릭 - 실행(run)
아래 그림 처럼 footerPanel의 내용이 잘 나타나는 걸 보실 수 있습니다.
주: Wicket 용어에서, 패널은 재사용가능한 컴포넌트입니다. 이러한 패널을 활용한다면 원하는 만큼의 웹 페이지를 원하는 곳에 재사용 가능하게 만들 수 있습니다.
************************************************************
이제 이 게시물의 마지막으로 AJAX 기능에 대해 만들어 보겠습니다.
Wicket 에서는 AJAX 기능을 추가하기 위해 자바스크립트를 사용하는 대신, AJAX 를 캡슐화한 자바 컴포넌트 모델을 만들어 사용합니다. 이번 게시물에서는 위의 FooterPanel에 AJAX 의 autocomplete 위젯을 추가하도록 하겠습니다.
autocomplete 위젯은 플러그인 설치 jar 에 포함되어 있지 않은 extension jar 이므로 따로 다운로드 받아 사용시 프로젝트 라이브러리에 추가해줘야 합니다.
우선 이 extension jar 파일을 grepcode.com에서 다운로드 합니다. 아래 그림의 사이트에서 binary download 를 선택하면 됩니다.
그런 다음 프로젝트의 library 에서 마우스 오른쪽을 클릭하여 JAR/폴더 추가를 클릭합니다.
팝업창이 뜨면 아까 받은 jar (wicket-extensions-1.4.0.jar 파일을 선택하고, 열기를 클릭합니다)
이제 FooterPanel.java 파일을 열어 생성자 아래 다음 내용(굵은 글씨)을 작성합니다.
=======================================================
...
public final class FooterPanel extends Panel {
FooterPanel(String id) {
super(id);
add(new Label("title", "I am a reusable component!"));
}
final AutoCompleteTextField field = new AutoCompleteTextField("countries", new Model("")) {
@Override
protected Iterator getChoices(String input) {
if (Strings.isEmpty(input)) {
return Collections.EMPTY_LIST.iterator();
}
List choices = new ArrayList(10);
Locale[] locales = Locale.getAvailableLocales();
for (int i = 0; i < locales.length; i++) {
final Locale locale = locales[i];
final String country = locale.getDisplayCountry();
if (country.toUpperCase().startsWith(input.toUpperCase())) {
choices.add(country);
if (choices.size() == 10) {
break;
}
}
}
return choices.iterator();
}
};
}
========================================================
그런 다음 생성자 부분에서 라벨 대신 field 변수를 추가합니다
=======================================================
...
public FooterPanel(String id) {
super(id);
//add(new Label("title", "I am a reusable component!"));
add(field);
}
...
=======================================================
임포트 문제를 해결하기 위해 편집기 여백에서 마우스 오른쪽 클릭 - 가져오기 수정(fix import)
아래 그림을 참고하여 임포트 할 클래스를 선택합니다.
임포트 확인
----------------------------------------------------
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.string.Strings;
----------------------------------------------------
이제 FooterPanel HTML 에서 자바 클래스에서 만든 위켓을 연결합니다.
Wicket id는 "countries" 를 사용하여 입력 텍스트 필드를 추가합니다.
==============================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns:wicket>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>FooterPanel</title>
</head>
<body>
<wicket:panel>
<!--<span wicket:id="title">title here</span>-->
<input type="text" wicket:id="countries" size="50"/>
</wicket:panel>
</body>
</html
==============================================
자바 파일을 수정했기 때문에 원칙적으로 다시 빌드를 해야 합니다. (다만 여기서 예전 파일이 deploy 되어 있는 상태에서 clean and build 가 정상 동작하지 않을 수도 있기 때문에 그런 경우 해당 서버를 중지시키고, file 탭으로 가서 build와 dist 폴더를 삭제하거나, 아니면 아예 넷빈을 다시 껐다가 켜서 해당 프로젝트를 clean and build 하는 게 좋습니다)
프로젝트를 실행합니다. 프로젝트에서 마우스 오른쪽 클릭 - 실행(run)
브라우저에 텍스트 필드가 나타나면 "대"라고 입력합니다.
그럼 그림과 같이 아래 대만,대한민국이 제시됩니다.
*************************************************************
추가분: (문제상황점검)
현재 나라에 대한 설정을 잘 살펴보면 우선 10개씩만 나타나도록 되어 있습니다. 이 문제도 수정을 해야 하고.. 또 하나, 로케일에 관한 사항인데 현재 소스로는 한글로 입력시에 해당 로케일에 대해 나옵니다만 영어로 하는 경우에는 영문 로케일을 반영하지 않기 때문에 아무 제시어도 나타나지 않습니다.
그럼 영어로 나라이름을 적었을 때 나타나게 하려면 어떻게 소스를 수정해야 할까요? 또하나 10개의 제한을 없애려면?
-------------------------------------------------------------
해답: 아까의 FooterPanel.java 의 코드 부분을 다음과 같이 수정합니다.
===================================================
public final class FooterPanel extends Panel {
...
final AutoCompleteTextField field = new AutoCompleteTextField("countries", new Model("")) {
@Override
protected Iterator getChoices(String input) {
if (Strings.isEmpty(input)) {
return Collections.EMPTY_LIST.iterator();
}
List choices = new ArrayList(10);
Locale[] locales = Locale.getAvailableLocales();
for (int i = 0; i < locales.length; i++) {
final Locale locale = locales[i];
locale.setDefault(Locale.ENGLISH);
final String country = locale.getDisplayCountry();
if (country.toUpperCase().startsWith(input.toUpperCase())) {
choices.add(country);
/*
if (choices.size() == 10) {
break;
}
*
*/
}
}
return choices.iterator();
}
};
...
=================================================================
파일을 저장하고 프로젝트를 다시 clean and build 한 후 실행시키면 아래 그림처럼 영어로 입력시 나라이름이 제시됩니다. a 로 시작되는 나라들
s 로 시작되는 나라들..(south korea ㅋㅋㅋ)
이상 간단히 알아본 Wicket 이었습니다.
나중에 좀더 다양한 형태의 Wicket 위젯들에 대해 알아보도록 하겠습니다.
수고하셨습니다. *^^*