RAP を使用して RCP アプリケーションを Web アプリケーションに変換する

わずかな変更でマイグレーションする

RCP (Rich Client Platform) はリッチなデスクトップ・アプリケーションを構築するためのプラットフォームです。一方、RAP (Rich Ajax Platform) では Eclipse 開発モデルを使って Ajax 対応の Web アプリケーションを構築することができます。この RAP の助けを借りれば、ほんのわずかな変更を加えるだけで、既存の RCP アプリケーションを Web アプリケーションとして実行できるようになります。この記事では、RAP の主要な機能を詳しく探り、単純な HTML ビューアーのコードを例に、RAP を使って RCP アプリケーションを Web にマイグレートする方法を説明します。

Zhi Da Luo, Software Engineer, IBM China

Zhi Luo photoZhi Da Luo は、IBM China Development Lab の Emerging Technology Institute に勤務するソフトウェア・エンジニアです。彼は 2008年に IBM に入社しました。プログラム分析、バイトコード・インスツルメンテーション、Java 並行プログラムで経験を積んだ彼は、現在、Java 並列ソフトウェアの静的/ランタイム分析ツールに取り組んでいます。彼は、中国・北京の Peking University でソフトウェア・エンジニアリングの修士号を取得しました。



Wei Liu, Software Engineer, IBM

Wei Liu photoWei Liu は、IBM China Development Lab の Emerging Technology Institute に勤務するソフトウェア・エンジニアです。北京大学でソフトウェア・エンジニアリングの修士号を取得した彼は、2010年に IBM に入社し、Eclipse RCP および RAP、Java 並行性プログラミング、および動的プログラム分析で経験を積んでいます。



Ming Hai Wang, Software Engineer, iSoftStone

Ming Hai Wang photoMing Hai Wang は、プラグイン、RCP、および RAP 開発を得意とするソフトウェア・エンジニアで、これまで 2 年以上、RCP 開発に携わっています。また、Java 対応の Multicore Software Development Kit での場合をはじめ、RCP から RAP へのプラグインのマイグレーションでも経験を積んでいます。現在は、z/OS の調査に多くの時間を費やしています。



Raja Das, Software Architect, IBM

Raja Das photoRaja Das は、IBM Software Group のソフトウェア・アーキテクトです。現在は、マルチコア/複数コア・システムを対象としたライブラリーおよびフレームワークを専門としています。以前は WebSphere Partner Gateway の製品アーキテクトでした。Dr. Das は、プログラミング言語、並列ソフトウェアおよびシステムなどに興味を持っています。



2011年 4月 19日

はじめに

Eclipse RCP (Rich Client Platform) を使用すると、アプリケーションを構築することができます。RCP では動的なプラグイン・モデルをベースにリッチなアプリケーションを構築し、共通のツールキットと拡張ポイントを使って UI を作成します。Eclipse RCP は、オープン・ツールの開発で広く用いられています。

RAP (Rich Ajax Platform) プロジェクトでは、Eclipse 開発モデル、プラグイン、そして Java のみの API を使って Ajax 対応のリッチな Web アプリケーションを構築することができます。RAP の目的は、最小限の変更を加えるだけで、RCP アプリケーションを Web ブラウザーで実行できるようにすることです。

RAP と RCP のインターフェースは共通していますが、それぞれがベースとしている実装は大きく異なります。RAP は SWT API の代わりとして、Tomcat のようなサーブレット・コンテナーで稼働する RWT を実装します。クライアントが RWT にアクセスするには、Internet Explorer や Chrome などの標準 Web ブラウザーを使用することができます。

