| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml"> |
| <head> |
| <title>NetBeans Platform Quick Start for NetBeans Platform 6.5</title> |
| <link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"> |
| <meta name="AUDIENCE" content="NBUSER"> |
| <meta name="TYPE" content="ARTICLE"> |
| <meta name="EXPIRES" content="N"> |
| <meta name="developer" content="gwielenga@netbeans.org"> |
| <meta name="indexed" content="y"> |
| <meta name="description" |
| content="A short guide to getting started with the NetBeans Platform."> |
| </head> |
| <body> |
| |
| <h1>NetBeans Platform Quick Start</h1> |
| |
| <p>Welcome to the <a href="https://platform.netbeans.org/"><b>NetBeans Platform</b></a>! |
| |
| <p>The key benefit of the NetBeans Platform is its modular architecture. Secondary |
| benefits are the NetBeans Platform's reliance on the Swing UI toolkit, which is the |
| official toolkit for creating user interfaces in Java, in combination with the |
| NetBeans IDE's award winning "Matisse" GUI Builder. |
| |
| <p>In this quick start, you are introduced to the benefit and usage of modularity via |
| a very simple example, contributed by Thomas Würthinger, who is currently a |
| PhD student at the Johannes Kepler University in Linz, Austria. Once you have |
| grasped the concepts introduced in this quick start, you will be ready to |
| step onto the <a href="https://netbeans.org/kb/trails/platform.html">NetBeans Platform Learning Trail</a>, |
| providing a very rich variety of tutorials for many different scenarios |
| relating to the NetBeans Platform. |
| |
| <p class="tips"> If you are new to the NetBeans Platform, it is highly |
| recommended to watch the screencast series <a href="https://platform.netbeans.org/tutorials/nbm-10-top-apis.html">Top 10 NetBeans APIs</a>. |
| |
| <p><b>Contents</b></p> |
| <img src="../images/articles/67/netbeans-stamp6567.gif" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 6.5" title="Content on this page applies to NetBeans IDE 6.5"> </p> |
| <ul class="toc"> |
| <li><a href="#single">A Single Module NetBeans Platform Application</a></li> |
| <li><a href="#lookup">A Modular Application Using Lookup</a> |
| <li><a href="#listener">LookupListener and InstanceContent</a></li> |
| </ul> |
| |
| <p><b>To follow this tutorial, you need the software and resources listed in the following |
| table.</b></p> |
| |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td> |
| <td class="tbltd1">version 6.5</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">Java Developer Kit (JDK)</a></td> |
| <td class="tbltd1">Version 6 or<br/>version 5</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><b class="notes">Note:</b> Even though it is a separate product, there is no |
| need to download the NetBeans Platform separately. Typically, you develop the |
| application in NetBeans IDE and then exclude the modules that are specific to |
| the IDE but that are superfluous to your application. |
| |
| <!-- ===================================================================================== --> |
| |
| <h2 class="tutorial"><a name="single"></a>A Single Module NetBeans Platform Application</h2> |
| |
| <p>We start by simply creating a new NetBeans Platform application, |
| containing a single module. |
| |
| <ol> |
| |
| <p><li><p>Choose File | New Project and then choose NetBeans Modules. |
| Select "NetBeans Platform Application". You should see this:</p> |
| <p><p align="left"><img border="1" src="../images/tutorials/quickstart-platform/fig-1.png" alt="Fig 1"> |
| <p>Click Next.</p> |
| |
| <p><li><p>Call your new application "WordApp" and make it the IDE's main project:</p> |
| <p><p align="left"><img border="1" src="../images/tutorials/quickstart-platform/fig-2.png" alt="Fig 2"> |
| <p class="tips"> The IDE's main project is started when the |
| global project command "Run Project" is invoked.</p> |
| <p>Click Finish.</p> |
| |
| <p><li><p>Expand the new application in the Projects window, |
| right-click the Modules node, and choose "Add New". Call the new |
| module "WordEngine":</p> |
| <p><p align="left"><img border="1" src="../images/tutorials/quickstart-platform/fig-3.png"/> |
| <p>Click Next.</p> |
| |
| <p><li><p>Specify a unique name for the module, which is its code name |
| base, as well as a name that will be displayed in the Projects window:</p> |
| <p><p align="left"><img border="1" src="../images/tutorials/quickstart-platform/fig-4.png"/> |
| <p>Click Finish. The new module is created and its structure is |
| shown in the Projects window. |
| |
| <p><li><p>Right-click the "WordEngine" module and choose New | Other. |
| In the Module Development category, select "Window Component": |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-17.png"/> |
| |
| <p><p>Click Next. You should now see this:</p> |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-5.png"/> |
| <p>Click Next.</p> |
| |
| <p><li><p>Set the class name prefix to "Text" and the package to "org.demo.wordengine":</p> |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-6.png"/> |
| <p>Click Finish. The new window is added to the source structure |
| of your module, together with some ancillary XML files.</p> |
| |
| <p><li><p>Now double click on the file "TextTopComponent.java" to open |
| it in the Design view of the "Matisse" GUI Builder. Use the Palette (Ctrl-Shift-8) to |
| drag and drop a button and a text area onto the window:</p> |
| |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-7.png"/> |
| |
| <p>Right-click the text area, choose "Change Variable Name", and then |
| name it "text". That is the name that will enable you to access the |
| component from your code. Set the text of the button to "Filter!" |
| |
| <p><li><p>Double click on the button, causing an event handling method |
| to automatically be created in the Source editor. The method is called whenever the button is clicked. Change the body |
| of the method to the following code.</p> |
| <p><pre class="examplecode">private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { |
| String s = text.getText(); |
| s = s.toUpperCase(); |
| text.setText(s); |
| }</pre> |
| |
| <p><li><p>Right-click the application and choose Run. Doing so will start up your |
| new NetBeans Platform application and install your module. Your new application |
| should look as follows:</p> |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-8.png"/> |
| |
| <p><li><p>Choose Window | Text, enter a text in the text area, and click "Filter!". |
| You should see that the text is now shown in uppercase:</p> |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-9.png"/> |
| |
| </ol> |
| |
| <p>You have learned how to create a new NetBeans Platform application and how |
| to add new modules to it. |
| |
| <!-- ===================================================================================== --> |
| |
| <h2 class="tutorial"><a name="lookup"></a>A Modular Application Using Lookup</h2> |
| |
| <p>We create two additional modules. The first new module |
| defines a service, which the second module provides to |
| the module we defined in the previous section. |
| |
| <ol> |
| <p><li><p>Expand the new application in the Projects window, |
| right-click the Modules node, and choose "Add New". Call the new |
| module "TextFilter", with code name base "org.demo.textfilter", |
| complete the wizard, which adds the module to your previously created |
| application, as you did in the previous section.</p> |
| |
| <p><li><p>Right-click the "TextFilter" module and choose |
| New | Java Interface. Name the Java interface "TextFilter", |
| in the package "org.demo.textfilter", and use the editor |
| to define it as follows: |
| |
| <p><pre class="examplecode">package org.demo.textfilter; |
| |
| public interface TextFilter { |
| |
| String process(String s); |
| |
| } |
| </pre> |
| |
| <p><li><p>Right-click the "TextFilter" module, |
| choose Properties, and use the "API Versioning" |
| tab so specify that the package containing the |
| interface should be available throughout the |
| application:</p> |
| |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-10.png"/> |
| |
| <p><li><p>Create a third module in your application, |
| name it "MyFilter", with "org.demo.myfilter" as the |
| code name base.</p> |
| |
| <p><li><p>Add a dependency in the |
| Project Properties dialog of the newly created |
| "MyFilter" module |
| to the "TextFilter" module:</p> |
| |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-11.png"/> |
| |
| <p><li>Because of the dependency you defined above, |
| you can now implement the |
| interface defined in the second module: |
| |
| <p><pre class="examplecode">package org.demo.myfilter; |
| |
| import org.demo.textfilter.TextFilter; |
| |
| public class UpperCaseFilter implements TextFilter { |
| |
| public String process(String s) { |
| return s.toUpperCase(); |
| } |
| |
| }</pre> |
| |
| <p><li><p>Next, you need to publish the implementation |
| of the interface, using the standard JDK 6 way of |
| doing so. In the "MyFilter" module, create a |
| folder structure "src/META-INF/services", add to |
| it a file named after the fully qualified name |
| of the interface, containing one |
| line consisting of the fully qualified name |
| of the implementation:</p> |
| |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-13.png"/> |
| |
| <p class="tips"> An empty file can be created |
| via Other | Empty File in the New File dialog:</p> |
| |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-12.png"/> |
| |
| <p><li><p>The code that handles a click on the |
| filter button now needs to be changed, so that an |
| implementor of the interface "TextFilter" is located |
| and loaded. |
| When such an implementor is found, it is invoked to |
| filter the text.</p> |
| <p>Before we can do this, we need to |
| add a dependency in the Project Properties dialog of |
| the "WordEngine" module to the "TextFilter" module:</p> |
| |
| <p><img src="../images/tutorials/quickstart-platform/fig-14.png"/> |
| |
| <p>Now, you can load implementations of the |
| "TextFilter" class, as shown below:</p> |
| |
| <p><pre class="examplecode">private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { |
| String s = text.getText(); |
| <b>TextFilter filter = Lookup.getDefault().lookup(TextFilter.class)</b>; |
| if (filter != null) { |
| s = filter.process(s); |
| } |
| text.setText(s); |
| }</pre> |
| |
| <p class="tips"> The above could be done via the |
| JDK 6 "ServiceLoader" class, except that the |
| "Lookup" class can be used in JDK's prior |
| to JDK 6. Aside from that, the "Lookup" class |
| has a number of additional features, as the |
| next section will illustrate.</p> |
| |
| </ol> |
| |
| <p>Now you are ready to run the code and check |
| that everything works just as before. While the functionality |
| is the same, the new modular design offers a clear separation |
| between the graphical user interface and the implementation |
| of the filter. The new application can also be extended |
| quite easily, simply by adding new service providers to |
| the application's classpath.</p> |
| |
| <p>As an exercise, you could change the code, |
| so that ALL found text filters (use the method "lookupAll") |
| are applied consecutively on the text. For example, |
| add a text filter |
| implementation that removes all whitespaces and then test |
| the resulting application.</p> |
| |
| <!-- ===================================================================================== --> |
| |
| <h2 class="tutorial"><a name="listener"></a>LookupListener and InstanceContent</h2> |
| |
| <p>We create a fourth module, which receives texts |
| dynamically whenever we click the "Filter!" button |
| in our first module. |
| |
| <ol> |
| <p><li><p>In the first module, change the |
| constructor of the "TextTopComponent" as follows:</p> |
| |
| <p><pre class="examplecode"><b>private InstanceContent content;</b> |
| |
| private TextTopComponent() { |
| initComponents(); |
| setName(NbBundle.getMessage(TextTopComponent.class, "CTL_TextTopComponent")); |
| setToolTipText(NbBundle.getMessage(TextTopComponent.class, "HINT_TextTopComponent")); |
| // setIcon(Utilities.loadImage(ICON_PATH, true)); |
| |
| <b>content = new InstanceContent(); |
| associateLookup(new AbstractLookup(content));</b> |
| |
| }</pre> |
| |
| <p><li><p>Change the code of the filter |
| button so that the old value is added to |
| the <tt>InstanceContent</tt> object when the button is clicked.</p> |
| |
| <p><pre class="examplecode">private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { |
| String s = text.getText(); |
| TextFilter filter = Lookup.getDefault().lookup(TextFilter.class); |
| if (filter != null) { |
| <b>content.add(s);</b> |
| s = filter.process(s); |
| } |
| text.setText(s); |
| }</pre> |
| |
| <p><li><p>Create a new module called "History" |
| with code name base "com.demo.history". |
| <p><li>In the History module, create a |
| new window component with prefix "History", |
| in the "com.demo.history" package. Specify that |
| it should appear in the "editor" position. Once |
| you have created the window, add a |
| text area to it. Change the variable |
| name of the text area to "historyText".</p> |
| |
| <p><li><p>Add code to the constructor of the HistoryTopComponent class so |
| that it listens to the lookup of the <tt>String</tt> class |
| of the current active window. It displays all retrieved |
| <tt>String</tt> objects in the text area:</p> |
| |
| <p><pre class="examplecode"><b>private Lookup.Result result;</b> |
| |
| private HistoryTopComponent() { |
| |
| ... |
| |
| <b>result = org.openide.util.Utilities.actionsGlobalContext().lookupResult(String.class); |
| result.addLookupListener(new LookupListener() { |
| public void resultChanged(LookupEvent e) { |
| historyText.setText(result.allInstances().toString()); |
| } |
| });</b> |
| }</pre> |
| |
| <p><li>Then you can start the application and |
| experiment with it. The result should look similar |
| to the one shown in the screenshot below:</p> |
| |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-15.png"/> |
| |
| <p>As an exercise, you can change the type of the |
| lookup result from <tt>String</tt> to <tt>Object</tt> and see |
| what happens when you select different windows.</p> |
| |
| </ol> |
| |
| <p>Congratulations! At this stage, with very little coding, |
| you have created a small example of a modular |
| application: |
| |
| <p><img border="1" src="../images/tutorials/quickstart-platform/fig-16.png"/> |
| |
| <p>The application consists of 4 modules. Code from one module can only |
| be used by another module if (1) the first module explicitly exposes |
| packages and (2) the second module sets a dependency on the first module. |
| In this way, the NetBeans Platform helps to organize your code in a |
| strict modular architecture, ensuring that code isn't reused randomly |
| but only when there are contracts set between the modules that provide |
| the code.</p><p>Secondly, the <tt>Lookup</tt> class has been introduced as |
| a mechanism for communicating between modules, as an extension of the |
| JDK 6 ServiceLoader approach. Implementations are loaded via their |
| interfaces. Without using any code from an implementation, the "WordEngine" |
| module is able to display the service provided by the implementor. Loose |
| coupling is provided to NetBeans Platform applications in this way.</p> |
| |
| <p class="tips"> To continue learning about modularity |
| and the NetBeans Platform, head on to |
| the 4-part "NetBeans Platform Selection |
| Management" series, <a href="https://platform.netbeans.org/tutorials/nbm-selection-1.html">which starts here</a>. |
| After that, get started with the <a href="https://netbeans.org/kb/trails/platform.html">NetBeans Platform Learning Trail</a>, choosing |
| the tutorials that are most relevant to your particular business scenario. Also, |
| whenever you have questions about the NetBeans Platform, of any kind, feel free |
| to write to the mailing list, dev@platform.netbeans.org, its related |
| archive <a href="https://netbeans.org/projects/platform/lists/dev/archive">is here</a>.</p> |
| |
| <p>Have fun with the NetBeans Platform and see you on the mailing list!</p> |
| |
| |
| |
| </body> |
| |
| </html> |