메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

ZK에서 CDI 프로그래밍 모델 탐색하기

간단한 애플리케이션 구현하기

Mr. Sachin K Mahajan, Software Developer, WSO2 Inc
Sachin tem um diploma de Mestrado da University of Utah, em Salt Lake City, EUA. Ele trabalhou em empresas grandes e pequenas nos Estados Unidos e Índia, executando várias funções técnicas e gerenciais. Sachin trabalha atualmente na divisão Lotus do IBM Software Group.
(An IBM developerWorks Contributing Author)
Ashish Dasnurkar, Software Developer, WSO2 Inc
Photo of Ashish Dasnurkar
Ashish has a bachelor's degree from the University of Pune, India, and has worked with the Java EE platform for six years on several enterprise applications for multi-national companies. He currently works at the Potix Corporation, which is the driving force behind the ZK Ajax Framework.

요약:  JSR(Java™ Specification Request) 299: Java EE 플랫폼용 CDI(Contexts and Dependency Injection)는 강력한 서비스 설정입니다. 이 서비스는 Java EE 구성 요소의 형안전(type-safe) 의존성 삽입이 포함되고, 구성 요소 사이에 상호작용을 허용하기 위한 이벤트 알림 모델도 포함되어 Java EE 웹 티어에서 Java EE 서비스로의 액세스를 간소화해 줍니다. 근본적으로 Java EE 웹 티어에서 사용된 모든 써드파티 프레임워크는 CDI 휴대용 확장 메커니즘을 사용하여 CDI 서비스를 활용할 수 있습니다. 이 글에서는 "Rich Internet applications using ZK"이라는 글의 샘플 애플리케이션을 확장하여 ZK 프레임워크 및 강력한 CDI 서비스와의 통합을 사용하여 현존하는 예제를 수정하는 방법을 설명합니다.

원문 게재일:  2010 년 5 월 25 일 번역 게재일:   2010 년 8 월 05 일
난이도:  중급 영어로:  보기 PDF:  A4 and Letter (190KB | 20 pages)Get Adobe® Reader®
페이지뷰:  2362 회
의견:  


소개

Java 코드로 쓴 오픈 소스 Ajax(Asynchronous JavaScript and XML) 프레임워크인 ZK를 통해 JavaScript 코드를 하나도 쓰지 않고도 Web 2.0이 가능한 리치 인터넷 애플리케이션을 쓸 수 있다.

ZK는 JavaScript가 없는 Ajax와 비슷하다. ZK는 Ajax 기반 이벤트 구동형 엔진과 XHTML 및 XUL 구성 요소의 풍부한 설정에 기능이 풍부한 사용자 인터페이스를 작성하기 위한 ZUML 마크업 언어로 구성된 강력한 프레임워크이다.

이 글에서 ZK 프레임워크와 관련된 Java EE 플랫폼용 CDI(Contexts and Dependency Injection) 프로그래밍 모델을 배워보자. 이 글에서는 ZK의 성능을 탐색하는 글인 "Rich Internet applications using ZK: An open source Ajax framework"의 예제 애플리케이션을 빌드한다. ZK와 CDI를 사용하여 고객 관리를 위한 현존하는 자세한 예제 애플리케이션을 확장하게 된다.

이 글의 애플리케이션의 소스 코드를 다운로드할 수 있다.

JSR-299 및 CDI

JSR(Java Specification Request) 299 또는 Java CDI는 의존성 삽입 및 콘텍스트의 라이프사이클 관리를 위한 Java 표준이다. 이 표준을 통해 서비스 세트가 애플리케이션 개발을 더 쉽고 분명하게 정의한다. 서비스는 다음을 제공한다.

  • 이벤트 알림 메커니즘을 통해 오브젝트의 상호작용
  • 형안전(type-safe) 의존성 삽입
  • 콘텍스트로 바인드된 상태기반(stateful) 오브젝트를 위한 라이프사이클 메소드
  • 인터셉터를 오브젝트로 바인드하는 "데코레이터" 인터셉터
  • 휴대용 확장을 개발하는 서비스 공급자 인터페이스(SPI)

CDI는 느슨한 결합(loose coupling)과 강력한 타이핑(strong typing)을 강조하기 때문에, bean은 구현, 스레드 모델 또는 라이프사이클과 같은 특정한 측면을 인식할 필요가 없다. 이러한 측면은 배치에 따라 달라질 수 있으며 클라이언트에 전혀 영향을 미치지 않는다. 느슨한 결합으로 인해 코드를 유지보수하기가 쉽고 확장할 수 있다.

ZK 및 CDI