RAP アプリケーションと RCP アプリケーションとでは、これらのアプリケーションが使用されるユーザー環境にも違いがあります。デスクトップ・アプリケーションである RCP は、一度に 1 人のユーザーしか使用することができません。その一方、RAP アプリケーションは Web ベースのプログラムであり、複数のユーザーが同時にアクセスすることができます。RAP がベースとする Equinox は、サーバー・サイドの OSGi およびランタイム・バンドルです。Web アプリケーションごとに 1 つの OSGi インスタンスが、アプリケーションのスコープで実行されます。RCP とは対照的に、RAP はユーザー・セッションと、ユーザー・セッション間で共有されるバンドルを扱わなければなりません。

この記事では RAP の主要な機能を紹介し、RAP を使って RCP アプリケーションを Web にマイグレーションする方法を説明します。記事で使用するサンプル・ソース・コードは、ここからダウンロードすることができます。

RAP と RCP のシングル・ソーシング手法

RAP は、単一のコード・ベースからリッチ・クライアント・アプリケーションおよび Web アプリケーションの両方を開発できることで人気を得ています。シングル・ソーシングとも呼ばれるこの開発手法では、既存の RCP 開発のスキルとコード・ベースを Web ベースの 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 イベント、FileDialog などです。RAP は Web 特有の要件に対処しなければならないことから、PhaseListenerISessionStore などの RAP 独自の API もあります。異なる API に対処するには、以下の推奨案を検討してください。
    • 問題となるインターフェースをホスト・プラグインに定義します。
    • 問題となるインターフェースを異なるフラグメントに実装する新しいクラスを定義し、それぞれのプラットフォームに応じた方法で問題を解決します。
    • プラットフォームに固有の実装を Java リフレクションによって実行時にロードします。

    サンプル・ソース・コードは、「シングル・ソーシングの例」のセクションに記載します。

  • UI ライブラリー: RCP と RAP がターゲットとするプラットフォームは異なるため、それぞれが利用する UI ライブラリーも異なります。RCP と RAP に共通のコードが含まれるホスト・プラグインには、両方のプラットフォームの UI ライブラリーへの依存関係が必要です。例えば、RCP 用の org.eclipse.ui プラグインと RAP 用の org.eclipse.rap.ui プラグインは、両方ともホストの必須プラグインとしてインポートしなければなりません。

    異なるターゲット・ランタイムを使用する場合には、コンパイル時のエラーを防ぐために、「Properties (プロパティー)」の下にある「Optional (オプション)」チェック・ボックスを有効にします (図 1 を参照)。このようにすることで、RAP/RCP ランタイムは実行を開始する際に適切なライブラリーをロードします。

    図 1. オプションの依存関係
    オプションの依存関係
  • 拡張ポイント (E-P): 現時点では、RCP の E-P のなかには RAP で使用できないものもあります (bindingshelpSupportなど)。Web 特有の要件により、RAP には entrypoint および themes などの E-P が追加されています。

    E-P の違いに対処して RCP と RAP に同じコード・ベースを使用できるようにするために、OSGi フラグメントが導入されました。フラグメントとは、別のバンドルを拡張する特殊な OSGi バンドルのことです。これらの拡張バンドルは、実行時にマージすることができます。それにはまず、RCP と RAP に共通のコードを収容するホスト・プラグインを定義します。次に、RAP と RCP ごとに別個のフラグメントを作成し、そこに RAP と RCP それぞれのプラットフォーム固有のコードを収容します。実行時には、該当するどちらか一方のフラグメント (RAP または RCP) だけが、ホスト・プラグインと一緒にインストールされるため、該当するフラグメントにプラットフォーム固有の E-P 拡張を移すことができます。こうすれば、バンドルの構造は手付かずのままになります。

  • マルチユーザー環境: RCP ではシングルトン・パターンが広く使用されています。ただし、複数のユーザーが同時にアクセスできる Web ベースのアプリケーションには、セッション・ベースのシングルトン・パターンが必要となります。そこで 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 ファイルを表示するビューがあり、このビューのツールバーの「Open (開く)」ボタンを使って HTML ファイルを開くことができます (図 2 を参照)。

