메인 컨텐츠로 가기

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

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

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

  • 닫기 [x]

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

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

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

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

  • 닫기 [x]

RAP를 사용하여 RCP 애플리케이션을 웹 애플리케이션으로 변환하기

일부만 변경하여 마이그레이션하기

Zhi Luo, 소프트웨어 엔지니어, IBM China
Zhi Da Luo는 IBM China Development Lab, Emerging Technology Institute의 소프트웨어 엔지니어이다. Luo는 2008년에 IBM에 입사했다. 그는 프로그램 분석, 바이트코드 인스트루멘테이션 및 Java 동시성 프로그래밍 분야에 대한 경력이 있다. 현재는 Java 병렬 소프트웨어 정적/런타임 분석 도구를 담당한다. Luo는 중국 베이징에 있는 베이징 대학교에서 소프트웨어 엔지니어링 분야 석사학위를 받았다.
Wei Liu, 소프트웨어 엔지니어, IBM
Wei Liu
Wei Liu는 BM China Development Lab인 Emerging Technology Institute의 소프트웨어 엔지니어이다. Liu는 베이징대학교에서 소프트웨어 엔지니어링 분야 석사학위를 받았다. 그는 2010년에 IBM에 입사했으며 Eclipse RCP 및 RAP, Java 동시성 프로그래밍, 동적 프로그램 분석을 다룬 경험이 있다.
Ming Hai Wang, 소프트웨어 엔지니어
Ming Hai Wang
Ming Hai Wang은 플러그인 RCP 및 RAP를 개발하는 데 익숙한 소프트웨어 엔지니어이다. 그는 2년 넘게 RCP 개발을 진행했다. 또한, Java용 멀티코어 소프트웨어 개발 킷과 같은 것을 사용하여 플러그인을 RCP에서 RAP로 마이그레이션한 경험이 있다. 현재는 z/OS를 연구하는 데 전념하고 있다.
Raja Das, 소프트웨어 아키텍트, IBM
Raja Das
Raja Das는 IBM Software Group의 소프트웨어 아키텍처이다. 그는 현재 멀티코어 시스템에 필요한 라이브러리와 프레임워크를 개발하는 데 집중하고 있다. 이전에는 WebSphere Partner Gateway의 제품 아키텍트였다. 관심 분야는 프로그래밍 언어와 병렬 소프트웨어 및 시스템이다.

요약:  RCP(Rich Client Platform)를 이용하면 리치 데스크탑 애플리케이션을 빌드할 수 있습니다. 또한, RAP(Rich Ajax Platform)를 이용하면 Eclipse 개발 모델을 사용하여 Ajax 가능형 웹 애플리케이션을 빌드할 수 있습니다. 게다가 약간만 변경해도 기본 RCP 애플리케이션을 웹 애플리케이션으로 실행할 수 있습니다. 이 기사에서는 RAP의 주요 기능을 탐구하고 이어서 간단한 HTML 뷰어의 예제 코드를 통해, RAP를 사용하여 RCP 애플리케이션을 웹으로 마이그레이션하는 방법을 배웁니다.

기사 게재일:  2011 년 10 월 05 일
난이도: 중급 원문:  보기 PDF:  A4 and Letter (604KB | 24 pages)Get Adobe® Reader®
페이지뷰:  1124 회
의견:  


소개

Eclipse RCP(Rich Client Platform)를 사용하여 애플리케이션을 빌드할 수 있다. 이러한 리치 애플리케이션은 동적 플러그인 모델을 기반으로 하며 UI는 공통 툴킷과 확장 지점을 사용하여 빌드된다. 개방형 도구 개발 분야에서는 Eclipse RCP가 널리 사용된다.

RAP(Rich Ajax Platform) 프로젝트를 이용하면 Eclipse 개발 모델, 플러그인 및 Java 전용 API를 사용하여 Ajax 가능형 리치 웹 애플리케이션을 빌드할 수 있다. RAP의 목표는 가능한 거의 수정하지 않고 RCP 애플리케이션을 웹 브라우저에서 실행할 수 있게 하는 데 있다.

RAP와 RCP에는 동일한 인터페이스가 있지만, 기본적인 구현은 매우 다르다. RAP는 RWT라고 하는 SWT API를 대체하는 구현을 제공하며, Tomcat과 같은 서블릿 컨테이너에서 실행된다. 클라이언트는 Internet Explorer나 Chrome과 같은 표준 웹 브라우저를 사용하여 RAP에 액세스할 수 있다.

RAP와 RCP 애플리케이션은 다양한 사용자 환경에서 사용된다. RCP는 데스크탑 애플리케이션으로서 한 번에 사용자 한 명하고만 작동한다. 이와는 반대로 RAP 애플리케이션은 웹 기반 프로그램이며 동시에 다수의 사용자가 액세스할 수 있다. RAP는 서버측 OSGi 및 런타임 번들인 Equinox를 기반으로 한다. 웹 애플리케이션마다 OSGi 인스턴스 하나가 애플리케이션 범위에서 실행된다. RCP와는 대조적으로, RAP에서는 사용자 세션 간에 공유되는 번들과 사용자 세션을 처리해야 한다.