ZK 프레임워크로 제공되는 ZK CDI는 ZK 프레임워크 내에서 CDI 서비스를 노출하여 CDI와의 원활한 통합을 제공한다. 이를 통해 엔터프라이즈 개발자는 CDI 구동형 애플리케이션을 ZK에서 공급하는 압축적이고 강력한 Ajax 프런트 엔드와 통합할 수 있다. CDI와 ZK를 함께 사용하면 Java의 EE 웹 티어와 Java EE 사이의 간격을 손쉽게 연결할 수 있다.

ZK CDI 확장을 통해 ZK 프로그래밍 모델 내에서 CDI 기능을 원활하게 사용할 수 있다. 내장 CDI 기능 이외에도 ZK CDI 확장은 다음과 같은 기능을 제공하여 개발을 쉽게 만들어 준다.

사용자 정의 변수 분석기/EL 분석기(variable resolver/EL resolver)
<zscript />, EL 표현식(${...}) 및 해당 EL 이름으로 ZK 어노테이트된 데이터 바인딩 표현식(@{…}) 내에서 CDI 관리되는 bean을 분석(resolve)한다.
ZK 사용자 정의 범위
이러한 확장은 내장 CDI 범위인 세션(Session), 리퀘스트(Request), 애플리케이션(Application), 컨버세이션(Conversation) 이외에도 다섯 가지의 ZK 범위를 더하여 데스크탑(Desktop), 페이지(Page), 이그제큐션(Execution), IdSpace, 구성 요소(Component)를 제공한다.
관리되는 bean으로서 ZK 구성 요소
ZK 작성기와 같이 ZK 구성 요소를 관리되는 bean으로 삽입할 수 있다.
ZK 사용자 정의 어노테이션 및 CDI 제공 이벤트 알림 모델을 사용한 UI 이벤트 핸들러
ZK 사용자 정의 어노테이션을 통해 메소드를 어노테이트할 수 있고 이벤트 핸들러 메소드로 변환할 수 있다.

ZK CDI 확장은 CDI를 정의하는 JSR-299 스펙의 참조 구현인 Weld(자세한 내용은 참고자료 참조)를 기반으로 한다.


CDI로 ZK 사용하기

다음의 간단한 예제에서는 ZUL 파일에서 CDI 관리되는 bean으로 액세스하는 방법을 보여 준다. (.zul 파일 확장자는 ZK 사용자 인터페이스 파일용이다.) CDI 컨텍스트에서 관리되는 bean 또는 간단한 bean은 컨텍스트와 연관되거나 EL 표현식을 통해 접근된 다른 구성 요소로 삽입할 수 있는 Java EE 구성 요소이다.

Listing 1의 간단한 HelloWorld 예제는 ZUL 파일 내에서 관리되는 bean이 EL 표현식을 통해 액세스되는 방법을 보여 준다. 먼저 text라는 이름의 단일 String 필드와 getter 메소드인 getText()으로 HelloWorld 클래스를 정의한다. CDI 스펙에 따르면 no-arg 기본 생성자가 있으면 이 클래스는 관리되는 bean이 될 수 있는 자격을 갖추게 된다. 통합된 EL 표현식을 통해 HelloWorld 관리되는 bean을 참조하려면 @javax.inject.Named 규정자로 어노테이트되어야 한다. EL 이름이 @Named 규정자의 값 멤버를 제공하여 관리되는 bean에 부여될 수 있다. 지정되지 않은 경우에 EL 이름은 첫 번째 문자를 소문자로 변환한 후에 해당 bean 클래스의 비적격 클래스 이름이 기본값이 된다. 예를 들어, HelloWorld는 helloWorld EL이 기본값이 된다.


Listing 1. 관리되는 bean 액세스하기
                
@Named
@SessionScoped
public class HelloWorld implements Serializable {

	private String text = "HelloWorld";
	
	public String getText() {
		return text;
	}
}

Listing 2의 ZUL 코드는 기본값이 된 EL 이름인 helloWorld를 사용하여 HelloWorld bean에 액세스한다.


Listing 2. 기본값 EL 이름
                
<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver"?>
<window title="ZK + CDI: Hello World" width="300px" border="normal">
    My CDI-injected bean says: ${helloWorld.text}
</window>

ZK는 variable-resolver 지시문 <?variable-resolver ?> 를 제공한다. 이를 사용하여 ZK EL 이밸류에이터(${...}), ZK 어노테이트된 데이터 바인더(@{...}) 및 알 수 없는 변수를 분석하는 <zscript> 인터프리터로 사용되는 리졸버 클래스를 지정할 수 있다.

