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 애플리케이션을 개발할 수 있다. 현재의 RAP 1.3.x 버전에서는 기존 RCP 코드를 변경하지 않고도 이 코드의 70% ~ 90%를 RAP 환경에서 재사용할 수 있다.
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가 사용 가능한 것은 아니다(예:
bindings및helpSupport). 웹에 고유한 요구사항으로 인해 RAP에는 몇 가지 E-P(예:entrypoint및themes)가 추가로 포함되었다.다양한 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 뷰어 샘플
이 예제에서는 브라우저 위젯을 사용하여 HTML 파일을 표시한다. 이 기능을 구현하려면 com.ibm.msdk.example이라고 하는 샘플 플러그인을 작성해야 한다.
- 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)에서 다운로드할 수 있다.
- 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로 설정
- 특정 함수를 처리할 추상 클래스를 작성한다.
RAP에는 FileDialog 위젯이 없다. 따라서 클라이언트 측에서 서버로 파일을 업로드할 수 있는 새로운 위젯을 사용해야 한다. 다행히도 RAP CVS는 저장소 위치 URL pserver:anonymous@dev.eclipse.org:/cvsroot/rt에서 다운로드할 수 있는 사용자 정의된 업로드 위젯을 제공하므로 org.eclipse.rap/sandbox/org.eclipse.rwt.widgets.upload에서 이 위젯을 찾아보자. 이 업로드 위젯이 올바르게 작동되도록 하려면
org.apache.commons.fileupload와org.apache.commons.io플러그인이 필요하다. 이 두 가지 플러그인은 저장소 위치 URL pserver:anonymous@dev.eclipse.org:/cvsroot/tools에서 다운로드할 수 있다. org.eclipse.orbit/에서 이 플러그인을 찾아보자. CVS를 사용하여 다운로드하는 방법에 관한 자세한 정보는 참고자료를 참조한다.- 그림 5와 같이 RAP 프래그먼트에 필수 플러그인을 추가한다.
그림 5. 종속 항목에 업로드 플러그인을 추가한다.
- 호스트 플러그인에서는 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; } }
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(); } } ... }
- 그림 5와 같이 RAP 프래그먼트에 필수 플러그인을 추가한다.
- 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(){ ... ... }); } ... }
- 다중 사용자 지원
RAP 플랫폼은 세션의 범위 내에서 고유 인스턴스를 액세스하는 데 필요한 세션 싱글톤을 제공한다. 예제를 통해 RAP에서 세션 싱글톤을 사용하고 RCP에서 공통 싱글톤을 사용하는 것이 합리적이라는 것을 알 수 있다.
- 호스트 플러그인에서 싱글톤 클래스
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; } }
-
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!"; } }
- 호스트 플러그인에서 싱글톤 클래스
이 섹션에서는 WAR 파일을 작성하여 Tomcat에 배치한다. 그리고 배치된 WAR 파일이 작동하지 않는 경우에 문제점을 해결할 수 있는 몇 가지 팁을 배운다.
현재, Eclipse는 RAP 애플리케이션을 빌드하는 기능을 직접 지원하지 않는다. 따라서 지금은 여러 가지 Ant 스크립트와 자원 템플리트를 사용하여 WAR 파일을 작성해야 한다. RAP의 CVS에 있는 org.eclipse.rap.demo.feature를 통해 org.eclipse.rap.demo 프로젝트를 RAP 애플리케이션으로 패키지하는 WAR 파일을 작성하는 방법을 확인할 수 있다. 이 프로젝트를 수정하여 HTML 뷰어 샘플에서 사용 가능한 특수 프로젝트를 작성할 수 있다.
- RAP Developer Guide 온라인 버전에서 Team Project Set 파일을 다운로드한다(Advanced Topics > WAR Deployment). (관련 링크는 참고자료에서 확인한다.)
- File > Import > Team Project Set를 선택하고 다운로드한 파일의 위치를 입력한다.
- Finish를 클릭하면 org.eclipse.equinox.http.servletbridge, org.eclipse.equinox.servletbridge 및 org.eclipse.rap.demo.feature를 포함한 필수 프로젝트를 CVS에서 가져올 수 있다.
- 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를 제거한다.
- 그림 6과 같이 피처의 ID를
com.ibm.msdk.example.rap.feature로 수정한다.
그림 6. HTML 뷰어의 피처
- Ant 태스크를 구성한 후, 실행하여 다음과 같이 전체 HTML 뷰어 RAP 애플리케이션을 빌드한다.
- webappBuilder.xml을 열고 27행에 있는 특성값을
com.ibm.msdk.example.rap.feature로 수정한다. - webappBuilder.xml을 마우스 오른쪽 단추로 클릭하여 External Tools Dialog를 연다(Run As > External Tools Configuration).
- Ant Build를 두 번 클릭한다.
- 새 항목, com.ibm.msdk.example.rap.feature webappBuilder.xml을 선택한다.
- JRE 탭에서 Runtime JRE를 Run in the same JRE as the workspace로 조정한다. 이렇게 하지 않으면 스크립트에서 PDE Ant Task를 사용하여 피처를 내보낼 수 없게 된다.
- Run을 클릭한다.
- 그러면 콘솔에
BUILD SUCCESSFUL메시지가 표시된다.
PDE Export 태스크가 백그라운드에서 계속 진행 중이라는 것을 진행 표시기를 통해 알 수 있다. 이 태스크가 완료될 때까지 기다린다.
- webappBuilder.xml을 열고 27행에 있는 특성값을
- 다음과 같이 config.ini 파일을 생성한다.
- org.eclipse.rap.demo에서 ConfigIniCreator.java 파일을 열고 리스트 13과 같이 39행을 수정한다.
리스트 13. 수정된 코드File file = new File( "build\\demo\\WEB-INF\\eclipse\\plug-ins" )
- 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
- 이 텍스트를 모두 복사하여 {Project root}/templates/WEB-INF/eclipse/config.ini의 기존 컨텐츠를 바꾼다.
- 모든 랩 프래그먼트(com.ibm.msdk.example.rap)에서
@start를 제거한다. - 먼저, {Project root}/templates/WEB-INF/eclipse/config.ini를 {Project root}/build/demo/WEB-INF/eclipse/configuration/으로 복사하여 이전 컨텐츠를 바꾼다. feature.xml을 수정한 후에는 config.ini 파일을 재생성해야 한다.
- 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>
- Eclipse에서 Ant Build로 build.xml을 실행한다. 그러면 그림 7과 같이 HTML 뷰어의 sample.war 파일이 프로젝트 루트 디렉토리에 생성된다.
그림 7. Eclipse 작업 공간에 표시된 sample.war
- org.eclipse.rap.demo에서 ConfigIniCreator.java 파일을 열고 리스트 13과 같이 39행을 수정한다.
sample.war 파일을 Tomcat에 배치하려면 sample.war 파일을 {TOMCAT_HOME}/webapps/로 복사해야 한다. Tomcat을 시작한 후, 그림 8과 같이 http://localhost:8080/sample/msdkExample URL로 HTML 뷰어에 액세스한다.
그림 8. sample.war 파일을 Tomcat에 배치
개발 시에는 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의 시작된 번들
- 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 sample | workspaceExample.zip | 57KB | HTTP |
교육
-
RAP(Rich Ajax Platform): Eclipse 개발 모델, Eclipse 워크벤치 확장 지점이 있는 플러그인 및 SWT API가 있는 위젯 툴킷을 사용하여 Ajax 가능형
리치 웹 애플리케이션을 빌드할 수 있는 RAP에 관해 자세히 알아보자.
-
RAP/FAQ(The Eclipse Foundation, 2011): 이 RAP FAQ를 확인하자.
-
CVS Howto: Anonymous CVS(The Eclipse Foundation, 2011): CVS를 사용하여 다운로드하는 방법을 자세히 배우자.
-
RAP Developer Guide: Eclipse RAP 개발자 안내서를 읽자.
- "Rich Ajax Platform, Part 1: An introduction"(developerWorks, 2007년 10월) 및 "Rich Ajax Platform, Part 2: Developing applications"(developerWorks, 2007년 12월):
이 기사에서 RAP에 대한 소개 내용을 읽고 핵심 개념을 탐구하고 RAP의 고급 기능을 사용하는 방법을 배우자.
제품 및 기술
- 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를 다운로드하자.
토론
- 지금 developerWorks 프로파일을 작성하고 Ajax에 대한 관심 목록을 설정하자. developerWorks 커뮤니티에서 최신 정보를 자주 확인하자.
- 웹 개발에 관심이 있는 다른 developerWorks 멤버를 찾아보자.
- 자신의 지식을 공유하자. 웹 주제를 다루는 developerWorks 그룹에 참여하자.
- Roland Barcia는 자신의 블로그에서 Web 2.0 및 미들웨어에 대해 설명했다.
- developerWorks의 멤버들이 공유하고
있는 웹 주제에 대한 책갈피를 살펴보자.
- 빠른 해답: Web 2.0 Apps forum을 방문한다.
- 빠른 해답: Ajax forum을 방문하십시오.
Zhi Da Luo는 IBM China Development Lab, Emerging Technology Institute의 소프트웨어 엔지니어이다. Luo는 2008년에 IBM에 입사했다. 그는 프로그램 분석, 바이트코드 인스트루멘테이션 및 Java 동시성 프로그래밍 분야에 대한 경력이 있다. 현재는 Java 병렬 소프트웨어 정적/런타임 분석 도구를 담당한다. Luo는 중국 베이징에 있는 베이징 대학교에서 소프트웨어 엔지니어링 분야 석사학위를 받았다.

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