이 기사에서는 RAP의 주요 기능과 RAP를 사용하여 RCP 애플리케이션을 웹으로 마이그레이션하는 방법을 배운다. 이 기사에서 사용한 예제 코드를 다운로드할 수 있다.

RAP 및 RCP의 단일 소싱 기술

RAP는 단일 소싱이라고 하는 단일 코드 기반으로 리치 클라이언트 애플리케이션과 웹 애플리케이션을 개발하는 데 널리 사용된다. 기존의 RCP 개발 기술과 코드 기반을 재사용하여 웹 기반 RAP 애플리케이션을 개발할 수 있다. 현재의 RAP 1.3.x 버전에서는 기존 RCP 코드를 변경하지 않고도 이 코드의 70% ~ 90%를 RAP 환경에서 재사용할 수 있다.

다양한 API 및 함수 처리

RCP와 RAP에는 다양한 API, 함수, UI 라이브러리, 확장 지점 및 사용자 환경이 있다.

  • API: RAP 1.3.x 버전에서 모든 RCP API를 사용할 수 있는 것은 아니며 사용 가능한 API는 GC(Graphics Context), MouseMove Events 및 FileDialog가 있다. RAP에는 웹 고유의 요구사항을 처리하는 자체 추가 API(예: PhaseListener, ISessionStore 등)가 있다. 다양한 API를 다루려면 다음과 같은 권장사항을 고려한다.
    • 문제점을 해결하기 위해 호스트 플러그인에서 인터페이스를 정의한다.
    • 특정 플랫폼에만 적합한 방식의 문제점을 해결하기 위해 다양한 프래그먼트(Fragment)에서 인터페이스를 구현하는 클래스를 새로 정의한다.
    • Java Reflection으로 런타임 시에 특정 플랫폼에만 적합한 구현을 로드한다.

    샘플 소스 코드는 "단일 소싱 예제" 섹션에 있다.


  • UI 라이브러리: RCP와 RAP의 대상 플랫폼은 다양하기 때문에 RCP와 RAP에는 다양한 기본 UI 라이브러리리가 있다. RCP와 RAP의 공통 코드를 포함하고 있는 호스트 플러그인은 RCP와 RAP의 UI 라이브러리(예: RCP용 org.eclipse.ui 플러그인 또는 RAP용 org.eclipse.rap.ui 플러그인)에 종속된다. 필요에 따라 이 두 가지 플러그인을 호스트의 플러그인으로 가져와야 한다.

    다양한 대상 런타임을 사용할 때 컴파일 오류가 발생하지 않도록 하려면 그림 1과 같이 Properties 아래에 있는 Optional 선택란을 체크한다. 이렇게 하면 RAP/RCP 런타임이 실행될 때 올바른 라이브러리가 로드된다.



    그림 1. 선택적 종속성
    선택적 종속성

  • 확장 지점(E-P): 현재는 RAP에서 모든 RCP E-P가 사용 가능한 것은 아니다(예: bindingshelpSupport). 웹에 고유한 요구사항으로 인해 RAP에는 몇 가지 E-P(예: entrypointthemes)가 추가로 포함되었다.

    다양한 E-P를 처리하고 RCP와 RAP의 동일한 코드 기반을 사용하기 위해 OSGi 프래그먼트가 도입되었다. 프래그먼트는 특수한 OSGi 번들로, 또 다른 번들을 확장하며 런타임 시에 확장된 번들과 병합될 수 있다. 먼저, RCP와 RAP의 공통 코드를 포함하고 있는 호스트 플러그인을 정의한다. 그런 다음, RCP와 RAP 프래그먼트를 각각 작성한다. 이 프래그먼트에는 RCP와 RAP의 특정 플랫폼에만 적합한 코드가 포함된다. 런타임 시에는 해당 프래그먼트 중 하나만(RAP 또는 RCP) 호스트 플러그인과 함께 설치된다. 그러므로, 특정 플랫폼에만 적합한 E-P 확장을 해당 프래그먼트로 이동할 수 있으며 번들의 구조는 그대로 유지된다.


  • 다중 사용자 환경 싱글톤 패턴은 RCP에서 널리 사용된다. 그러나 다수의 사용자가 동시에 액세스할 수 있는 웹 기반 애플리케이션에서는 세션을 기반으로 하는 싱글톤이 필요하다. RAP는 각 세션에 맞는 싱글톤 구현을 제공하는 기본 클래스(SessionSingletonBase)를 제공하고 여러 사용자들이 애플리케이션 상태를 공유하지 못하도록 한다.

    세션 싱글톤은 RWT에 특정된 싱글톤으로, 세션의 범위 내에서 고유 인스턴스에 액세스할 수 있는 기능을 제공한다. 사용자 세션이 하나인 상황에서는 getInstance(Class)가 언제나 동일한 오브젝트를 리턴한다. 그러나 사용자 세션이 다양한 경우에는 리턴되는 인스턴스도 다양하다.

    세션 싱글톤 클래스를 구현하려면 싱글톤 인스턴스의 해당 범위를 처리하는 SessionSingletonBase#getInstance()를 호출해야 한다. 리스트 1 에는 이 패턴이 표시되어 있다. RAP FAQ는 참고자료를 참조한다.



    리스트 1. 세션 싱글톤 샘플
    
    package com.ibm.msdk.ui.configWas;
    
    import org.eclipse.rwt.SessionSingletonBase;
    
    public class SampleSessionSingleton{
        private SampleSessionSingleton(){}
    	
        public static SampleSessionSingleton getInstance(){
    	    return (SampleSessionSingleton)SessionSingletonBase
    		        .getInstance(SampleSessionSingleton.class);
        }
    }
    