図 2. RCP HTML ビューアーの例
RCP HTML ビューアーの例を示すスクリーン・ショット。「Open (開く)」ボタンが赤い丸で囲われています。

サンプルでは、ブラウザー・ウィジェットを使用して HTML ファイルを表示します。この機能を実装するためには、com.ibm.msdk.example という名前のサンプル・プラグインを作成する必要があります。

  1. RCP プラットフォームに固有のコードを識別します。

    前述のとおり、サンプル・プラグインには RAP/RCP プラットフォームに固有のコードが含まれています。まずは、サンプル・プロジェクトから共通コードを抽出してください。共通コードを分析することで、RAP ではサポートしていない RCP HTML ビューアーの API、つまり (com.ibm.msdk.example.action パッケージに含まれる) FileDialog#open が見つかります (リスト 2 を参照)。

    リスト 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 プラットフォームの両方をターゲットとするため、「必須プラグイン」としては、この 2 つのプラットフォームに必要なバンドルをインポートしなければなりません。例えば UI バンドルとしては、org.eclipse.ui (RCP) と org.eclipse.rap.ui (RAP) の両方が必要です。ターゲット・プラットフォームの違いによるコンパイル・エラーが発生しないようにするには、プラグインの「Properties (プロパティー)」で、異なる UI バンドルの依存関係を「Optional (オプション)」として指定します (図 3 を参照)。

    図 3. オプション依存関係
    オプション依存関係

    これで、プラットフォーム・ランタイム環境 (RCP または RAP) は適切なバンドルをロードすることになります。ターゲット・プラットフォームは 2 つあるため、それぞれのプラットフォーム固有のコードを収容する 2 つのフラグメントを新規に作成しなければなりません。これらのフラグメントのホスト・プラグインのプロパティーは、図 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.fileupload および org.apache.commons.io プラグインが必要です。この 2 つはどちらもリポジトリー・ロケーションの URL、pserver:anonymous@dev.eclipse.org:/cvsroot/tools からダウンロードすることができます。これらのプラグインは、org.eclipse.orbit/ にあります。CVS をダウンロードに使用する方法についての詳細は、「参考文献」を参照してください。

    1. 必要なプラグインを RAP フラグメントに追加します (図 5 を参照)。
      図 5. アップロード・プラグインを依存関係に追加する
      アップロード・プラグインを依存関係に追加する
    2. ホスト・プラグイン内には、RAP プラットフォームと RCP プラットフォームとの間で共通していない特殊な関数を扱うための抽象クラスを作成する必要があります。そこで、doViewHtml() という名前の抽象メソッドを定義します (リスト 3 を参照)。
      リスト 3. Action の抽象クラス
      /**
       * 
       */
      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() {
      		doViewHtml();
      	}
      
      	/**
      	 * 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);
      	}	
      	...
      }

      新しいフラグメントのアクションを取得するには、com.ibm.msdk.example プラグインの HtmlContentsView.java で Java リフレクションを使用します (リスト 5 を参照)。すると、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 フラグメントに作成するのは、抽象クラス AbstractViewHtmlAction を継承する新規クラスです (リスト 6 を参照)。この新規クラスにより、FileDialog で HTML ファイルを開くための抽象メソッドを実装します。

    リスト 6. RCP での AbstractViewHtmlAction の実装
    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 とは異なります。RAP の場合には、「アップロード」ウィジェットによって HTML ファイルを Web サーバーに転送してから、ファイルを開きます (リスト 7 を参照)。

    リスト 7. RAP での AbstractViewHtmlAction の実装
    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 ファイルの作成方法が示されています。作成した WAR ファイルを変更すれば、この RAP デモ・フィーチャー・プロジェクトをサンプル HTML ビューアーで使用できるようになります。

  1. オンライン・バージョンの RAP Developer Guide の記述 (RAP Developer Guide を「Advanced Topics」 > 「WAR Deployment」の順に展開すると表示されるページの記述) に従って、チーム・プロジェクト・セット・ファイルをダウンロードします (「参考文献」にリンクを記載)。
  2. Eclipse で「File (ファイル)」 > 「Import (インポート)」 > 「Team Project Set (チーム・プロジェクト・セット)」の順に選択し、ダウンロードしたファイルの場所を入力します。
  3. Finish (完了)」をクリックします。これで、必要なプロジェクトが CVS からインポートされます。インポートされるプロジェクトには、org.eclipse.equinox.http.servletbridge、org.eclipse.equinox.servletbridge、org.eclipse.rap.demo.feature があります。
  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. フィーチャーの ID を com.ibm.msdk.example.rap.feature に変更します (図 6 を参照)。
    図 6. HTML ビューアーのフィーチャー
    HTML ビューアーのフィーチャー
  6. 以下の手順に従って、HTML ビューアー RAP アプリケーション全体をビルドする Ant タスクを構成して実行します。
    1. 「webappBuilder.xml」を開き、プロパティーの値 (27 行目) を「com.ibm.msdk.example.rap.feature」に変更します。
    2. 「webappBuilder.xml」を右クリックして、「External Tools Dialog (外部ツール・ダイアログ)」を開きます (「Run As (実行)」 > 「External Tools Configuration (外部ツールの構成)」)。
    3. Ant Build (Ant ビルド)」をダブルクリックします。
    4. 新規エントリー「com.ibm.msdk.example.rap.feature webappBuilder.xml」を選択します。
    5. 「JRE」タブで、「Runtime JRE (ランタイム JRE)」を「Run in the same JRE as the workspace (ワークスペースと同じ JRE で実行)」に設定します。このように設定しないと、スクリプトは PDE Ant タスクを使用してフィーチャーをエクスポートすることができません。
    6. Run (実行)」をクリックします。
    7. コンソールに「BUILD SUCCESSFUL (ビルド成功)」というメッセージが表示されるはずです。

    進行状況表示バーを見ると、PDE Export タスクがまだバックグラウンドで実行中であることがわかります。このタスクが完了するまで待ってください。

  7. 以下の手順に従って、config.ini ファイルを生成します。
    1. org.eclipse.rap.demo に含まれる ConfigIniCreator.java という Java ファイルを開き、39 行目をリスト 13 に示す内容に変更します。
      リスト 13. 変更後のコード
      File file = new File( "build\\demo\\WEB-INF\\eclipse\\plug-ins" )
    2. ConfigIniCreator を Java アプリケーションとして起動します (Eclipse コンソールにリスト 14 に示すようなテキストが出力されます)。
      リスト 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. 出力されたテキストをすべてコピーして、{プロジェクト・ルート}/templates/WEB-INF/eclipse/config.ini の既存の内容を置き換えます。
    4. すべての RAP フラグメント (com.ibm.msdk.example.rap) から @start を削除します。
    5. まず、{プロジェクト・ルート}/templates/WEB-INF/eclipse/config.ini を {プロジェクト・ルート}/build/demo/WEB-INF/eclipse/configuration/ にコピーして、既存のファイルを置き換えます。feature.xml が変更されている場合は、config.ini を生成し直す必要があります。
    6. com.ibm.msdk.example.rap.feature/script ディレクトリーに新規 build.xml を作成し、そのファイルに以下のスクリプトをコピーします。
      リスト 15. WAR ファイルをビルドするための ANT スクリプト
      <?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 (Ant ビルド)」として build.xml を実行します。すると HTML ビューアーの WAR ファイルとして、sample.war というファイルがプロジェクト・ルート・ディレクトリー内に生成されます (図 7 を参照)。
      図 7. Eclipse ワークスペース内の sample.war
      A sample.war in Eclipse workspace

ファイルを Tomcat にデプロイする

sample.war ファイルを Tomcat にデプロイするには、sample.war を {TOMCAT_HOME}/webapps/ にコピーします。そして Tomcat を起動し、http://localhost:8080/sample/msdkExample を指定して HTML ビューアーにアクセスします (図 8 を参照)。

図 8. sample.war を Tomcat にデプロイする
sample.war を Tomcat にデプロイする

デプロイした WAR ファイルが機能しない場合

RAP は開発時に機能していても、Tomcat や WebSphere にデプロイすると機能しなくなる場合があります。このような場合には、以下の点を確認してください。

  • RAP アプリケーションが build.properties ファイルを使用している場合、このファイルがエクスポートされていること、そして RAP アプリケーションで使用するすべてのライブラリーがプラグインのクラス・パスに記載されていることを確認します。
  • リスト 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>

    コンソールに「ss」と入力して (Tomcat の場合)、すべてのバンドルが起動されているかどうかを確認します。起動されていない場合は、「start <bundle-id>」を実行してバンドルを起動してみてください。何が欠けているかについては、スタック・トレースがヒントになる場合があります。ss による出力に、org.eclipse.equinox.servletbridge.extensionbundleRESOVLED 状態として含まれていることを確認します (図 9 を参照)。

    図 9. Tomcat で起動されているバンドル
    Tomcat で起動されているバンドル
  • WAR に以下のバンドルが含まれていないことを確認します。
    • javax.servlet バンドル。javax.servlet は、プラグイン・マニフェストの Require-Bundle セクションではなく、Import-Package セクションに記載されていなければなりません。
    • org.eclipse.update.configurator バンドル
    • *.jetty.* バンドル
  • WAR ファイルを再デプロイする場合は、サーブレット・エンジンの作業ディレクトリー (例えば、Tomcat の <tomcat_install>/work/Catalina/localhost/work/<webapp_name>) を必ず削除してください。

まとめ

この記事では、RAP および RCP アプリケーション開発のシングル・ソーシングの概念を紹介し、シングル・ソーシング手法を使って既存の RCP アプリケーションを Web ベースの RAP アプリケーションに変換する方法を説明しました。RAP は RCP 開発者にとって、既存のコード・ベースを再利用して Web ベースのアプリケーションを作成するための強力なツールとなります。記事ではまた、RAP アプリケーションを WAR ファイルにパッケージ化する方法、そして WAR ファイルを Web コンテナーにデプロイする方法についても説明しました。


ダウンロード

内容ファイル名サイズ
Project sampleworkspaceExample.zip57KB

参考文献

学ぶために

  • RAP (Rich Ajax Platform): Eclipse 開発モデル、Eclipse ワークベンチ拡張ポイントを使用するプラグイン、そして SWT API を備えたウィジェット・ツールキットを使用して、リッチな Ajax 対応 Web アプリケーションを構築する手段となる RAP の全容を読んでください。
  • RAP/FAQ (The Eclipse Foundation、2011年): RAP の FAQ を調べてください。
  • CVS Howto: Anonymous CVS (The Eclipse Foundation、2011年): CVS を使用してダウンロードする方法についての詳細を学んでください。
  • RAP Developer Guide: RAP 開発者向けガイドを読んでください。
  • Rich Ajax Platform、第 1 回: 概要」(developerWorks、2007年10月) および「Rich Ajax Platform, Part 2: Developing applications」(developerWorks、2007年12月): RAP の概要、主要な概念、そして RAP が提供する高度な機能を使用する方法を学んでください。

製品や技術を入手するために

  • RAP ツールと RAP ランタイム: RAP ツールおよび RAP ランタイムをダウンロードしてください。
  • Eclipse for RCP and RAP developers: RCP および RAP 開発者向け Eclipse をダウンロードして、Eclipse プラグイン、RCP+RAP (Rich Client or Rich Ajax Applications)、Mylyn、そして XML エディターを作成したい開発者向けのツール一式を入手してください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=660414
ArticleTitle=RAP を使用して RCP アプリケーションを Web アプリケーションに変換する
publish-date=04192011