| <?php |
| /******************************************************************************* |
| * Copyright (c) 2015 Eclipse Foundation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eric Poirier (Eclipse Foundation) - Initial implementation |
| *******************************************************************************/ |
| ?> |
| |
| <h1 class="article-title"><?php echo $pageTitle; ?></h1> |
| <p> |
| In the previous parts of this tutorial series we described <a |
| href="http://eclipsesource.com/blogs/2012/05/10/eclipse-4-final-sprint-part-1-the-e4-application-model/">how |
| to create an application model</a>, <a |
| href="http://eclipsesource.com/blogs/2012/06/12/eclipse-4-e4-tutorial-part-2/">link |
| those elements to implementations</a>, how to <a |
| href="http://eclipsesource.com/blogs/2012/06/26/eclipse-4-e4-tutorial-part-3-extending-the-application-model/">extend |
| the application model</a> and <a |
| href="http://eclipsesource.com/blogs/tutorials/eclipse-4-e4-tutorial-part-4-dependency-injection-basics/">details |
| about dependency injection</a> . All parts of this tutorial are |
| available now as a <a title="Eclipse 4 Tutorial" |
| href="http://eclipsesource.com/eclipse4tutorial">downloadable |
| PDF</a>.<br> This tutorial describes how to do a soft migration |
| to the Eclipse 4 (e4) programming model. The basic goal of the |
| tutorial is to enable development using the new concepts such as |
| Dependency Injection and Annotations, but without first requiring |
| a complete application migration. Therefore, all existing plugins |
| and frameworks which require 3.x, can still be used as before. |
| However, developing new UI components for an application following |
| the e4 programming model has two major advantages: |
| </p> |
| <p> |
| 1. The new components are POJOs and therefore very flexible, |
| testable and re-usable.<br> 2. If the application is migrated to |
| the Eclipse 4 Application Platform, these components are ready to |
| be used in e4. |
| </p> |
| <p>Interestingly, the first point is worth taking advantage of, even |
| if you are sure that Eclipse 4 will not be an option in the near |
| future. The idea is actually pretty simple and isn’t really new at |
| all.</p> |
| <h2>POJOs in 3x</h2> |
| <p> |
| The basic concept is to make a clear separation between the code |
| that you develop for a custom application and the code that binds |
| your component into the Eclipse workbench. The second group of |
| code depends on the workbench API and is therefore specific to a |
| certain Eclipse version, i.e. 3.x or 4.x. The first group of code |
| does not need to be specific to an Eclipse version and in fact, |
| doesn’t need to know about the workbench at all.<br> <a |
| href="http://eclipsesource.com/blogs/wp-content/uploads/2012/11/wrapper.png"><img |
| class="aligncenter size-medium wp-image-12612" title="wrapper" |
| src="http://eclipsesource.com/blogs/wp-content/uploads/2012/11/wrapper-300x159.png" |
| alt="wrapper 300x159 Eclipse 4 (e4) Tutorial Soft migration from 3.x to Eclipse 4 (e4)" |
| height="159" width="300"></a><br> A good example for the |
| separation is the implementation of a handler. To implement a |
| handler in Eclipse 3.x that is bound to a command, you need to |
| implement the interface IHandler. Let’s look at a typical example |
| handler in 3.x, which does something with the current selection. |
| In this example the handler checks if the current selection is of |
| type “MailAccount”. If this is true, the handler checks if the |
| user is already logged in and then sends and receives mails. |
| </p> |
| |
| <div class="wp_syntax"> |
| <table> |
| <tbody> |
| <tr> |
| <td class="code"><pre class="java" |
| style="font-family: monospace;"> |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #003399;">Object</span> execute<span |
| style="color: #009900;">(</span>ExecutionEvent event<span |
| style="color: #009900;">)</span> <span |
| style="color: #000000; font-weight: bold;">throws</span> ExecutionException <span |
| style="color: #009900;">{</span> |
| ISelection currentSelection <span style="color: #339933;">=</span> HandlerUtil.<span |
| style="color: #006633;">getCurrentSelection</span><span |
| style="color: #009900;">(</span>event<span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #000000; font-weight: bold;">if</span> <span |
| style="color: #009900;">(</span>currentSelection <span |
| style="color: #000000; font-weight: bold;">instanceof</span> IStructuredSelection<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| <span style="color: #003399;">Object</span> firstElement <span |
| style="color: #339933;">=</span> <span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">(</span>IStructuredSelection<span |
| style="color: #009900;">)</span> currentSelection<span |
| style="color: #009900;">)</span> |
| .<span style="color: #006633;">getFirstElement</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #000000; font-weight: bold;">if</span> <span |
| style="color: #009900;">(</span>firstElement <span |
| style="color: #000000; font-weight: bold;">instanceof</span> MailAccount<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| MailAccount account <span style="color: #339933;">=</span> <span |
| style="color: #009900;">(</span>MailAccount<span |
| style="color: #009900;">)</span> firstElement<span |
| style="color: #339933;">;</span> |
| <span style="color: #000000; font-weight: bold;">if</span><span |
| style="color: #009900;">(</span><span |
| style="color: #339933;">!</span>account.<span |
| style="color: #006633;">isLoggedIn</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">{</span> |
| account.<span style="color: #006633;">logIn</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| account.<span style="color: #006633;">sendMails</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| account.<span style="color: #006633;">recieveMails</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| <span style="color: #009900;">}</span> |
| |
| <span style="color: #000000; font-weight: bold;">return</span> <span |
| style="color: #000066; font-weight: bold;">null</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| </pre></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <p> |
| There are three major problems with this design: boilerplate code, |
| lack of testability and lack of re-usability. Let’s imagine that |
| you would like to write a test case for this handler. You need to |
| manually create an ExecutionEvent and also make sure that the |
| HandlerUtil is available in your test environment. As the |
| selection in this case is not a plain field, but a property, you |
| would need to look at the implementation of |
| HandlerUtil.getCurrentSelection() to find out how to properly |
| prepare your Mock ExecutionEvent. In the last section, you have |
| more lines of boilerplate code in the test case. Even if you |
| manage to create a test case, let’s imagine you want to trigger a |
| timer-based mail synchronization, meaning that you want to |
| directly call the execute method. In order to re-use the handler, |
| you would need to create an ExecutionEvent. If the handler is |
| within your control, you will probably refactor at this time. But |
| the handler might be within a framework where you cannot refactor.<br> |
| The solution for this is pretty simple: we split the code into two |
| methods. The first deals with all workbench specific parts, i.e. |
| unpacking the selection. The second method executes the business |
| logic itself and can, as in this case, be static. |
| </p> |
| |
| <div class="wp_syntax"> |
| <table> |
| <tbody> |
| <tr> |
| <td class="code"><pre class="java" |
| style="font-family: monospace;"> |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #003399;">Object</span> execute<span |
| style="color: #009900;">(</span>ExecutionEvent event<span |
| style="color: #009900;">)</span> <span |
| style="color: #000000; font-weight: bold;">throws</span> ExecutionException <span |
| style="color: #009900;">{</span> |
| ISelection currentSelection <span style="color: #339933;">=</span> HandlerUtil.<span |
| style="color: #006633;">getCurrentSelection</span><span |
| style="color: #009900;">(</span>event<span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #000000; font-weight: bold;">if</span> <span |
| style="color: #009900;">(</span>currentSelection <span |
| style="color: #000000; font-weight: bold;">instanceof</span> IStructuredSelection<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| <span style="color: #003399;">Object</span> firstElement <span |
| style="color: #339933;">=</span> <span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">(</span>IStructuredSelection<span |
| style="color: #009900;">)</span> currentSelection<span |
| style="color: #009900;">)</span> |
| .<span style="color: #006633;">getFirstElement</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #000000; font-weight: bold;">if</span> <span |
| style="color: #009900;">(</span>firstElement <span |
| style="color: #000000; font-weight: bold;">instanceof</span> MailAccount<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| synchronizeAccount<span style="color: #009900;">(</span><span |
| style="color: #009900;">(</span>MailAccount<span |
| style="color: #009900;">)</span> firstElement<span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| <span style="color: #009900;">}</span> |
| |
| <span style="color: #000000; font-weight: bold;">return</span> <span |
| style="color: #000066; font-weight: bold;">null</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000000; font-weight: bold;">static</span> <span |
| style="color: #000066; font-weight: bold;">void</span> synchronizeAccount<span |
| style="color: #009900;">(</span>MailAccount account<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">if</span><span |
| style="color: #009900;">(</span><span |
| style="color: #339933;">!</span>account.<span |
| style="color: #006633;">isLoggedIn</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">{</span> |
| account.<span style="color: #006633;">logIn</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| account.<span style="color: #006633;">sendMails</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| account.<span style="color: #006633;">recieveMails</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| </pre></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <p> |
| With this design it is much easier to write a test case for the |
| second method. Additionally, the method can be easily called from |
| anywhere else, e.g. triggering the timer-based synchronization. |
| Finally, the code is easier to understand. As a next step, the |
| second method can be moved out of the handler, for example, into a |
| plugin which does not have any workbench dependencies.<br> |
| Applying the same design pattern to views results in the same |
| advantages. We have one class implementing the workbench specific |
| parts and one class which can be a POJO. In the following example |
| the WorkbenchView does all workbench specific parts, including |
| handling the current selection, while the POJOView is completely |
| independent. |
| </p> |
| |
| <div class="wp_syntax"> |
| <table> |
| <tbody> |
| <tr> |
| <td class="code"><pre class="java" |
| style="font-family: monospace;"> |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000000; font-weight: bold;">class</span> WorkbenchView <span |
| style="color: #000000; font-weight: bold;">extends</span> ViewPart <span |
| style="color: #009900;">{</span> |
| |
| <span style="color: #000000; font-weight: bold;">private</span> POJOView pojoView<span |
| style="color: #339933;">;</span> |
| |
| <span style="color: #000000; font-weight: bold;">public</span> WorkbenchView<span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| pojoView <span style="color: #339933;">=</span> <span |
| style="color: #000000; font-weight: bold;">new</span> POJOView<span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| |
| @Override |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000066; font-weight: bold;">void</span> createPartControl<span |
| style="color: #009900;">(</span><span |
| style="color: #003399;">Composite</span> parent<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| pojoView.<span style="color: #006633;">createPartControl</span><span |
| style="color: #009900;">(</span>parent<span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| ISelectionService service <span style="color: #339933;">=</span> <span |
| style="color: #009900;">(</span>ISelectionService<span |
| style="color: #009900;">)</span> getSite<span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span>.<span |
| style="color: #006633;">getService</span><span |
| style="color: #009900;">(</span> |
| ISelectionService.<span style="color: #000000; font-weight: bold;">class</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| service.<span style="color: #006633;">addSelectionListener</span><span |
| style="color: #009900;">(</span><span |
| style="color: #000000; font-weight: bold;">new</span> ISelectionListener<span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| |
| @Override |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000066; font-weight: bold;">void</span> selectionChanged<span |
| style="color: #009900;">(</span>IWorkbenchPart part, |
| ISelection selection<span style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">if</span> <span |
| style="color: #009900;">(</span>selection <span |
| style="color: #000000; font-weight: bold;">instanceof</span> IStructuredSelection<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| <span style="color: #003399;">Object</span> firstElement <span |
| style="color: #339933;">=</span> <span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">(</span>IStructuredSelection<span |
| style="color: #009900;">)</span> selection<span |
| style="color: #009900;">)</span> |
| .<span style="color: #006633;">getFirstElement</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| pojoView.<span style="color: #006633;">setInput</span><span |
| style="color: #009900;">(</span>firstElement<span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| |
| <span style="color: #009900;">}</span> |
| <span style="color: #009900;">}</span> |
| <span style="color: #009900;">}</span><span style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| |
| <span style="color: #009900;">}</span> |
| |
| @Override |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000066; font-weight: bold;">void</span> setFocus<span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| pojoView.<span style="color: #006633;">setFocus</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| |
| <span style="color: #009900;">}</span> |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000000; font-weight: bold;">class</span> POJOView <span |
| style="color: #009900;">{</span> |
| |
| <span style="color: #000000; font-weight: bold;">private</span> Text text<span |
| style="color: #339933;">;</span> |
| |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000066; font-weight: bold;">void</span> createPartControl<span |
| style="color: #009900;">(</span><span |
| style="color: #003399;">Composite</span> parent<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| text <span style="color: #339933;">=</span> <span |
| style="color: #000000; font-weight: bold;">new</span> Text<span |
| style="color: #009900;">(</span>parent, SWT.<span |
| style="color: #006633;">NONE</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000066; font-weight: bold;">void</span> setFocus<span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| text.<span style="color: #006633;">setFocus</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| |
| <span style="color: #009900;">}</span> |
| |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000066; font-weight: bold;">void</span> setInput<span |
| style="color: #009900;">(</span><span |
| style="color: #003399;">Object</span> object<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">if</span><span |
| style="color: #009900;">(</span>object<span |
| style="color: #339933;">!=</span><span |
| style="color: #000066; font-weight: bold;">null</span><span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">{</span> |
| text.<span style="color: #006633;">setText</span><span |
| style="color: #009900;">(</span>object.<span |
| style="color: #006633;">toString</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| <span style="color: #009900;">}</span> |
| |
| <span style="color: #009900;">}</span> |
| </pre></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <p>Again the POJOView is now very easy to understand, test and |
| re-use. As an example, the POJOView could be embedded into a JFace |
| Wizard. Until this point, we have not used any Eclipse 4 specific |
| concepts; the pattern can be used in plain 3.x. As the wrapper |
| classes (the one which implements the 3.x interface) always look |
| pretty similar, it would be easy to provide a few generic |
| implementations. In the next section we introduce such a generic |
| implementation that uses dependency injection.</p> |
| <h2>Dependency Injection in 3.x</h2> |
| <p>If you separate workbench specific code and custom components as |
| POJOs, components are easier to re-use and to test, even in 3.x. |
| However, there are still two disadvantages compared to developing |
| a component for the Eclipse 4 Application Platform:</p> |
| <p> |
| 1. The wrapper has to be manually implemented and registered via |
| an extension point.<br> 2. The implementation of the component |
| cannot use dependency injection and is therefore not ready to be |
| used in Eclipse 4. |
| </p> |
| <p>Once your application is running on an Eclipse 4.x version there |
| is a solution for this, even if you still use the 3.x API. The |
| solution is provided by the 3.x e4 bridge from the e4 tools |
| project, developed by Tom Schindl. The plugin basically provides |
| generic wrapper classes, which can be used in a 3.x application. |
| The wrapper classes allow the definition of a second class which |
| is a POJO, and implements the corresponding component. The |
| solution follows the same pattern we describe before, but works in |
| a generic way and supports dependency injection. At writing, |
| implementations for Views and Editors are available. To create the |
| 3.x workbench wrapper, one simply inherits from the respective |
| type, e.g. from DIViewPart to implement a View. The wrapper class |
| is almost empty. It only has to specify the POJO class that |
| implements the component.</p> |
| |
| <div class="wp_syntax"> |
| <table> |
| <tbody> |
| <tr> |
| <td class="code"><pre class="java" |
| style="font-family: monospace;"> |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000000; font-weight: bold;">class</span> ExampleViewWrapper <span |
| style="color: #000000; font-weight: bold;">extends</span> DIViewPart<span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">public</span> ExampleViewWrapper<span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">super</span><span |
| style="color: #009900;">(</span>ExampleView.<span |
| style="color: #000000; font-weight: bold;">class</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| <span style="color: #009900;">}</span> |
| </pre></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <p>This class is now registered using the view’s extension point as |
| is usual in 3.x.</p> |
| <p>The implementation of the view itself can be a POJO and |
| dependency injection can therefore be used. In addition to being |
| quite convenient to program today, in case the component is |
| migrated to e4, it is ready to be used without any adaptation. In |
| this case, you can remove the wrapper and the extension and |
| integrate the POJOView into the application model. As you can see, |
| the view can use all features of dependency injection, including |
| injection into the current selection.</p> |
| |
| <div class="wp_syntax"> |
| <table> |
| <tbody> |
| <tr> |
| <td class="code"><pre class="java" |
| style="font-family: monospace;"> |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000000; font-weight: bold;">class</span> ExampleView <span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">private</span> <span |
| style="color: #003399;">Label</span> label<span |
| style="color: #339933;">;</span> |
| @Inject |
| <span style="color: #000000; font-weight: bold;">public</span> ExampleView<span |
| style="color: #009900;">(</span><span |
| style="color: #003399;">Composite</span> parent<span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">{</span> |
| label <span style="color: #339933;">=</span> <span |
| style="color: #000000; font-weight: bold;">new</span> <span |
| style="color: #003399;">Label</span><span |
| style="color: #009900;">(</span>parent, SWT.<span |
| style="color: #006633;">NONE</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| label.<span style="color: #006633;">setText</span><span |
| style="color: #009900;">(</span><span |
| style="color: #0000ff;">"Hello World"</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| |
| @Inject |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000066; font-weight: bold;">void</span> setInput<span |
| style="color: #009900;">(</span>@Optional @Named<span |
| style="color: #009900;">(</span>IServiceConstants.<span |
| style="color: #006633;">ACTIVE_SELECTION</span><span |
| style="color: #009900;">)</span><span |
| style="color: #003399;">Object</span> input<span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">if</span><span |
| style="color: #009900;">(</span>input<span |
| style="color: #339933;">==</span><span |
| style="color: #000066; font-weight: bold;">null</span><span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">return</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| label.<span style="color: #006633;">setText</span><span |
| style="color: #009900;">(</span>input.<span |
| style="color: #006633;">toString</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| <span style="color: #009900;">}</span> |
| </pre></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <p> |
| To understand how this works, we look at the simplest case, a |
| wrapper for a Handler, <a |
| href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=394341">which |
| I recently contributed</a>. To simplify the example, we will |
| ignore the annotation @CanEnable for now. The DIHandler needs to |
| implement the 3.x IHandler interface allowing it to be registered |
| with the handler extension point, as is common in 3.x. |
| Additionally, the DIHandler needs to know about the POJO class it |
| wraps. This POJO class should be instantiated by the wrapper. To |
| do this, we use the e4 ContextInjectionFactory. As the application |
| is running on the compatibility layer, we can retrieve the |
| EclipseContext as a service and use it to create the class. This |
| way all fields expected by the Handler are being injected (as is |
| standard in e4). |
| </p> |
| |
| <div class="wp_syntax"> |
| <table> |
| <tbody> |
| <tr> |
| <td class="code"><pre class="java" |
| style="font-family: monospace;"> |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #000000; font-weight: bold;">class</span> DIHandler <span |
| style="color: #000000; font-weight: bold;">extends</span> AbstractHandler <span |
| style="color: #009900;">{</span> |
| |
| <span style="color: #000000; font-weight: bold;">private</span> Classclazz<span |
| style="color: #339933;">;</span> |
| <span style="color: #000000; font-weight: bold;">private</span> C component<span |
| style="color: #339933;">;</span> |
| |
| <span style="color: #000000; font-weight: bold;">public</span> DIHandler<span |
| style="color: #009900;">(</span>Classclazz<span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">this</span>.<span |
| style="color: #006633;">clazz</span> <span |
| style="color: #339933;">=</span> clazz<span |
| style="color: #339933;">;</span> |
| IEclipseContext context <span style="color: #339933;">=</span> getActiveContext<span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| component <span style="color: #339933;">=</span> ContextInjectionFactory.<span |
| style="color: #006633;">make</span><span |
| style="color: #009900;">(</span>clazz, context<span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| <span style="color: #000000; font-weight: bold;">private</span> <span |
| style="color: #000000; font-weight: bold;">static</span> IEclipseContext getActiveContext<span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span> <span |
| style="color: #009900;">{</span> |
| IEclipseContext parentContext <span style="color: #339933;">=</span> <span |
| style="color: #009900;">(</span>IEclipseContext<span |
| style="color: #009900;">)</span> PlatformUI.<span |
| style="color: #006633;">getWorkbench</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span>.<span |
| style="color: #006633;">getService</span><span |
| style="color: #009900;">(</span> |
| IEclipseContext.<span style="color: #000000; font-weight: bold;">class</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #000000; font-weight: bold;">return</span> parentContext.<span |
| style="color: #006633;">getActiveLeaf</span><span |
| style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| </pre></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <p>The only missing piece now is the implementation of the execute |
| method. It simply uses the InjectionFactory again to invoke the |
| method of the POJO, which is marked with @Execute:</p> |
| |
| <div class="wp_syntax"> |
| <table> |
| <tbody> |
| <tr> |
| <td class="code"><pre class="java" |
| style="font-family: monospace;"> |
| <span style="color: #000000; font-weight: bold;">public</span> <span |
| style="color: #003399;">Object</span> execute<span |
| style="color: #009900;">(</span>ExecutionEvent event<span |
| style="color: #009900;">)</span> <span |
| style="color: #000000; font-weight: bold;">throws</span> ExecutionException <span |
| style="color: #009900;">{</span> |
| <span style="color: #000000; font-weight: bold;">return</span> ContextInjectionFactory.<span |
| style="color: #006633;">invoke</span><span |
| style="color: #009900;">(</span>component, Execute.<span |
| style="color: #000000; font-weight: bold;">class</span>, |
| getActiveContext<span style="color: #009900;">(</span><span |
| style="color: #009900;">)</span><span |
| style="color: #009900;">)</span><span |
| style="color: #339933;">;</span> |
| <span style="color: #009900;">}</span> |
| </pre></td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <p>This DIHandler is not very complex and allows wrapping POJO |
| handlers into the 3.x workbench.</p> |
| <h2>Conclusion</h2> |
| <p>This tutorial described an approach for a soft migration from 3.x |
| to the Eclipse 4 programming model. We started with the concept of |
| separating the implementation of custom UI components and |
| workbench specific classes. This improved the re-usability and the |
| testability of the components. Using the bridge plugin, the e4 |
| tools wrapper classes didn’t have to be implemented manually. |
| Additionally the DIWrapper enabled the use of dependency injection |
| even when programming in 3.x. Components developed in this way can |
| be integrated without any adaptations, into any pure e4 |
| application.</p> |
| <p> |
| This tutorial and all other parts of the series are available as a |
| <a title="Eclipse 4 Tutorial" |
| href="http://eclipsesource.com/eclipse4tutorial">downloadable |
| PDF</a>. |
| </p> |
| <p> |
| For more information, contact us:<br> Jonas Helming and Maximilian |
| Koegel<br> <a href="http://eclipsesource.com/munich">EclipseSource |
| Munich</a> leads |
| </p> |
| |
| |
| <div class="bottomitem"> |
| <h3>About the Authors</h3> |
| |
| <div class="row"> |
| <div class="col-sm-12"> |
| <div class="row"> |
| <div class="col-sm-8"> |
| <img class="author-picture" |
| src="/community/eclipse_newsletter/2013/february/images/jhelming.jpg" |
| alt="Jonas Helming" /> |
| </div> |
| <div class="col-sm-16"> |
| <p class="author-name"> |
| Jonas Helming <br /> |
| <a href="http://eclipsesource.com/">EclipseSource</a> |
| </p> |
| <ul class="author-link"> |
| <li><a href="http://eclipsesource.com/blogs/author/jhelming/">Blog</a> |
| </li> |
| <li><a href="https://twitter.com/JonasHelming">Twitter</a></li> |
| <li><a href="<?php echo $original_url; ?>">Original Article</a></li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="col-sm-12"> |
| <div class="row"> |
| <div class="col-sm-8"> |
| <img class="author-picture" |
| src="/community/eclipse_newsletter/2013/february/images/mjoegel.jpg" |
| alt="Maximilian Koegel" /> |
| </div> |
| <div class="col-sm-16"> |
| <p class="author-name"> |
| Maximilian Koegel <br /> |
| <a href="http://eclipsesource.com/">EclipseSource</a> |
| </p> |
| <ul class="author-link"> |
| <li><a href="http://eclipsesource.com/blogs/author/mkoegel/">Blog</a> |
| </li> |
| <li><a href="https://twitter.com/MKoegel">Twitter</a></li> |
| <?php echo $og; ?> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |