public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { (...) @Override public void postStartup() { try { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); page.openEditor(new MyEditorInput("TutoGEF"), MyGraphicalEditor.ID, false); } catch (Exception e) { e.printStackTrace(); } } }チュートリアルでやりたいことは、サンプルコードから察するに、表示されたウィンドウにエディタクラスを割り当て、エディタに定義された内容を表示すること、である。そこで以下のように、
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { (...) public void postWindowOpen(){ try { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); page.openEditor(new MyEditorInput("TutoGEF"), MyGraphicalEditor.ID, false); } catch (Exception e) { e.printStackTrace(); } } }WorkbenchWindowAdvisorクラスを継承したApplicationWorkbenchWindowAdvisorクラスに、WorkbenchWindowAdvisorクラスのpostWindowOpenメソッドをオーバライドし、上記のtry〜catch節部分をまるごとコピーする。これにより、まったく同じコードであるにもかかわらず、NullPointerExceptionは発生しない。なお、エラーに関する詳細は以下の検討で詳細に記載する。
IWorkbench bench = PlatformUI.getWorkbench(); IWorkbenchWindow bw = bench.getActiveWorkbenchWindow(); IWorkbenchPage page = bw.getActivePage(); page.openEditor(new MyEditorInput("TutoGEF"), MyGraphicalEditor.ID, false);のように1メソッドずつ分解、最初の行にブレークポイントを張り、ステップオーバで戻り値を確認していった。その結果、bench.getActiveWorkbenchWindow()の戻り値がnullとなり、次の行でいわばnull.getActivePage()を実行しようとして、NullPointerExceptionが発生したのだろう。
public IWorkbenchWindow getActiveWorkbenchWindow() { // Return null if called from a non-UI thread. // This is not spec'ed behaviour and is misleading, however this is how // it // worked in 2.1 and we cannot change it now. // For more details, see [Bug 57384] [RCP] Main window not active on // startup if (Display.getCurrent() == null || !initializationDone) { return null; } // the source providers try to update again during shutdown if (windowsClosed) { return null; } // rendering engine not available, can't make workbench windows, see bug // 320932 if (e4Context.get(IPresentationEngine.class) == null) { return null; } MWindow activeWindow = application.getSelectedElement(); if (activeWindow == null && !application.getChildren().isEmpty()) { activeWindow = application.getChildren().get(0); } // We can't return a window with no widget...it's in the process // of closing...see Bug 379717 if (activeWindow != null && activeWindow.getWidget() == null) { return null; } return createWorkbenchWindow(getDefaultPageInput(), getPerspectiveRegistry() .findPerspectiveWithId(getPerspectiveRegistry().getDefaultPerspective()), activeWindow, false); }e4Context.get(IPresentationEngine.class)の戻り値がnullのためnullが返却されたところまでわかった。さらに、e4Context.get()やIPresentationEngine.classにステップインしてみたが、さっぱりわからない。get()しようとしているということは、これより以前のどこかのタイミングでsetするコードを通過している必要が有ることは想像に難くないものの、どこを探せばいいのかも分からない。キーワードはIPresentationEngineとe4ContextでEclipseのヘルプを中心に検索したが、まったくヒントが見当たらない。
public class ApplicationActionBarAdvisor extends ActionBarAdvisor { private NewAction newAction; public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) { super(configurer); } protected void makeActions(IWorkbenchWindow window) { newAction = new NewAction(); newAction.setWorkbenchWindow(window); } protected void fillMenuBar(IMenuManager menuBar) { } @Override protected void fillCoolBar(ICoolBarManager coolBar) { // クールバーの取得 ToolBarManager toolBar = new ToolBarManager(SWT.FLAT); // アクションの追加 toolBar.add(new Separator()); toolBar.add(newAction); toolBar.add(new Separator()); coolBar.add(toolBar); } }
public class NewAction extends Action { private IWorkbenchWindow workbenchWindow; public NewAction() { } public void dispose() { workbenchWindow = null; } public void run() { IWorkbenchPage page = workbenchWindow.getActivePage(); try { page.openEditor(new MyEditorInput("TutoGEF"), MyGraphicalEditor.ID, false); } catch (Exception e) { e.printStackTrace(); } } public void setWorkbenchWindow(IWorkbenchWindow window) { workbenchWindow = window; } }とあるように、ActionBarAdvisorクラスのmakeActionsメソッドの引数にあるIWorkbenchWindowのオブジェクトをnewAction.setWorkbenchWindow(window)でActionクラスの変数に記憶しておき、newActionのボタン押下時にIWorkbenchWindowのオブジェクトを使用して、エディタ画面を表示させるというものである。