ZK CDI 확장의 기능 중 하나인 사용자 정의 EL 리졸버 DelegatingVariableResolver는 통합된 EL 표현식 내에서 해당 EL 이름으로 HelloWorld 관리되는 bean을 분석하기 위해 사용할 수 있다.

Listing 2의 index.zul 파일에서 간단한 창 구성 요소를 정의하고 ${helloWorld.text} EL 표현식을 사용하여 HelloWorld 클래스의 텍스트 필드를 표시했다. ZUL 렌더링 단계 도중에 ZUL 구문 분석기가 이 EL 표현식을 접하면 helloWorld bean 인스턴스를 해석하기 위해 <?variable-resolver ?>에서 지정한 DelegatingVariableResolver를 사용하게 된다. 왜냐하면 HelloWorld가 이제 컨테이너 관리되는 bean이기 때문에 컨테이너가 HelloWorld bean 인스턴스를 제공하기로 되어 있다. 컨테이너가 리턴한 bean 인스턴스를 사용하여 ${helloWorld.text}가 평가된다. getText() 메소드의 평가 결과는 그림 1에서 보여 주는 것처럼 "Hello World" 스트링을 리턴한다.


그림 1. HelloWorld
My CDI-injected bean says HelloWorld라는 메시지를 보여 주는 스크린샷

CDI로 ZK를 사용하여 현존하는 애플리케이션 구현하기

이 섹션에서는 현존하는 애플리케이션을 구현하여 더 많은 CDI 기능을 탐색한다. "Rich Internet applications using ZK" 글에서 시연한 Manage Customer 애플리케이션을 빌드할 것이다. Manage Customer 애플리케이션을 통해 사용자는 새 고객 추가하기, 고객 데이터 편집하기 및 데이터베이스에서 고객 항목 임시 삭제하기 등 다양한 작업을 수행할 수 있다. 그림 2에서는 Manage Customer 애플리케이션의 기본 사용자 인터페이스 화면을 보여 준다.


그림 2. Manage Customers 대시보드
고객 이름, ID, 날짜 및 삭제 여부를 보여 주는 화면

애플리케이션 내에 등록된 고객이 나열된다. 목록은 ID, 고객의 이름, 활성 날짜 및 삭제된 플래그에 대한 열이 있는 격자이다. 격자의 데이터는 열 이름 근처의 단추를 클릭하여 정렬할(오름차순 또는 내림차순 방식) 수 있다. ID(int), Name(String) 및 active date(Date) 열에 대한 정렬이 사용되었다. 또한 화면 아래에서 보여 주는 것과 같이 이 애플리케이션에서 페이지 나누기도 사용되었다. 페이지는 5개의 기록을 동시에 보여 주도록 사용되었다. 사용자는 다음 페이지로 이동하거나 특정 페이지로 직접 이동할 수 있다.

그림 3에서는 Manage Customer 애플리케이션의 맨 위 표시줄을 보여 준다.


그림 3. 맨 위 메뉴 표시줄
새 고객을 등록할 수 있는 위치를 보여 주는 드롭 다운 메뉴

메뉴 표시줄은 ZK의 메뉴 표시줄 위젯을 사용하여 구현되었다. 여기에는 새 고객을 등록하고 애플리케이션을 종료하는 옵션이 포함된다.


개발 환경 설정하기

구현의 세부 사항을 알아 보기 전에, 고객을 관리하는 샘플 애플리케이션의 작성에 대한 일부 세부 사항을 검토해 보자. 애플리케이션을 작성하기 위해 Eclipse IDE를 사용했지만 어떤 IDE를 선택해도 작동해야 한다.

기본적인 개념은 동적 웹 애플리케이션 프로젝트를 작성하는 것이며, 그 프로젝트를 애플리케이션 서버 런타임에 향하도록 하는 것인데, 이 경우에는 Apache Tomcat 런타임이 해당된다. 새 프로젝트와 런타임을 설정한 후에 그림 4에서 보여 주는 것과 같이 폴더 구조를 복제한다.


그림 4. 디렉토리 구조
ZKmanagecustomers 디렉토리 구조

Manage Customer 애플리케이션의 디렉토리 구조는 그림 4에 보여 주는 것과 동일한 패턴을 따른다.

이 애플리케이션의 핵심 파일은 다음과 같은 서브디렉토리가 있는 WebContent 폴더에 있다.

  • META-INF에는 MySQL 데이터베이스에 연결하기 위해 데이터베이스 신임 정보가 있다.
  • WEB-INF에는 애플리케이션을 실행하기 위해 필요한 ZK JAR 파일이 들어 있는 라이브러리 폴더가 포함된다. 또한 다음 세 가지 구성 파일도 포함된다.
    • beans.xml은 이 애플리케이션 내에서 삽입에 사용 가능한 bean 클래스를 표시한다.
    • web.xml은 데이터소스, ZK 서블릿 및 Weld 구성을 설명한다.
    • zk.xml은 ZK 특별 구성이 들어 있을 수 있다.

다른 모든 ZUL과 HTML 관련 파일은 WebContent 폴더 내에 들어 있다. 이러한 파일은 웹 애플리케이션에 동적 및 정적 내용을 제공하여 애플리케이션의 보기 파트로서 역할을 한다.

샘플 파일 zkManageCustomer.zip(다운로드 참조)에는 애플리케이션의 압축된 버전이 있다. 또한 Eclipse에 필요한 메타데이터 파일이 포함되어 무리없이 해당 IDE로 직접 가져올 수 있다.

Eclipse에서 J2EE(Java 2 Platform, Enterprise Edition) 퍼스펙티브는 오른쪽 마우스를 클릭하면 새 서버를 작성하는 옵션을 표시하는 서버 탭이 있다. 이 서버를 사용하여 Eclipse IDE로부터 애플리케이션 서버를 관리할 수 있다.

새 서버를 구성한 후에 새로 작성된 자원이 서버에 구성되어야 한다. 이 서버 구성은 개발 코스 도중에 작성된 자원을 배치한다.

MySQL 구성하기

예제 프로그램은 Tomcat과 MySQL로 작업하도록 구성된다. 그러나 다른 CDI 사용 가능한 애플리케이션 서버에서도 이를 실행하는 데 아무 문제가 없어야 한다. 예제가 JDBC를 사용하기 때문에, 연결 코드를 약간만 변경하여 DB2 Express-C와 같이 지원되는 모든 SQL 데이터베이스로 작업이 되어야 한다.

Tomcat을 MySQL 데이터베이스에 연결하려면 자원 참조를 정의해야 한다. 이 요소는 Listing 3에 보여 주는 것과 같이 자원 관리자 연결 출하 시 기본 참조의 이름을 지정한다. 이 경우에는 javax.sql.DataSource의 유형인 jdbc/mysql로 지정된 데이터베이스 연결이 될 것이다.


Listing 3. 자원 참조 정의
                
<resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/mysql</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
</resource-ref>
            

또한 WebContent/META-INF 폴더 아래의 context.xml 파일에서 연결 자원을 정의해야 한다. 이 파일에는 드라이버 이름, jndi 이름, 사용자 이름, 비밀번호, 데이터 유형 및 URL과 같은 특성이 들어 있다.


Listing 4. 연결 자원 정의하기
                
<Resource driverClassName="com.mysql.jdbc.Driver" 
	maxActive="4" maxIdle="2" maxWait="5000" auth="Container" 
	name="jdbc/mysql" password="as1008" type="javax.sql.DataSource" 
	url="jdbc:mysql://localhost:3306/customer" username="root"/>
            

고객 데이터베이스에 Listing 5에서 스크립트를 실행하여 작성할 수 있는 단일 표가 있다.


Listing 5. 표 작성하기
                
use customer;
CREATE TABLE 'customer' (
	  'ID' int(11) NOT NULL AUTO_INCREMENT,
	  'name' varchar(255) DEFAULT NULL,
	  'date' date DEFAULT NULL,
	  'deleted' tinyint(1) DEFAULT '0',
	  PRIMARY KEY ('ID')
	); 

ZK CDI 확장 지원 사용하기

ZK CDI 확장을 활용하려면 zkcdi.jar 파일(ZK CDI 확장의 바이너리 분배 내)을 웹 애플리케이션 프로젝트의 WEB-INF/lib 폴더로 복사하자. zkcdi.jar는 웹 애플리케이션 라이브러리로 사용되어야 한다.

Tomcat을 위한 Weld 지원 사용하기

Tomcat을 위한 Weld 지원을 사용하려면 다음과 같이 하자.

  1. Weld 서블릿 리스너(Weld를 부트하고 요청과의 상호작용을 제어하기 위해 사용됨)를 웹 루트의 WEB-INF/web.xml 파일에서 다음과 같이 지정한다.

    <listener>
       <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
    </listener>
    <listener>
       <listener-class>org.jboss.weld.el.WeldELContextListener</listener-class>
    </listener>
                

  2. Tomcat은 읽기 전용 JNDI가 있기 때문에 Weld가 BeanManager 확장 SPI를 자동으로 바인드할 수 없다. BeanManager를 JNDI로 바인드하려면 배치에 사용할 수 있게 웹 루트의 META-INF/context.xml을 다음과 같은 내용으로 채워야 한다.

    <Resource name="BeanManager" auth="Container"
    		type="javax.enterprise.inject.spi.BeanManager" 
    		factory="org.jboss.weld.resources.ManagerObjectFactory" />
                            

          <resource-env-ref>
          <description>Object factory for the CDI Bean Manager</description>
          <resource-env-ref-name>BeanManager</resource-env-ref-name>
          <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager
         </resource-env-ref-type>
    </resource-env-ref>
    

  3. CDI로 의존성 삽입이 사용 가능하도록 WEB-INF 폴더 아래 빈 beans.xml 파일을 추가한다.

다른 애플리케이션 서버와 환경으로 Weld를 설정하는 유사한 지시사항을 보려면 참고자료를 확인하자.


애플리케이션 확장하기

Manage Customers 애플리케이션은 다음 기능을 제공한다.

  • 모든 고객 보기를 포함한 사용자 조작을 위한 대시보드
  • 새 고객 추가하기
  • 기존 고객 편집하기
  • 고객 삭제하기(임시 삭제)

그림 2에서는 등록된 모든 고객의 목록이 나와 있는 대시보드를 보여 준다. 사용자는 ID나 이름을 기준으로 데이터를 정렬할 수 있다. index.zul 파일은 borderlayout, menubar, menumenupopup과 같이 애플리케이션의 룩앤필을 정의하는 다양한 속성이 있다.


Listing 6. 룩 정의
                
<?page id="manageCust" title="Manage Customers" cacheable="false" 
	language="xul/html" zscriptLanguage="Java" contentType="text/html;charset=UTF-8"?>
	<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver"?>
<zk>
  <window id="win" border="normal" width="810px" minheight="300"
   apply="${manageCustomer}">
      <caption label="Manage Customers"/>
         <borderlayout height="30px">
	     <north border="none">
	        <menubar id="menubar" width="800px">
		   <menu label="Manage Customers">
		      <menupopup>
		         <menuitem id="add" label="Register New Customer">
			  </menuitem>
			  <menuseparator />
			  <menuitem id="exit" label="Exit" onClick="win.detach()" />
		       </menupopup>
		    </menu>
		 </menubar>
	      </north>
	  </borderlayout>
      <listbox id="customerList" mold="paging" pageSize="5" multiple="true" width="800px">
	   <listhead sizable="true">
	      <listheader label="Id" sort="auto(id)"/>
	      <listheader label="Name" sort="auto(name)"/>
	      <listheader label="Active Date" sort="auto(date)"/>
	      <listheader label="Deleted?" />
	   </listhead>
	</listbox>
</window>
</zk>
            

Manage Customer의 이전에 했던 구현과는 달리 이 예제는 제어기에서부터 보기를 분리하는 ZK의 MVC 접근 방식을 사용했다. index.zul 파일은 애플리케이션의 보기 파트만 들어 있는 반면에, 제어기 코드는 작성기 클래스 ManageCustomer에서 별도로 쓰여졌다. 이러한 점에서 ZK CDI 기능을 활용할 수 있다.

ZK MVC 접근 방식에서 제어기는 apply 속성을 사용하여 특정 구성 요소에 적용될 수 있다. 예제는 이 기술을 사용하여 ManageCustomer를 대시보드 기본 창 구성 요소에 적용한다. 또한 DelegatingVariableResolver과 EL 표현식에 대해 variable-resolver 지시문을 사용하여 컨테이너로 제공된 ManageCustomer 관리되는 bean 인스턴스를 적용하는 것을 시연한다.

대시보드 페이지에 두 가지 주요 구성 요소가 있다.

  • 맨 위의 메뉴에 Register New Customer와 Exit의 두 가지 서브메뉴 항목이 있다.

    Menubar는 ID가 addexit로 두 개의 하위 ZK menuitem 구성 요소가 있는 ZK 메뉴 표시줄 구성 요소이다.

  • 표에는 데이터베이스의 현재 고객이 나열된다. 예제의 표는 ID가 customerList인 ZK listbox 구성 요소이다. 표 열의 머리글은 customerList 목록 상자의 listheader 하위 구성 요소로 정의된다.

지금까지 대시보드 UI를 정의하는 구성 요소에 대해 알아 보았는데, 데이터는 어떨까? 언제 customerList 목록 상자가 채워질까? Listing 7에서 보여 주는 ManageCustomer 제어기 클래스를 살펴 보자.


Listing 7. ManageCustomer
                