단일 소싱 예제

이 섹션에서는 HTML 뷰어용 예제 RCP 애플리케이션을 사용하여 단일 소싱에 관해 배운다. 이 기사에서 사용한 샘플 코드를 다운로드할 수 있다. 이 예제에는 HTML 파일을 표시하는 데 사용된 뷰가 있으며, 그림 2에 표시되어 있듯이 이 뷰는 도구 모음에 있는 Open 단추를 사용하여 열 수 있다.


그림 2. RCP HTML 뷰어 샘플
Open 단추가 표시되어 있는 RCP HTML 뷰어 샘플의 스크린샷

이 예제에서는 브라우저 위젯을 사용하여 HTML 파일을 표시한다. 이 기능을 구현하려면 com.ibm.msdk.example이라고 하는 샘플 플러그인을 작성해야 한다.

  1. RCP에서 특정 플랫폼에만 적합한 코드를 식별한다.

    언급한 바와 같이 샘플 플러그인에는 RAP/RCP 특정 플랫폼에만 적합한 코드가 있다. 먼저, 샘플 프로젝트에서 공통 코드를 추출해야 한다. 이 코드를 분석하면 RAP에서 지원되지 않는 API가 RCP HTML 뷰어에서 식별된다. 목록 2에 표시되어 있는 FileDialog#open(com.ibm.msdk.example.action 패키지에 있는)이 이에 해당한다.



    리스트 2. RCP의 특정 플랫폼에만 적합한 코드
    	
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.ui.IWorkbenchWindow;
    
    import com.ibm.msdk.example.utils.HtmlFileReader;
    
    public class ImportHtmlAction extends Action {
    	
    	public static final String ACT_IMPORT_FILE = "ACT_IMPORT_FILE";
    	
    	private IWorkbenchWindow workbenchWindow;
    	
    	/**
    	 * Constructs an instance of <code>ImportHtmlAction</code> by given 
    	 * text and <code>IWorkbenchWindow</code>.
    	 * @param text
    	 * @param workbenchWindow
    	 */
    	public ImportHtmlAction(String text,IWorkbenchWindow workbenchWindow){
    		super(text);
    		this.workbenchWindow = workbenchWindow;
    	}
    
    	/**
    	 * Creates a file dialog for opening a new file,calls the method 
    	 * {@link HtmlFileReader#fetchHtmlContents(String)} to fetch the contents 
    	 * of the passed HTML file. Then fires the listener of <code>HTMLView</code> 
    	 * to refresh the contents of the view.
    	 */
    	@Override
    	public void run(){
    		Shell shell = workbenchWindow.getShell();
    		
    		FileDialog fileDialog = new FileDialog(shell,SWT.OPEN);
    		String filePath = fileDialog.open();
    		String htmlContents = null;
    		
    		if(filePath != null)
    			htmlContents = HtmlFileReader.fetchHtmlContents(filePath);
    		
    		firePropertyChange(ACT_IMPORT_FILE, null, htmlContents);
    	}
    }	
    

    RAP에서는 파일을 여는 대신 업로드하는 것이 합리적이다. "RAP Upload Project"에서는 이러한 업로드 함수를 제공하며, 이러한 함수는 RAP CVS 저장소(sandbox/org.eclipse.rwt.widgets.upload)에서 다운로드할 수 있다.

  2. RCP와 RAP 프래그먼트를 작성한다.

    com.ibm.msdk.example 플러그인은 RAP와 RCP 플랫폼 모두를 대상으로 하기 때문에 이 두 가지 플랫폼의 필수 번들을 필수 플러그인으로서 가져와야 한다. 예를 들면, org.eclipse.ui(RCP) 및 org.eclipse.rap.ui(RAP)와 같은 UI 번들이 필요하다. 다양한 대상 플랫폼에서 컴파일 오류가 발생하지 않도록 하려면 그림 3과 같이 해당 플러그인의 Properties에서 다양한 UI 번들의 종속성을 Optional로 지정한다.



    그림 3. 선택적 종속성
    선택적 종속성

    플랫폼 런타임 환경(RCP 또는 RAP)은 올바른 번들을 로드하게 된다. 대상 플랫폼이 두 개이므로 특정 플랫폼에만 적합한 코드를 유지할 프래그먼트 두 개를 새로 작성해야 한다. 그림 4에 표시되어 있는 바와 같이 프래그먼트의 호스트 플러그인 특성은 com.ibm.msdk.example 플러그인으로 설정된다.



    그림 4. 호스트 플러그인을 com.ibm.msdk.example로 설정
    호스트 플러그인을 com.ibm.msdk.example로 설정

  3. 특정 함수를 처리할 추상 클래스를 작성한다.

    RAP에는 FileDialog 위젯이 없다. 따라서 클라이언트 측에서 서버로 파일을 업로드할 수 있는 새로운 위젯을 사용해야 한다. 다행히도 RAP CVS는 저장소 위치 URL pserver:anonymous@dev.eclipse.org:/cvsroot/rt에서 다운로드할 수 있는 사용자 정의된 업로드 위젯을 제공하므로 org.eclipse.rap/sandbox/org.eclipse.rwt.widgets.upload에서 이 위젯을 찾아보자. 이 업로드 위젯이 올바르게 작동되도록 하려면 org.apache.commons.fileuploadorg.apache.commons.io 플러그인이 필요하다. 이 두 가지 플러그인은 저장소 위치 URL pserver:anonymous@dev.eclipse.org:/cvsroot/tools에서 다운로드할 수 있다. org.eclipse.orbit/에서 이 플러그인을 찾아보자. CVS를 사용하여 다운로드하는 방법에 관한 자세한 정보는 참고자료를 참조한다.

    1. 그림 5와 같이 RAP 프래그먼트에 필수 플러그인을 추가한다.

      그림 5. 종속 항목에 업로드 플러그인을 추가한다.
      종속 항목에 업로드 플러그인을 추가

    2. 호스트 플러그인에서는 RAP와 RCP 플랫폼마다 다른 특정 함수를 처리할 추상 클래스를 작성해야 한다. 리스트 3과 같이 추상 메소드 doViewHtml()을 정의한다.

      리스트 3. 액션용 추상 클래스
      /**
       * 
       */
      package com.ibm.msdk.example.actions;
      
      import org.eclipse.jface.action.Action;
      import org.eclipse.ui.IWorkbenchWindow;
      
      /**
       * @author Minghai.Wang
       * @version 1.0 2010-10-26
       * @since JDK1.6
       * @email wminghai@cn.ibmm.com
       */
      public abstract class AbstractViewHtmlAction extends Action {
      
      	protected IWorkbenchWindow workbenchWindow;
      
      	public static final String ACT_IMPORT_FILE = "ACT_IMPORT_FILE";
      
      	public static final String INSTANCE_CLASS = "com.ibm.msdk.example
      				.actions.ViewHtmlAction";
      
      	/**
      	 * Constructs an instance of <code>AImportHtmlAction</code> by given
      	 * <code>IWorkbenchWindow</code>.
      	 * 
      	 * @param workbenchWindow
      	 */
      	public AbstractViewHtmlAction(IWorkbenchWindow workbenchWindow) {
      		this.workbenchWindow = workbenchWindow;
      	}
      
      	public void run() {
      
      /**
      	 * Abstracts the method for viewing the given HTML file.
      	 * <p>
      	 * It is different between RCP platform and RAP platform.
      	 * <ul>
      	 * <li>In the RCP fragment,open a file dialog and select a HTML file that
      	 * will be parsed, and then show it.</li>
      	 * <li>In the RAP fragment,upload a parsing HTML file, then show it.
      	 * </ul>
      	 */
      	 
      	public abstract void doViewHtml();
      	 
      	/**
      	 * @return the workbenchWindow
      	 */
      	public IWorkbenchWindow getWorkbenchWindow() {
      		return workbenchWindow;
      	}
      
      	/**
      	 * @param workbenchWindow
      	 *            the workbenchWindow to set
      	 */
      	public void setWorkbenchWindow(IWorkbenchWindow workbenchWindow) {
      		this.workbenchWindow = workbenchWindow;
      	}
      
      }
      

    3. doViewHtml() 액션을 호출하려면 호스트 플러그인의 호출자 부분을 수정해야 한다. 리스트 4 에는 원본 클래스의 해당 메소드가 표시되어 있다.

      리스트 4. 원본 클래스 HtmlContentsView의 메소드
       	
      public class HtmlContentsView extends ViewPart implements
      		IPropertyChangeListener {
      		
          ...
          ...
      	/**
      	 * Fills the tool bar of the HTML view with a importing HTML action. A
      	 * listener is added to the created action of importing HTML view.
      	 */
      	protected void fillToolBarAction() {
      		ImportHtmlAction importHtmlAct = new ImportHtmlAction("Open...",
      				getViewSite().getWorkbenchWindow());
      		IToolBarManager toolBarManager = getViewSite().getActionBars()
      				.getToolBarManager();
      		toolBarManager.add(importHtmlAct);
      
      		importHtmlAct.addPropertyChangeListener(this);
      	}	
      	...
      }	
      

      리스트 5에 표시된 바와 같이 com.ibm.msdk.example 플러그인의 HtmlContentsView.java에서 Java Reflection을 사용하여 프래그먼트 액션을 새로 얻을 수 있다. RCP와 RAP 프래그먼트에서 작성된 서브클래스의 전체 이름은 동일해야 한다. 이렇게 하면 다양한 런타임 플랫폼(RCP 또는 RAP)에서 해당 프래그먼트가 로드되고 적절한 doViewHtml() 액션이 호출된다.



      리스트 5. 새 클래스 HtmlContentsView의 메소드
      	
      public class HtmlContentsView extends ViewPart implements
      		IPropertyChangeListener {		
          ...
      	/**
      	 * Fills an instance of <code>AbstractViewHtmlAction</code> 
      	 * that is created by Java reflection.
      	 */
          protected void fillToolBarAction() {
      	  try {
      		Class<?> clazz = Class
      		   .forName(AbstractViewHtmlAction.INSTANCE_CLASS);
      		Constructor<?> cons = clazz
      		   .getConstructor(IWorkbenchWindow.class);
      		AbstractViewHtmlAction viewHtmlAction = (AbstractViewHtmlAction) 
      		cons.newInstance(getViewSite().getWorkbenchWindow());
      
      		IToolBarManager toolBarManager = getViewSite().getActionBars()
      		   .getToolBarManager();
      		toolBarManager.add(viewHtmlAction);
      
      		viewHtmlAction.addPropertyChangeListener(this);
      			
      //		Add an action for viewing singleton info.
      		ViewSingletoInfoAction viewSingleton = new ViewSingletoInfoAction(
      		    getViewSite().getWorkbenchWindow());
      		toolBarManager.add(viewSingleton);
      	  } catch (ClassNotFoundException e) {
      		  e.printStackTrace();
      	  } catch (Exception e) {
      		  e.printStackTrace();
      	  } 
      	}	
      	...
      }	
      

  4. RAP와 RCP 프래그먼트를 구현한다.

    특정 플랫폼에서만 작동하는 함수를 처리하기 위해 추상 클래스를 정의한 후에는 RCP와 RAP 프래그먼트에서 각각 다르게 추상 메소드를 구현해야 한다. RCP 프래그먼트에서는 리스트 6과 같이 AbstractViewHtmlAction 추상 클래스를 확장하는 클래스를 새로 작성한다. 이 클래스는 FileDialog를 사용하여 HTML 파일을 열 추상 메소드를 구현한다.



    리스트 6. AbstractViewHtmlAction의 RCP 구현
    	
    public class ViewHtmlAction extends AbstractViewHtmlAction {
    	...
    
    	/**
    	 * Creates a file dialog for opening a new file,calls the method
    	 * {@link HtmlFileReader#fetchHtmlContents(String)} to fetch the 
    	 * contents of the passed HTML file.Then fires the listener of 
    	 * <code>HTMLView</code> to refresh the contents of the view.
    	 */
    	@Override
    	public void doViewHtml() {
    		Shell shell = workbenchWindow.getShell();
    		FileDialog fileDialog = new FileDialog(shell,SWT.OPEN);
    		String filePath = fileDialog.open();
    		String htmlContents = null;
    		if(filePath != null)
    			htmlContents = HtmlFileReader.fetchHtmlContents(filePath);
    		
    		firePropertyChange(ACT_IMPORT_FILE, null, htmlContents);
    	}
    	
    	...
    }	
    

    RAP 프래그먼트 추상 메소드 구현은 RCP와는 다르다. 리스트 7에 표시된 바와 같이 이 구현은 "upload" 위젯을 사용하여 HTML 파일을 웹 서버로 전송한 후에 이 파일을 연다.



    리스트 7. AbstractViewHtmlAction의 RAP 구현
    	
    public class ViewHtmlAction extends AbstractViewHtmlAction {
    	...
    
    	/**
    	 * Opens a new shell for uploading a HTML file,
    	 * creates the widgets.
    	 */
    	@Override
    	public void doViewHtml() {
    		Display display = Display.getDefault();
    		Shell shell = new Shell(display, SWT.PRIMARY_MODAL 
    				| SWT.CLOSE | SWT.RESIZE);
    		shell.setText("Upload a HTML file");
    		shell.setLayout(new GridLayout());
    		shell.setSize(450, 60);
    //		Creates the control in the shell.
    		createControl(shell);
    		shell.layout();
    		shell.open();
    		while (!shell.isDisposed()) {
    			if (!display.readAndDispatch())
    				display.sleep();
    		}
    	}
    	
    	/**
    	 * 
    	 * @param shell
    	 */
    	protected void createControl(final Shell shell){
    		Upload upload = new Upload(shell,SWT.NONE,Upload.SHOW_UPLOAD_BUTTON);
    		upload.setUploadButtonText("Upload");
    		upload.setBrowseButtonText("Location...");
    		GridDataFactory.fillDefaults().grab(true, false).applyTo(upload);
    		
    		upload.addUploadListener(new UploadListener(){
    			...
    			...
    		});
    	}	
    	...
    }	
    

  5. 다중 사용자 지원

    RAP 플랫폼은 세션의 범위 내에서 고유 인스턴스를 액세스하는 데 필요한 세션 싱글톤을 제공한다. 예제를 통해 RAP에서 세션 싱글톤을 사용하고 RCP에서 공통 싱글톤을 사용하는 것이 합리적이라는 것을 알 수 있다.

    1. 호스트 플러그인에서 싱글톤 클래스 ExampleSingleton을 작성한다. 인터페이스(ISingletonProvider)와 클래스 로더(ImplementationLoader)도 작성한다.

      리스트 8. 호스트 플러그인의 세션 싱글톤
       	
      public class ExampleSingleton {
      
      	private final static ISingletonProvider PROVIDER;
      	static{
      		PROVIDER = (ISingletonProvider) ImplementationLoader
      				.newInstance(ExampleSingleton.class);
      	}
      	
      	/**
      	 * Gets the instance of <code>ExampleSingleton</code> which has 
      	 * different implementations in RAP and RCP fragment.
      	 * @return
      	 */
      	public static ExampleSingleton getInstance(){
      		return (ExampleSingleton)PROVIDER.getInstanceInternal();
      	}
      	
      	public String fetchSingtonInfo(){
      		return PROVIDER.fetchSingletonInfo();
      	}
      	
      }	
      



      리스트 9. 호스트 플러그인의 인터페이스
      	
      public interface ISingletonProvider {
      
      	Object getInstanceInternal();
      	
      	/**
      	 * Fetches the singleton info,which is different 
      	 * between RCP platform and RAP platform.
      	 * @return
      	 */
      	String fetchSingletonInfo();
      }	
      



      리스트 10. 로더
      	
      public class ImplementationLoader {
      
      	public static Object newInstance(final Class<?> type){
      		String name = type.getName();
      		Object result = null;
      		try {
      			result = type.getClassLoader()
      			    .loadClass(name + "Impl").newInstance();
      		} catch (Exception e) {
      			e.printStackTrace();
      		}
      		return result;
      	}
      }	
      

    2. ExampleSingleton 서브클래스를 작성한다. RAP와 RCP 프래그먼트로 ISingletonProvider 인터페이스를 구현하여 다양한 싱글톤 구현을 제공한다.

      리스트 11. RAP로 세션 싱글톤 구현
       
      public class ExampleSingletonImpl implements ISingletonProvider {
      
      	public Object getInstanceInternal() {
      		return SessionSingletonBase.getInstance(ExampleSingleton.class);
      	}
      	...
      	...
      }	
      



      리스트 12. RCP로 세션 싱글톤 구현
      	
      public class ExampleSingletonImpl implements ISingletonProvider {
      	
      	private static ExampleSingleton singleton;
      	
      	/* (non-Javadoc)
      	 * @see com.ibm.msdk.example.singleton
      	 * .ISingletonProvider#getInstanceInternal()
      	 */
      	@Override
      	public Object getInstanceInternal() {
      		if(singleton == null)
      			singleton = new ExampleSingleton();
      		return singleton;
      	}
      
      	/* (non-Javadoc)
      	 * @see com.ibm.msdk.example.singleton
      	 * .ISingletonProvider#fetchSingletonInfo()
      	 */
      	@Override
      	public String fetchSingletonInfo() {
      		return "This message is from RCP fragment!";
      	}
      }
      


RAP 애플리케이션을 패키지하여 Tomcat에 배치

이 섹션에서는 WAR 파일을 작성하여 Tomcat에 배치한다. 그리고 배치된 WAR 파일이 작동하지 않는 경우에 문제점을 해결할 수 있는 몇 가지 팁을 배운다.

RAP 애플리케이션을 WAR 파일로 패키징

현재, Eclipse는 RAP 애플리케이션을 빌드하는 기능을 직접 지원하지 않는다. 따라서 지금은 여러 가지 Ant 스크립트와 자원 템플리트를 사용하여 WAR 파일을 작성해야 한다. RAP의 CVS에 있는 org.eclipse.rap.demo.feature를 통해 org.eclipse.rap.demo 프로젝트를 RAP 애플리케이션으로 패키지하는 WAR 파일을 작성하는 방법을 확인할 수 있다. 이 프로젝트를 수정하여 HTML 뷰어 샘플에서 사용 가능한 특수 프로젝트를 작성할 수 있다.

  1. RAP Developer Guide 온라인 버전에서 Team Project Set 파일을 다운로드한다(Advanced Topics > WAR Deployment). (관련 링크는 참고자료에서 확인한다.)
  2. File > Import > Team Project Set를 선택하고 다운로드한 파일의 위치를 입력한다.
  3. Finish를 클릭하면 org.eclipse.equinox.http.servletbridge, org.eclipse.equinox.servletbridge 및 org.eclipse.rap.demo.feature를 포함한 필수 프로젝트를 CVS에서 가져올 수 있다.
  4. org.eclipse.rap.demo.feature의 이름을 com.ibm.msdk.example.rap.feature로 수정하고 다음과 같은 것들을 피처 목록에 추가한다(그림 6).
    • com.ibm.msdk.example
    • com.ibm.msdk.example.rap
    • org.apache.commons.fileupload
    • org.apache.commons.io
    • org.eclipse.rwt.widgets.upload

    RAP 데모 플러그인이 필요하지 않으면 피처 목록에서 org.eclipse.rap.demo를 제거한다.

  5. 그림 6과 같이 피처의 ID를 com.ibm.msdk.example.rap.feature로 수정한다.

    그림 6. HTML 뷰어의 피처
    HTML 뷰어의 피처

  6. Ant 태스크를 구성한 후, 실행하여 다음과 같이 전체 HTML 뷰어 RAP 애플리케이션을 빌드한다.
    1. webappBuilder.xml을 열고 27행에 있는 특성값을 com.ibm.msdk.example.rap.feature로 수정한다.
    2. webappBuilder.xml을 마우스 오른쪽 단추로 클릭하여 External Tools Dialog를 연다(Run As > External Tools Configuration).
    3. Ant Build를 두 번 클릭한다.
    4. 새 항목, com.ibm.msdk.example.rap.feature webappBuilder.xml을 선택한다.
    5. JRE 탭에서 Runtime JRERun in the same JRE as the workspace로 조정한다. 이렇게 하지 않으면 스크립트에서 PDE Ant Task를 사용하여 피처를 내보낼 수 없게 된다.
    6. Run을 클릭한다.
    7. 그러면 콘솔에 BUILD SUCCESSFUL 메시지가 표시된다.

    PDE Export 태스크가 백그라운드에서 계속 진행 중이라는 것을 진행 표시기를 통해 알 수 있다. 이 태스크가 완료될 때까지 기다린다.

  7. 다음과 같이 config.ini 파일을 생성한다.
    1. org.eclipse.rap.demo에서 ConfigIniCreator.java 파일을 열고 리스트 13과 같이 39행을 수정한다.

      리스트 13. 수정된 코드
      	
      File file = new File( "build\\demo\\WEB-INF\\eclipse\\plug-ins" )

    2. ConfigIniCreator를 Java 애플리케이션으로 실행한다. (리스트 14에 있는 것과 비슷한 텍스트가 Eclipse 콘솔에 출력된다.)

      리스트 14. Config.ini 샘플
      					
      
      #Eclipse Runtime Configuration File
      osgi.bundles= com.ibm.icu.base@start,\
      com.ibm.msdk.example.rap,\
      com.ibm.msdk.example@start,\
      org.apache.commons.fileupload@start,\
      org.apache.commons.io@start,\
      org.eclipse.core.commands@start,\
      org.eclipse.core.contenttype@start,\
      org.eclipse.core.databinding.observable@start,\
      org.eclipse.core.databinding.property@start,\
      org.eclipse.core.databinding@start,\
      org.eclipse.core.expressions@start,\
      org.eclipse.core.jobs@start,\
      org.eclipse.core.runtime@start,\
      org.eclipse.equinox.app@start,\
      org.eclipse.equinox.common@2:start,\
      org.eclipse.equinox.http.registry@start,\
      org.eclipse.equinox.http.servletbridge@start,\
      org.eclipse.equinox.http.servlet@start,\
      org.eclipse.equinox.preferences@start,\
      org.eclipse.equinox.registry@start,\
      org.eclipse.help@start,\
      org.eclipse.osgi.services@start,\
      org.eclipse.rap.demo@start,\
      org.eclipse.rap.jface.databinding@start,\
      org.eclipse.rap.jface@start,\
      org.eclipse.rap.rwt.q07,\
      org.eclipse.rap.rwt@start,\
      org.eclipse.rap.ui.views@start,\
      org.eclipse.rap.ui.workbench@start,\
      org.eclipse.rap.ui@start,\
      org.eclipse.rwt.widgets.upload@start,\
      org.eclipse.equinox.servletbridge.extensionbundle
      osgi.bundles.defaultStartLevel=4
      

    3. 이 텍스트를 모두 복사하여 {Project root}/templates/WEB-INF/eclipse/config.ini의 기존 컨텐츠를 바꾼다.
    4. 모든 랩 프래그먼트(com.ibm.msdk.example.rap)에서 @start를 제거한다.
    5. 먼저, {Project root}/templates/WEB-INF/eclipse/config.ini를 {Project root}/build/demo/WEB-INF/eclipse/configuration/으로 복사하여 이전 컨텐츠를 바꾼다. feature.xml을 수정한 후에는 config.ini 파일을 재생성해야 한다.
    6. com.ibm.msdk.example.rap.feature/script 디렉토리에서 build.xml을 새로 작성한 후에 다음 스크립트를 이 파일에 복사한다.

      리스트 15. ANT 스크립트를 사용하여 WAR 파일 빌드
       <?xml version="1.0"?>
      <project name="warbuild" default="war.gen">
        <property name="war.name" value="sample.war"/>
        <target name="war.gen" depends="clean">
          <war warfile="../${war.name}" webxml="../build/msdk/WEB-INF/web.xml">
            <lib dir="../build/msdk/WEB-INF/lib" />
            <lib dir="../build/msdk/WEB-INF/eclipse" prefix="WEB-INF/eclipse" />
          </war>
        </target>
        <target name="clean">
          <delete file="../${war.name}"/>
        </target>
      </project>
      

    7. Eclipse에서 Ant Build로 build.xml을 실행한다. 그러면 그림 7과 같이 HTML 뷰어의 sample.war 파일이 프로젝트 루트 디렉토리에 생성된다.

      그림 7. Eclipse 작업 공간에 표시된 sample.war
      Eclipse 작업 공간에 표시된 sample.war

sample.war 파일을 Tomcat에 배치

sample.war 파일을 Tomcat에 배치하려면 sample.war 파일을 {TOMCAT_HOME}/webapps/로 복사해야 한다. Tomcat을 시작한 후, 그림 8과 같이 http://localhost:8080/sample/msdkExample URL로 HTML 뷰어에 액세스한다.


그림 8. sample.war 파일을 Tomcat에 배치
sample.war 파일을 Tomcat에 배치

배치된 WAR 파일이 작동하지 않는 경우

개발 시에는 RAP가 작동했지만, Tomcat이나 WebSphere에 배치한 후에는 작동하지 않는 경우가 발생할 수 있다. 이러한 상황이 발생하면 다음을 확인한다.

  • RAP 애플리케이션이 build.properties 파일을 사용하는 경우에는 이 파일을 가져왔는지 그리고 사용된 라이브러리가 플러그인 클래스 경로에 나열되어 있는지 확인한다.
  • 리스트 16에 있는 수정된 텍스트를 web.xml에 추가하여 OSGi 콘솔을 활성화한다.

    리스트 16. OSGi 프레임워크 콘솔 활성화
    									
    
    <init-param>
    <param-name>commandline</param-name>
    <param-value>-console</param-value>
    </init-param> 
    <!-- 
    <init-param>
    <param-name>commandline</param-name>
    <param-value>-registryMultiLanguage</param-value> 
    </init-param>
    -->
    <init-param>
    <param-name>enableFrameworkControls</param-name>
    <param-value>true</param-value>
    </init-param>
    

    Tomcat 콘솔에서 ss를 입력하여 모든 번들이 시작되었는지 확인한다. 그렇지 않은 경우에는 start <bundle-id>를 사용하여 모든 번들을 시작한다. 스택을 추적하면 누락된 것이 무엇인지 쉽게 확인할 수 있다. 그림 9와 같이 ss로 나열된 목록에서 org.eclipse.equinox.servletbridge.extensionbundle의 상태가 RESOVLED로 되어 있는지 확인한다.



    그림 9. Tomcat의 시작된 번들
    Tomcat의 시작된 번들

  • WAR 파일에 다음과 같은 번들이 포함되어 있는지 확인한다.
    • javax.servlet 번들. 플러그인 명시 파일에서는 Require-Bundle 섹션 대신 Import-Package 섹션에 javax.servlet이 표시되어야 한다.
    • org.eclipse.update.configurator 번들
    • *.jetty.* 번들
  • WAR 파일을 재배치한 후에는 해당 서블릿 엔진의 작업 디렉토리(Tomcat에서는 <tomcat_install>/work/Catalina/localhost/work/<webapp_name>)가 삭제되었는지 확인한다.

결론

이 기사에서는 RAP와 RCP 애플리케이션 개발의 단일 소싱 개념을 소개했다. 또한, 단일 소싱 기술을 사용하여 기존 RCP 애플리케이션을 웹 기반 RAP 애플리케이션으로 변환하는 방법을 배웠다. RAP는 RCP 개발자에게 기존 코드 기반을 재사용하여 웹 기반 애플리케이션을 작성할 수 있는 강력한 도구를 제공한다. 이 기사에서는 RAP 애플리케이션을 WAR 파일로 패키지하는 방법과 이 WAR 파일을 웹 컨테이너에 배치하는 방법을 살펴보았다.



다운로드 하십시오

설명이름크기다운로드 방식
Project sampleworkspaceExample.zip57KBHTTP

다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술

  • RAP Tooling 및 RAP Runtime: RAP Tooling 및 RAP Runtime을 다운로드하자.

  • Eclipse for RCP and RAP developers: Eclipse 플러그인, 리치 클라이언트 또는 리치 Ajax 애플리케이션(RCP+RAP), Mylyn 및 XML 편집기를 개발하고자 하는 개발자를 위한 완전한 도구 세트인, Eclipse for RCP and RAP developers를 다운로드하자.

토론

필자소개

Zhi Da Luo는 IBM China Development Lab, Emerging Technology Institute의 소프트웨어 엔지니어이다. Luo는 2008년에 IBM에 입사했다. 그는 프로그램 분석, 바이트코드 인스트루멘테이션 및 Java 동시성 프로그래밍 분야에 대한 경력이 있다. 현재는 Java 병렬 소프트웨어 정적/런타임 분석 도구를 담당한다. Luo는 중국 베이징에 있는 베이징 대학교에서 소프트웨어 엔지니어링 분야 석사학위를 받았다.

Wei Liu

Wei Liu는 BM China Development Lab인 Emerging Technology Institute의 소프트웨어 엔지니어이다. Liu는 베이징대학교에서 소프트웨어 엔지니어링 분야 석사학위를 받았다. 그는 2010년에 IBM에 입사했으며 Eclipse RCP 및 RAP, Java 동시성 프로그래밍, 동적 프로그램 분석을 다룬 경험이 있다.

Ming Hai Wang

Ming Hai Wang은 플러그인 RCP 및 RAP를 개발하는 데 익숙한 소프트웨어 엔지니어이다. 그는 2년 넘게 RCP 개발을 진행했다. 또한, Java용 멀티코어 소프트웨어 개발 킷과 같은 것을 사용하여 플러그인을 RCP에서 RAP로 마이그레이션한 경험이 있다. 현재는 z/OS를 연구하는 데 전념하고 있다.

Raja Das

Raja Das는 IBM Software Group의 소프트웨어 아키텍처이다. 그는 현재 멀티코어 시스템에 필요한 라이브러리와 프레임워크를 개발하는 데 집중하고 있다. 이전에는 WebSphere Partner Gateway의 제품 아키텍트였다. 관심 분야는 프로그래밍 언어와 병렬 소프트웨어 및 시스템이다.

잘못된 도움말 신고

부정사용 신고

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


잘못된 도움말 신고

부정사용 신고

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


디벨로퍼웍스 로그인


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=763487
ArticleTitle=RAP를 사용하여 RCP 애플리케이션을 웹 애플리케이션으로 변환하기
publish-date=10052011

태그

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

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

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

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

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