blob: 3217ec73e1db6c81b460550211e946fbd2136c98 [file] [log] [blame]
<!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 7.2</title>
<meta name="AUDIENCE" content="NBUSER"/>
<meta name="TYPE" content="ARTICLE"/>
<link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"/>
<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."/>
<!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -->
<!-- Use is subject to license terms.-->
</head>
<body>
<h1>NetBeans Platform 7.2 Quick Start</h1>
<p>Welcome to the <a href="https://platform.netbeans.org/"><b>NetBeans Platform</b></a>!</p>
<p>The NetBeans Platform is a generic application framework primarily for Java desktop applications.
The main benefit of the NetBeans Platform is its predefined modular architecture. Secondary
benefits are the NetBeans Platform's reusable solutions such as its
docking framework and its out-of-the-box pluggable components, in combination with the tools
provided by its SDK, NetBeans IDE, in particular
its award winning "Matisse" GUI Builder for designing GUI components.</p>
<p>In this quick start, you are introduced to the benefits and usages of modularity
on the Java desktop via
a very simple example, contributed by Thomas W&#252;rthinger, 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>
<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>
<p><strong class="notes">Note: </strong>This document uses NetBeans Platform 7.2 and
NetBeans IDE 7.2. If you
are using an earlier version, see <a href="71/nbm-quick-start.html">the previous version
of this document</a>.</p>
<p><b>Contents</b></p>
<p><img src="../../images/articles/72/netbeans-stamp.gif" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 7.2" title="Content on this page applies to NetBeans IDE 7.2"/></p>
<ul class="toc">
<li>Part 1: <a href="#single">A Single Module NetBeans Platform Application</a>
<ul>
<li><a href="#application">Create the Application</a></li>
<li><a href="#module">Create the Module</a></li>
<li><a href="#window">Create the Window</a></li>
<li><a href="#run">Run the Application</a></li>
</ul>
</li>
<li>Part 2: <a href="#lookup">A Modular Application Using Lookup</a>
<ul>
<li><a href="#api">Create the API</a></li>
<li><a href="#impl">Implement the API</a></li>
<li><a href="#run2">Run the Application</a></li>
</ul>
</li>
<li>Part 3: <a href="#listener">Publishing and Subscribing to the Lookup</a>
<ul>
<li><a href="#publish">Publish to the Lookup</a></li>
<li><a href="#subscribe">Subscribe to the Lookup</a></li>
</ul>
</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 7.2 or above</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 above</td>
</tr>
</tbody>
</table>
<p></p>
<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.</p>
<p class="tips"> Do some background reading before diving into
this tutorial. In particular, read the <a href="http://bits.netbeans.org/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html">Modules API Reference</a> document,
which explains what modules are and provides some
context for this tutorial, while noting that there is an extensive Reference Material section
on the <a href="https://netbeans.org/kb/trails/platform.html">NetBeans Platform Learning Trail</a>.</p>
<!-- ===================================================================================== -->
<h2 class="tutorial"><a name="single"></a>A Single Module NetBeans Platform Application</h2>
<p>We start by creating a new NetBeans Platform application,
containing a single module.</p>
<ul>
<li><a href="#application">Create the Application</a></li>
<li><a href="#module">Create the Module</a></li>
<li><a href="#window">Create the Window</a></li>
<li><a href="#run">Running the Application</a></li>
</ul>
<div class="indent">
<h3 class="tutorial"><a name="application"></a>Create the Application</h3>
<p>In this section, you create your first NetBeans Platform application.</p>
<div class="indent">
<ol>
<li><p>Choose File | New Project and then choose NetBeans Modules.
Select "NetBeans Platform Application". You should see this:</p><br/>
<p><img src="../../images/tutorials/quickstart-platform/72/new-project-1.png" alt="Fig 1"/></p>
<br/><p>Click Next.</p></li>
<li><p>Name your new application "WordProcessor" and specify a folder on disk
for storing it:</p><br/>
<p><img src="../../images/tutorials/quickstart-platform/72/new-project-2.png" alt="Fig 2"/></p>
<br/><p>Click Finish. The new project appears as follows in the Projects window:</p>
<br/><p><img src="../../images/tutorials/quickstart-platform/72/new-project-3.png" alt="Fig 2-1"/></p></li>
</ol>
</div>
</div>
<div class="indent">
<h3 class="tutorial"><a name="module"></a>Create the Module</h3>
<p>In this section, you create your first NetBeans Platform module.</p>
<div class="indent">
<ol>
<li><p>Right-click the "Modules" node, shown in the screenshot above,
and choose "Add New":</p>
<br/><p><img src="../../images/tutorials/quickstart-platform/72/new-project-4.png" alt="Fig 2-1"/></p>
<p>Name the new
module "WordEditorCore":</p>
<br/><p><img alt="create new module" src="../../images/tutorials/quickstart-platform/72/new-project-5.png"/></p>
<br/><p>Click Next.</p></li>
<li><p>Specify "org.word.editor.core" as the unique string identifying the module, which is its code name
base, together with a project display name that will be shown in the Projects window.</p><br/>
<p><img alt="create new module" src="../../images/tutorials/quickstart-platform/72/new-project-6.png"/></p>
<br/><p>Click Finish. The new module is created and its structure is
shown in the Projects window:</p>
<br/><p><img alt="specify a name" src="../../images/tutorials/quickstart-platform/72/new-project-7.png"/></p></li>
</ol>
</div>
</div>
<div class="indent">
<h3 class="tutorial"><a name="window"></a>Create the Window</h3>
<p>In this section, you create your first NetBeans window.</p>
<div class="indent">
<ol>
<li><p>Right-click the "WordEditorCore" module and choose New | Other.
In the Module Development category, select "Window":</p>
<p><br/><img alt="create new window" src="../../images/tutorials/quickstart-platform/72/new-window-1.png"/></p>
<br/><p>Click Next.</p></li>
<li><p>You should now see a dialog for specifying the position where the new window
will appear in the application frame, as well as whether it will open automatically when the application
starts, among other settings:</p>
<p><br/><img alt="create new window" src="../../images/tutorials/quickstart-platform/72/new-window-2.png"/></p>
<p><br/>In the wizard step above, select "editor", which is the default central
position within the application frame, and "Open on Application Start". Then click Next.</p></li>
<li><p>Set the class name prefix to "Word" and the package to "org.word.editor.core":</p>
<p><br/><img alt="set definitions" src="../../images/tutorials/quickstart-platform/72/new-window-3.png"/></p>
<p><br/>Click Finish. The new window is added to the source structure
of your module:</p>
<p><br/><img alt="set definitions" src="../../images/tutorials/quickstart-platform/72/new-window-4.png"/></p></li>
<li><p>Now double click on the file "WordTopComponent.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><br/><img alt="palette" style="border: 1px solid black;" src="../../images/tutorials/quickstart-platform/72/new-window-5.png"/></p>
<br/><p>Do the following to make the new GUI components meaningful:</p>
<br/><ul>
<li>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.</li>
<li>Right-click the button, choose "Edit Text", and then set the text of the button to "Filter!"</li>
</ul></li>
<li>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.
<pre class="examplecode">private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
<b>String s = text.getText();
s = s.toUpperCase();
text.setText(s);</b>
}</pre></li>
</ol>
</div>
</div>
<div class="indent">
<h3 class="tutorial"><a name="run"></a>Run the Application</h3>
<p>In this section, you deploy the application.</p>
<div class="indent">
<ol>
<li><p>Right-click the application and choose Run. Doing so will start up your
new NetBeans Platform application and install your module. You will have a new
window, as well as a new menu item for opening it,
as shown below:</p>
<br/><p><img alt="show new app" src="../../images/tutorials/quickstart-platform/72/new-app-1.png"/></p></li>
<li><p>Enter a text in lowercase in the text area, and click "Filter!".
You should see that the text is now shown
in uppercase:</p>
<br/><p><img alt="uppercase" src="../../images/tutorials/quickstart-platform/72/new-app-3.png"/></p></li>
</ol>
</div>
</div>
<p>You have learned how to create a new NetBeans Platform application and how
to add new modules to it. In the next section, you will be introduced
to the NetBeans Platform's pluggable service infrastructure.</p>
<!-- ===================================================================================== -->
<h2 class="tutorial"><a name="lookup"></a>A Modular Application Using Lookup</h2>
<p>In this section, you create two additional modules. The first
new module, "WordEditorAPI",
contains a service provider interface. The second module,
"UppercaseFilter", is a service provider for the interface.</p>
<p> The GUI module, which you created in the previous section, will be loosely coupled from
the "UppercaseFilter" service provider because the GUI module
will not refer to any code from the "UppercaseFilter" service provider.
That will be possible because the "UppercaseFilter"
service provider will be registered in the META-INF/services folder
and loaded via the NetBeans Lookup class, which is comparable to
the JDK 6 ServiceLoader class.</p><p> You will then
create another loosely coupled service provider,
named "LowercaseFilter".</p>
<ul>
<li><a href="#api">Create the API</a></li>
<li><a href="#impl">Implement the API</a></li>
<li><a href="#run2">Run the Application</a></li>
</ul>
<div class="indent">
<h3 class="tutorial"><a name="api"></a>Create the API</h3>
<p>In this section, you create an API.</p>
<div class="indent">
<ol>
<li><p>Expand the new application in the Projects window,
right-click the Modules node, and choose "Add New":</p>
<br/><p><img alt="uppercase" src="../../images/tutorials/quickstart-platform/72/new-api-1.png"/></p>
<br/><p>Name the new
module "WordEditorAPI":</p>
<br/><p><img alt="uppercase" src="../../images/tutorials/quickstart-platform/72/new-api-2.png"/></p>
<br/><p>Click Next. Use code name base "org.word.editor.api" and
complete the wizard, which adds the module to your previously created
application, as you did in the previous section:</p>
<br/><p><img alt="uppercase" src="../../images/tutorials/quickstart-platform/72/new-api-3.png"/></p></li>
<li><p>Right-click the "WordEditorAPI" module and choose
New | Java Interface. Name the Java interface "WordFilter",
in the package "org.word.editor.api", and use the editor
to define it as follows:</p>
<pre class="examplecode">package org.word.editor.api;
public interface WordFilter {
String process(String s);
}</pre></li>
<li><p>Right-click the "WordEditorAPI" module,
choose Properties, and use the "API Versioning"
tab to specify that the package containing the
interface should be available throughout the
application:</p>
<br/><p><img alt="" src="../../images/tutorials/quickstart-platform/72/new-api-4.png"/></p>
<br/><p>Click OK.</p>
<p class="tips">In the Projects window, expand "Important Files" in the
"WordEditorAPI" project and then
double-click "Project Metadata". The "project.xml" file
opens and you should see that the package has now been declared
public:</p>
<pre class="examplecode">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project xmlns="https://netbeans.org/ns/project/1"&gt;
&lt;type&gt;org.netbeans.modules.apisupport.project&lt;/type&gt;
&lt;configuration&gt;
&lt;data xmlns="https://netbeans.org/ns/nb-module-project/3"&gt;
&lt;code-name-base&gt;org.word.editor.api&lt;/code-name-base&gt;
&lt;suite-component/&gt;
&lt;module-dependencies/&gt;
<b>&lt;public-packages&gt;
&lt;package&gt;org.word.editor.api&lt;/package&gt;
&lt;/public-packages&gt;</b>
&lt;/data&gt;
&lt;/configuration&gt;
&lt;/project&gt;</pre>
</li>
</ol>
</div>
</div>
<div class="indent">
<h3 class="tutorial"><a name="impl"></a>Implement the API</h3>
<p>In this section, you implement the API, in a separate module.</p>
<div class="indent">
<ol>
<li><p>Expand the new application in the Projects window,
right-click the Modules node, and choose "Add New" again:</p>
<br/><p><img alt="uppercase" src="../../images/tutorials/quickstart-platform/72/new-impl-1.png"/></p>
<br/><p>Name the new
module "UppercaseFilter":</p>
<br/><p><img alt="uppercase" src="../../images/tutorials/quickstart-platform/72/new-impl-2.png"/></p>
<br/><p>Click Next. Use code name base "org.word.editor.uppercase" and
complete the wizard, which adds the module to your previously created
application, as you did in the previous section:</p>
<br/><p><img alt="uppercase" src="../../images/tutorials/quickstart-platform/72/new-impl-3.png"/></p></li>
<li><p>Right-click the Libraries node "UppercaseFilter" module,
and Add Module Dependency, as shown below:</p>
<br/><p><img alt="" src="../../images/tutorials/quickstart-platform/72/new-impl-4.png"/></p>
<br/><p>Start typing the name of the API class and notice that the list narrows
until the module containing the class is found:</p>
<br/><p><img alt="" src="../../images/tutorials/quickstart-platform/72/new-impl-5.png"/></p>
<br/><p>Click OK.</p>
<br/><p class="tips">In the Projects window, expand "Important Files" in the "UppercaseFilter" project,
and then
double-click "Project Metadata". The "project.xml" file
opens and you should see that a new dependency has been declared:</p>
<pre class="examplecode">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;project xmlns="https://netbeans.org/ns/project/1"&gt;
&lt;type&gt;org.netbeans.modules.apisupport.project&lt;/type&gt;
&lt;configuration&gt;
&lt;data xmlns="https://netbeans.org/ns/nb-module-project/3"&gt;
&lt;code-name-base&gt;org.word.editor.uppercase&lt;/code-name-base&gt;
&lt;suite-component/&gt;
<b>&lt;module-dependencies&gt;
&lt;dependency&gt;
&lt;code-name-base&gt;org.word.editor.api&lt;/code-name-base&gt;
&lt;build-prerequisite/&gt;
&lt;compile-dependency/&gt;
&lt;run-dependency&gt;
&lt;specification-version&gt;1.0&lt;/specification-version&gt;
&lt;/run-dependency&gt;
&lt;/dependency&gt;
&lt;/module-dependencies&gt;</b>
&lt;public-packages/&gt;
&lt;/data&gt;
&lt;/configuration&gt;
&lt;/project&gt;</pre>
<p class="notes"><b>Note:</b> In the same way as shown above,
set a dependency on the Lookup API module, which provides the
@ServiceProvider annotation that you will use in the next step.</p></li>
<li>Because of the Lookup API dependency you defined above,
you can now implement the
interface defined in the WordEditorAPI module. Do so in the "UppercaseFilter" module, by creating
a new class named "UppercaseFilter", in the "org.word.editor.uppercase" package,
as shown below. Start by creating a new Java class, named "UppercaseFilter", and
then define it as follows:
<pre class="examplecode">package org.word.editor.uppercase;
import org.openide.util.lookup.ServiceProvider;
import org.word.editor.api.WordFilter;
@ServiceProvider(service=WordFilter.class)
public class UppercaseFilter implements WordFilter {
@Override
public String process(String s) {
return s.toUpperCase();
}
}</pre>
<p class="tips"> At compile time, the @ServiceProvider annotation will create a META-INF/services
folder with a file that registers your implementation of the
WordFilter interface, following the JDK 6 ServiceLoader mechanism.</p></li>
<li><p>In the WordEditorCore module, the code that handles a click on the
filter button now needs to be changed, so that all
implementations of the interface "WordFilter" are located
and loaded.
When such implementations are found, you need to invoke its method to
filter the text. Before we can do this, we need to
add a dependency in the
the "WordEditorCore" module on the "WordEditorAPI" module:</p>
<br/><p><img alt="" src="../../images/tutorials/quickstart-platform/72/new-impl-6.png"/></p>
<p>Now, you can load implementations of the
"WordFilter" class, as shown below:</p>
<pre class="examplecode">private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
<b>String enteredText = text.getText();
Collection&lt;? extends WordFilter> allFilters = Lookup.getDefault().lookupAll(WordFilter.class);
StringBuilder sb = new StringBuilder();
for (WordFilter textFilter : allFilters) {
String processedText = textFilter.process(enteredText);
sb.append(processedText).append("\n");
}
text.setText(sb.toString());</b>
}</pre>
<p class="tips"> The above could be achieved 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>
</li>
</ol>
</div>
</div>
<div class="indent">
<h3 class="tutorial"><a name="run2"></a>Run the Application</h3>
<p>In this section, you run the application again.</p>
<div class="indent">
<ol>
<li><p>Now you can run the application again and check
that everything works just as before. While the functionality
is the same, the new modular design offers a clear separation
between the GUI and the implementation
of the filter. The structure of the application should be as shown below.</p>
<br/><p><img alt="" src="../../images/tutorials/quickstart-platform/72/new-impl-7.png"/></p>
</li>
<li><p>The new application can also be extended
quite easily, by adding new service providers to
the application's classpath. As an exercise, add a new module that provides a "LowercaseFilter"
implementation of the API to the application.</p></li>
</ol>
</div>
</div>
<p>You have now used the default Lookup, that is, "Lookup.getDefault()", to load
implementations of an interface from the META-INF/services folder.</p>
<!-- ===================================================================================== -->
<h2 class="tutorial"><a name="listener"></a>Publishing and Subscribing to the Lookup</h2>
<p>In this section, we create a fourth module, which receives texts
dynamically whenever we click the "Filter!" button
in our first module.</p>
<ul>
<li><a href="#publish">Publish to the Lookup</a></li>
<li><a href="#subscribe">Subscribe to the Lookup</a></li>
</ul>
<div class="indent">
<h3 class="tutorial"><a name="publish"></a>Publish to the Lookup</h3>
<p>In this section, you publish a String into the Lookup of the TopComponent. Whenever
the TopComponent is selected, the String is published into the application's context.</p>
<div class="indent">
<ol>
<li>In the "WordEditorCore" module, we publish a String whenever
the user clicks the "Filter!" button. To do so, change the
constructor of the "WordTopComponent" as follows:
<pre class="examplecode"><b>private <a href="http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/org/openide/util/lookup/InstanceContent.html">InstanceContent</a> content;</b>
private WordTopComponent() {
initComponents();
setName(Bundle.CTL_WordTopComponent());
setToolTipText(Bundle.HINT_WordTopComponent());
<b>content = new InstanceContent();
<a href="http://bits.netbeans.org/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html#associateLookup(org.openide.util.Lookup)">associateLookup</a>(new <a href="http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/org/openide/util/lookup/AbstractLookup.html">AbstractLookup</a>(content));</b>
}</pre></li><li><p>Change the code of the filter
button so that the entered text is added to
the <tt>InstanceContent</tt> object when the button is clicked.</p>
<pre class="examplecode">private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String enteredText = text.getText();
Collection&lt;? extends WordFilter&gt; allFilters = Lookup.getDefault().lookupAll(WordFilter.class);
StringBuilder sb = new StringBuilder();
for (WordFilter textFilter : allFilters) {
String processedText = textFilter.process(enteredText);
sb.append(processedText).append("\n");
<b>content.add(enteredText);</b>
}
text.setText(sb.toString());
}</pre>
</li>
</ol>
</div>
</div>
<div class="indent">
<h3 class="tutorial"><a name="subscribe"></a>Subscribe to the Lookup</h3>
<p>In this section, you create a new module, with a new window. In
the new window, you listen to the application's context for Strings. When there
is a new String in the Lookup, you display it in the window.</p>
<div class="indent">
<ol>
<li><p>In the same way as done in the previous sections,
create another module in your application and name it "WordHistory".
Use code name base "org.word.editor.history".</p>
</li>
<li><p>In the WordHistory module, right-click the "org.word.editor.history" package
and choose New | Window. Use the New Window wizard to create a
new window component that will automatically be opened on the left side of the
application frame, which is the "explorer" position:</p>
<br/><p><img alt="" src="../../images/tutorials/quickstart-platform/72/new-window2-1.png"/></p>
<br/><p>Click Next. Use prefix "WordHistory" and specify that the new window will be stored
in the "org.word.editor.history" package. Click Finish.</p>
</li>
<li><p>Once
you have created the window, add a
<tt>JTextArea</tt> to it:</p>
<br/><p><img alt="" style="border:1px solid black" src="../../images/tutorials/quickstart-platform/72/new-window2-2.png"/></p>
<p>Change the variable
name of the text area to "historyText".</p>
</li>
<li>In the Source view, 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:
<pre class="examplecode">...
...
...
public final class HistoryTopComponent extends TopComponent <b>implements LookupListener</b> {
<b>private org.openide.util.Lookup.Result&lt;String&gt; result;</b>
...
...
...
<b>@Override
public void componentOpened() {
result = org.openide.util.Utilities.actionsGlobalContext().lookupResult(String.class);
result.addLookupListener(this);
}
@Override
public void componentClosed() {
result.removeLookupListener(this);
}
@Override
public void resultChanged(LookupEvent le) {
Collection&lt;? extends String&gt; allStrings = result.allInstances();
StringBuilder sb = new StringBuilder();
for (String string : allStrings) {
sb.append(string).append("\n");
}
historyText.setText(sb.toString());
}</b>
...
...
...
</pre></li>
<li><p>Then you can start the application and
experiment with it. The result should look similar
to that shown in the screenshot below:</p>
<br/><p><img alt="" src="../../images/tutorials/quickstart-platform/72/new-result-1.png"/></p>
<p class="tips">As an exercise, redesign the user interface of the "WordTopComponent"
in such a way that a <tt>JList</tt> displays the filters.</p>
</li>
</ol>
</div>
</div>
<p>Congratulations! At this stage, with very little coding,
you have created a small example of a loosely-coupled modular
application:</p>
<p><img alt="" src="../../images/tutorials/quickstart-platform/72/new-result-2.png"/></p>
<p>Two important concepts have been covered in this tutorial.</p>
<ol>
<li>The application consists of four 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.</li>
<li>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 "WordEditorCore"
module is able to display the service provided by the implementor. Loose
coupling is provided to NetBeans Platform applications in this way.</li>
</ol>
<p class="tips"> To continue learning about modularity
and the NetBeans Platform, head on to
the four-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>