@Named
@SessionScoped
public class ManageCustomer extends GenericComposer implements Serializable {	
	@Inject @SessionScoped CustomerService custSvc;
	@Inject @ComponentId("customerList") private transient Listbox customerList;
	/**
	 * Set up list of all customers on the dashboard
	 * @param component
	 */
	public void doAfterCompose(Component component) throws Exception {
    	   super.doAfterCompose(component);
	   List myList = custSvc.getAllCustomers();
	   ListModelList lm = new ListModelList(myList);
	   customerList.setModel(lm);
	   customerList.setItemRenderer(new CustomersListboxRenderer());
	}
...
            

먼저 ManageCustomer bean 클래스를 @Named 규정자로 표시하여 통합된 EL 표현식을 통해 이에 액세스할 수 있게 만든다. 이 과정은 "${manageCustomer}"apply 속성 값이 있는 index.zul 파일의 창 구성 요소에서 시연되었다.

다음 단계는 CDI 형안전 의존성 삽입 기능을 사용하여 CustomerService bean을 ManageCustomer 제어기 내에 삽입하는 것이다. CustomerService bean은 고객 정보의 추가, 업데이트, 제거 및 검색을 위해 데이터베이스에 액세스하는 메소드를 구현하는 유틸리티 클래스이다. 이 과정은 ManageCustomer 클래스 내에서 CustomerService 필드를 지정하고 이를 @javax.inject.Inject로 어노테이트하여 진행할 수 있다. CDI 스펙에 따르면 컨테이너가 ManageCustomer bean 인스턴스를 인스턴스화할 때마다 CustomerService bean 인스턴스가 자동으로 그 안에 삽입될 것이다.

이 시점에는 customerList 목록 상자에 액세스하여 모든 고객 데이터로 그 내용을 채워야 한다. 예제는 ZK CDI 확장으로 제공되는 GenericComposer 유틸리티 클래스를 사용한다. ManageCustomer 클래스를 org.zkoss.cdi.util.GenericComposer로 확장한 다음 창 구성 요소의 하위 구성 요소의 ManageCustomer 제어기 클래스로 자동 삽입을 사용 가능하게 만들자. ZK 구성 요소의 자동 삽입은 index.zul 파일에서 지정된 동일한 구성 요소 ID로 @org.zkoss.cdi.inject.ComponentId 규정자의 사용이 필요하다. 또한 ZK CDI 확장 스펙에 따르면 ComponentId 규정자 멤버 값은 필드 이름과 일치해야 한다. 예를 들어 customerList 목록 상자를 ManageCustomer에 삽입하려면 다음을 사용하자.

@Inject @ComponentId("customerList") private transient Listbox customerList;
            

이제 이 목록 상자 내에서 일부 데이터를 배치해 보자. 페이지가 클라이언트 브라우저에서 렌더링되기 전에 데이터 입력을 끝마쳐야 한다. GenericComposer는 유형 작성기이고 doAfterCompose() 메소드가 필요하다. 이 메소드는 모든 구성 요소가 작성된 후에 호출되는 콜백 메소드이다. 이를 통해 렌더링 이전이고 ZUL 구성 요소가 모두 작성된 후에 고객 목록 상자의 데이터 입력이 발생하도록 사용할 수 있다. 여전히 오버라이드된 doAfterCompose() 메소드에서 우선적으로 GenericComposerdoAfterCompose()를 호출해야 한다.

새 고객 등록하기

누군가가 "Register New Customer(새 고객 등록)"(Manage Customer 대시보드 메뉴 표시줄에서 Add 메뉴 항목)를 클릭하면 어떻게 될까? 클릭하면 그 후에는 Enter Customer Data 창이 표시되고 데이터베이스에서 새 Customer 기록으로 입력 데이터가 저장될 것이다. 이렇게 하려면 먼저 ManageCustomer 제어기에서 "add" 메뉴 항목 onClick 이벤트를 위해 이벤트 핸들링 메소드가 있어야 한다. 이는 ZK CDI 확장 정의된 @org.zkoss.cdi.event.Events 규정자와 CDI 정의된 이벤트 알림 모델을 사용하여 쉽게 할 수 있다. Listing 8에서 보여 주는 것과 같이 간단한 registerNewCustomer() 메소드를 정의하자.


Listing 8. registerNewCustomer() 메소드 정의하기
                
public void registerNewCustomer(@Observes @Events("add.onClick")  
                MouseEvent evt) throws Exception {
   Window win1 = (Window)Executions.createComponents("addCustomer.zul", null, null);
   win1.doModal();
   win1.setTitle("Enter Customer Data");
   win1.setClosable(true);
   win1.setMaximizable(true);
}
            

예제는 ZK 이벤트 유형인 유형 MouseEvent의 메소드 매개변수를 위한 @javax.enterprise.event.Observes 어노테이션을 사용한다. 이렇게 하면 registerNewCustomer() 메소드는 Observer 메소드(유형 MouseEvent를 관찰하는 메소드)가 된다. 유형 MouseEvent의 이벤트가 CDI로 게시될 때마다 이 메소드는 알림을 받는다. 유형 MouseEvent의 다양한 이벤트가 있을 수 있는데, 이 중에서 어떻게 구분할 수 있는가? 여기에서 @Events 규정자가 구출하려고 나타난다. @Events 규정자는 이 메소드가 어떠한 종류의 이벤트로 알려져야 하는지 표시하는 멤버 값으로 제공될 수 있다. @Events 멤버 값은 구성 요소 ID와 이어서 이벤트 이름의 형태로 지정될 수 있다. 예를 들어 Add menuitem onClick 이벤트의 경우 @Events 규정자는 Listing 7에서 보여 주는 것과 같이 "add.OnClick" 값으로 제공될 수 있다.

"Register New Customer" 메뉴 항목을 클릭했을 때 이벤트의 순서는 어떻게 되는가? 우선, 유형 MouseEvent의 ZK 이벤트가 서버에 전송된다. ZK 프레임워크는 이 이벤트를 수신하게 된다. 그 다음에 ZK CDI 확장은 적절한 @Events 규정자로 MouseEvent 유형에서 멤버 값과 함께 CDI 이벤트를 게시/작동시키게 된다. CDI는 정확한 @Events 규정자와 멤버 값으로 MouseEvent 유형에서 관찰되는 모든 메소드를 알리게 된다.


Listing 9. 고객 추가하기
                
<?page title="Add Customer" contentType="text/html;charset=UTF-8"?>
<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver"?>
<zk>
   <window id="addCustomerWin" title="Register New Customer" border="normal"
       apply="${addCustomer}">
      <grid fixedLayout="true" width="450px">
         <rows>
	    <row>
	       <label value="Customer Name" />
		<textbox id="customerName" constraint="no empty" />
	    </row>
	    <row>
	        <label value="Date" />
		   <datebox id="date" constraint="no empty"/>
	      </row>
	      <row>
		 <button id="saveBtn" label="Save" />
		 <button id="cancelBtn" label="Cancel" onClick="addCustomerWin.detach()"/>
	       </row>
	     </rows>
       </grid>
   </window>
</zk> 
            

호출된 이후에 registerNewCustomer() 메소드는 addCustomer.zul을 사용하는 새 창 구성 요소를 간단하게 작성하고, 이를 모달 대화 상자 창으로 만든다. 그림 5에는 이에 대한 예제가 있다.


그림 5. 새 고객 등록하기
Customer Date를 입력하고 Date 및 Save, Cancel 단추를 보여 주는 화면

이 예제는 index.zul 페이지와 유사하게도 <?variable-resolver ?> 지시문과 DelegatingVariableResolver를 사용하여 AddCustomer 관리되는 bean을 제어기로서 addCustomerWin 창 구성 요소에 적용한다. Register Customer 대화 상자는 Customer 이름과 Date의 필수 값이 있는 격자로 구현된다. AddCustomer 구현은 ManageCustomer 클래스와 유사하다. CustomerService bean은 @Inject 규정자를 사용하여 삽입되었고, addCustomerWin의 하위 구성 요소도 Listing 10에서 보여 주는 것과 같이 @Inject@ComponentId 규정자를 사용하여 자동으로 삽입된다.


Listing 10. 고객 추가하기
                
@Named
@SessionScoped
public class AddCustomer extends GenericComposer implements Serializable {
   @Inject @SessionScoped CustomerService custSvc;
   @Inject @ComponentId("customerName") private transient Textbox customerName;
   @Inject @ComponentId("date") private transient Datebox date;
   @Inject @ComponentId("saveBtn") private transient Button saveBtn;
}
            

ManageCustomer 클래스의 registerNewCustomer() 메소드와 같이 예제는 Listing 11에서 설명한 것과 같이 saveNewCustomerDetails() 옵저버 메소드를 구현한다.


Listing 11. 새 고객 세부 사항 저장하기
                    
public void saveNewCustomerDetails(
   @Observes @Events("saveBtn.onClick") MouseEvent evt, @New Customer newCustomer)
      throws Exception {
   newCustomer.setName(customerName.getValue());
   java.util.Date utilDate = date.getValue();
   java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
   newCustomer.setDate(sqlDate);
   custSvc.addCustomer(newCustomer);
   Executions.getCurrent().sendRedirect("index.zul");
   evt.getTarget().getParent().detach();
}	
            

Save 단추(saveBtn)를 클릭할 때마다 saveNewCustomerDetails() 메소드는 해당되는 onClick MouseEvent의 알림을 받는다. 이 메소드는 또한 유형 Customer의 추가 매개변수를 한 개 더 가진다. @New 규정자로 어노테이트되기 때문에 CDI 스펙에 따르면 Customer bean의 새 인스턴스는 이 메소드가 관찰될 때마다 자동으로 매개변수에 삽입된다.

고객 편집하기/(임시) 삭제하기

그림 6에서 보여 주는 것과 같이 사용자는 Manage Customer 대시보드에서 아무 고객 행을 선택하면 Edit Customer 화면에 액세스할 수 있다.


그림 6. 고객 편집하기
고객 이름, 날짜 및 확인된 삭제 상자를 보여 주는 화면

이 예제는 registerNewCustomer() 메소드와 유사하게도 옵저버 메소드 editCustomer()를 목록 상자에서 listitem이 선택될 때마다 전송되는 @Observes ZK SelectEvent로 정의한다.


Listing 12. 고객 편집하기
           
public void editCustomer(
   @Observes @Events("customerList.onSelect") SelectEvent evt) throws Exception {
      Listitem selectedCustomer = customerList.getSelectedItem();
      String custId = ((Listcell) (selectedCustomer.getChildren().get(0))).getLabel();
      Map<String, String> args = new HashMap<String, String>();
      args.put("custId", custId);
      Window win2 = (Window) Executions.createComponents("editCustomer.zul", null, args);
      win2.doModal();
      win2.setTitle("Enter Customer Data");
      win2.setClosable(true);
      win2.setMaximizable(true);
}	

editCustomer.zul의 editCustomerWin 창 구성 요소를 위한 EditCustomer 제어기 클래스를 구현하는 것은 AddCustomer와 매우 유사하다. 반복하지 않기 위해 이 글에서는 설명하지 않겠다.

이 애플리케이션의 코드, EditCustomer 클래스의 소스 및 editCustomer.zul 파일을 다운로드할 수 있다.


요약

My developerWorks에 있는 Web development 그룹에 참여하자.

My developerWorks Web development 그룹에서 다른 개발자들과 Web development와 관련된 주제를 토론하고 자원을 공유하자.

My developerWorks 회원이 아니라면, 지금 가입하자!

이 글에서 Java 코드로 쓰인 오픈 소스 Ajax 프레임워크인 ZK와 JSR-299 컨텍스트 및 의존성 삽입에 관해 살펴 보았다. ZK CDI 확장의 기능을 통해 ZK 프로그래밍 모델 내에서 CDI를 사용할 수 있다. Apache Tomcat에서 실행하고 MySQL 데이터베이스에 연결하는 현존하는 간단한 예제를 사용했다.

ZK 프레임워크는 풍부한 구성 요소 세트, 마크업 언어, 강력한 개발 도구 및 훌륭한 문서를 갖추었다. 이는 오픈 소스 이벤트 구동형 Ajax 프레임워크이다. 또한 Java EE 플랫폼 6의 JSR-299로 정의되는 CDI는 형안전 의존성 삽입, 이벤트 알림 모델 및 휴대용 확장을 개발하기 위한 SPI를 비롯한 강력한 기능 세트를 제공한다. ZK CDI 확장은 ZK 프로그래밍 모델과 CDI를 통합하여, 이를 통해 Java EE 6 엔터프라이즈 애플리케이션을 원활하게 개발할 수 있다.



다운로드 하십시오

설명이름크기다운로드 방식
Sample code for this articlezkManageCustomers.zip71 KBHTTP

다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기

토론

필자소개

developerWorks Contributing author level

Sachin tem um diploma de Mestrado da University of Utah, em Salt Lake City, EUA. Ele trabalhou em empresas grandes e pequenas nos Estados Unidos e Índia, executando várias funções técnicas e gerenciais. Sachin trabalha atualmente na divisão Lotus do IBM Software Group.

Photo of Ashish Dasnurkar

Ashish has a bachelor's degree from the University of Pune, India, and has worked with the Java EE platform for six years on several enterprise applications for multi-national companies. He currently works at the Potix Corporation, which is the driving force behind the ZK Ajax Framework.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=웹 개발, 자바
ArticleID=505398
ArticleTitle=ZK에서 CDI 프로그래밍 모델 탐색하기
publish-date=05252010
author1-email=sachin.mahajan@in.ibm.com
author1-email-cc=
author2-email=ashish@potix.com
author2-email-cc=

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.