blob: c7c26cd8e8ec734fb404c46c63f9355904402bf9 [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 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&#252;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>