For example, someone might want to write a module which would add a menu item to pop up a new window showing the Explorer in one pane and some information about selected files in the other, while sending progress messages to the Output Window, and also providing an Environment node describing the current status of the processing. This might involve:
The first step you should take is to download the OpenAPIs Support Module. It not only includes the full API documentation for you to browse, but includes a variety of templates for common API objects that will help you get started, and also has support features such as special testers and a module assembler that can streamline the process of developing and deploying a new module. Tips on how to use the support module to more easily accomplish some task will be inserted throughout this document, preceded by Support module: to alert you.
com.mycom.mymodule.*
. This way, you
can be sure that your module will not conflict with any other (they
are all loaded into the same namespace).
Most modules will also need some images, localized text, and so on. Typically these are placed in the same package together with source code, and the usual Java mechanisms (or NetBeans convenience variations) are used to load these - you will almost surely want to use classloader-based mechanisms for finding these resources. For example, localized text may be retrieved using code like:
String localizedText = NbBundle.getMessage (DialogPopper.class, "MSG_doYouWantToContinue");which would look in a
Bundle.properties
file (or
Bundle_ja.properties
, etc.) in the same directory as
the DialogPopper
source file:
# ---DialogPopper class resources--- # Message displayed when dialog such-and-such is popped up. MSG_doYouWantToContinue=Do you wish to continue with this installation now?The NetBeans I18N website has much more information, including detailed recommendations on how to organize localizable resources, and how to test that you are doing it right. Support module: all Java code templates which make use of human-displayable strings include calls to
NbBundle
to get you started - you will need to provide
the bundle yourself. Also if you use the I18N (Internationalization) module
in conjunction with the API Support,
you may ask to use NbBundle
rather than ResourceBundle
.
Images are requested in a number of different contexts and
should generally be loaded with similar mechanisms. For example,
the BeanInfo
for a system option will typically
override
SimpleBeanInfo.getIcon(...)
with a call to
Utilities.loadImage(String)
and pass in a pathname such as com/mycom/mymodule/optionIcon.gif
.
Support module: all bean info templates includes code to retrieve an image icon, and corresponding dummy images are included in the group templates.
OpenIDE-Module: com.mycom.mymodule module code name OpenIDE-Module-Name: My First Module display name blank line between header and first section Name: com/mycom/mymodule/MyModuleSettings.class extendsIt does not matter what you name the manifest file - it will be renamed in the JAR for you anyway.SystemOption
OpenIDE-Module-Class: Option please install as an option! blank lines between sections Name: com/mycom/mymodule/MyEnvironmentNode.class extendsNode
OpenIDE-Module-Class: Node please install as a node! Type: Environment put in the Environment part of the Explorer
Make sure you have a blank line at the end of the manifest, if you are having problems.
Support module: the Module JAR template, which creates a special API-aware JAR file, lets you visually copy API-related classes and their associated code and resources, then paste as a group onto the proper section node to add the correct manifest entry as well as incorporating files into the JAR. The Property Sheet lets you configure options such as the module display name, or the destination for a node section. The Module Manifest template creates just the bare manifest for a module, but otherwise behaves the same. In both cases, the support is bidirectional so you may modify the manifest via the Explorer, or see in the Explorer modifications you have made in the text.
$ cd ~/mysourcedir/ $ ls -R manifest.txt com com/: mycom com/mycom/: mymodule com/mycom/mymodule/: MyModuleSettings.java MyEnvironmentNode.java MyOtherClass.java Bundle.properties optionIcon.gif $ javac -deprecation -g -classpath .:/usr/local/netbeans/lib/openide.jar com/mycom/mymodule/*.java $ ls -R manifest.txt com com/: mycom com/mycom/: mymodule com/mycom/mymodule/: MyModuleSettings.java MyModuleSettings.class MyEnvironmentNode.java MyEnvironmentNode.class MyEnvironmentNode$1.class MyEnvironmentNode$2.class MyOtherClass.java MyOtherClass.class Bundle.properties optionIcon.gifYou should use the JDK's
jar
command, or the JAR Packager module, to actually build the JAR file:
$ jar cvfm0 mymodule.jar manifest.txt com/mycom/mymodule/ Adding com/mycom/mymodule/MyModuleSettings.java (storing 0%)... Adding com/mycom/mymodule/MyModuleSettings.class (storing 0%)... Adding com/mycom/mymodule/MyEnvironmentNode.java (storing 0%)... Adding com/mycom/mymodule/MyEnvironmentNode.class (storing 0%)... Adding com/mycom/mymodule/MyEnvironmentNode$1.class (storing 0%)... Adding com/mycom/mymodule/MyEnvironmentNode$2.class (storing 0%)... Adding com/mycom/mymodule/MyOtherClass.java (storing 0%)... Adding com/mycom/mymodule/MyOtherClass.class (storing 0%)... Adding com/mycom/mymodule/Bundle.properties (storing 0%)... Adding com/mycom/mymodule/optionIcon.gif (storing 0%)... $ ls -l mymodule.jar -rw-r--r-- 1 myacct myacct 27123 Dec 31 12:34 mymodule.jar(Here we just included the
*.java
source files for
simplicity, but you could easily exclude these, of course.)
Remember to:
-0
(zero) option to jar
so as not to compress the files. This reduces startup overhead.
jar
from the top of your package hierarchy; it
needs to "see" the included files in the correct relative
subdirectories, according to the Java package name (or you could
use the -C
option).
$ cd ~/elsewhere/ $ jar xf ~/mysourcedir/mymodule.jar meta-inf/manifest.mf Extracting meta-inf/manifest.mf... $ cat meta-inf/manifest.mf Manifest-Version: 1.0 OpenIDE-Module: com.mycom.mymodule Created-By: 1.2 (Sun Microsystems Inc.) OpenIDE-Module-Name: My First Module Name: com/mycom/mymodule/MyModuleSettings.class OpenIDE-Module-Class: Option Name: com/mycom/mymodule/MyEnvironmentNode.class OpenIDE-Module-Class: Node Type: Environment $ cd ~/mysourcedir/You should see the entries you created, plus a few lines added by the JAR tool.
Many people prefer to use Ant to build modules, as the entire sequence can be easily scripted, and there is support in the IDE for working with it too. See nbbuild.netbeans.org for some information on building NetBeans modules using Ant.
Support module: if you used the
Module JAR
template, then you can use the regular JAR
Packager interface to build the module without needing to use a
command line. You can develop and compile your classes inside the
IDE too. You can hit Execute to try the module.
Under Tools | Options | Modules you
will find a list of all modules installed in the IDE.
Some "test" modules
are distinguished with a red T
superimposed on the module icon, meaning that they are reloadable.
All modules can in principle be reloaded after they are installed if you just
disable them, change their JAR file, and enable them again; in practice,
various IDE and JDK bugs can make this not work reliably. If a module's
Reloadable property is set to True
(this property only appears with the special startup
option -J-Dnetbeans.module.test=true
,
set also by the API Support),
then the IDE will treat it in a special way making it reliable to reload it
while the IDE is still running.
Do not place your module's classes into the IDE's startup classpath. If you do so, it may seem to work, but the classes will be loaded from the wrong classloader: the startup loader and not the module loader (for regular modules) or the user loader (for test modules). Various subtle errors can occur in this case. For this reason, the IDE will try to detect this situation and warn you about what is wrong.
Support module: the default executor for module JARs installs the module into the running IDE in test (reloadable) mode. If you execute it again, the JAR will be reloaded so normally there is no need to restart the IDE while testing! This is merely a presentation variant of using test modules from the Modules node. Note that you can make a regular module reloadable and reload it without restarting the IDE.
The support module also defines a special Ant task,
<nbinstaller/>
, which can be used to install module
JARs in test mode from within an Ant script.
The Update Center feature (from the Tools menu) also permits you to dynamically publish module updates and upgrade them from an update server, which might live on netbeans.org, or on the Forte Portal, or on your own special server. Please see the Update Center's home page for more details on making NBM (NetBeans Module) packages and publishing them.
There is not much to say specifically about how to test modules
once you are sure they got installed, other than trying out their
functionality. Mainly, keep your console window open! If running on
Unix, make sure you ran NetBeans from a command window
(e.g. xterm
) so that its output is visible. If there
are any serious errors or diagnostics, they may be printed to the
console, so you should check this window if in doubt.
If messages overrun the available space on screen, you must make sure the console window is scrollable. On Unix, this is usually true by default. On Windows, you should give the console window a scroll buffer - right-click on the "MSDOS" icon in the upper-left corner of the window, select "Properties...", go to the "Layout" tab, and make sure "Screen Buffer Size" is set to something appropriate (e.g. a few hundred wide, and a thousand or two tall). Save your settings, and agree to apply them to the shortcut so that they will take effect the next time you restart.
If it is not there already, add
-J-Dnetbeans.debug.exceptions=true to your IDE command-line
options to make sure you are informed of all
unexpected exceptions that occur. You may also want to turn on various
ErrorManager
flags, though exactly which ones will depend
on what you want to know.
Support module: If your manifest file syntax is incorrect, a red X will appear superimposed on the JAR or manifest icon. You can check the property sheet to see the exact errors. Of course, other parts of the module are not checked by this, just the manifest syntax.
System.out.println
(e.g.) to display the results. You
must set such a file to use internal execution; then the code will
be run inside the IDE, so you can test it as you go. You can use
the Scripting Console to use your favorite scripting language to
test expressions interactively. Also, if
you have a Debugger module (e.g.) which provides interactive
evaluation of expressions, this may be used for similar purposes.
Support module: there is a template API Test Script which will be run using internal execution and includes a few useful testing methods and some standard imports.
Here are some specific things which can be done using internal execution that would make testing easier than rerunning the module:
TopManager.NodeOperation.explore(Node)
.
Especially useful is to call this on a newly created
BeanNode
,
so as to explore JavaBean-like objects you may be creating or
using.
Support module: if you have a public default constructor, try setting the executor on your node class to Test Beans. This will not only show you the node (and its children), but allow you to inspect otherwise invisible properties of it.
clone()
is called, does not create a new instance of
its own class but rather uses the
TopManager.currentClassLoader()
to load the "real" editor kit to use, which could then be code in
the Repository - so the normal edit-compile-test cycle could be
used. Just close existing editor windows using your old kit and
other code; change the code, recompile, and then open the panes
again.
Support module: if you use the Test Beans executor, you will see your file system displayed as a JavaBean, which means that you can test custom configuration of it. Then you can also browse through the enhanced hierarchy to look at file objects contained within it, their data objects, those objects' node delegates, and so on.
main
method, so that they may be executed after a
quick change and recompile. For NodeAction
s (including
CookieAction
s), you may want to use
TopManager.NodeOperation.select(...)
to permit you to select test nodes to run the action on.
Support module: all action templates come with one of two executors, Test SystemAction Objects or Test Presenter Objects, which permit you to test the functionality and appearance of the actions without needing to insert any special test code into the class.
The difficulty in debugging is that it is not possible to debug
a module by itself within the IDE, since it runs within the same VM
as the IDE and integrates into it. The same goes for code which
needs to be run in internal execution (as it makes API
calls) - there is no such thing as "internal debugging" using the
normal VM-supported debugger implementation. So, you will need to
run the entire IDE in debugging mode, using either another copy of
the IDE, or some alternate debugger such as command-line JDB, and
set breakpoints on the module code of interest. (Note that module
code is dynamically loaded, i.e. not statically referenced, and
therefore you may need to delay settings breakpoints until the
module has already been loaded.) To use (another instance of) the
IDE as the debugger, you should modify the startup script of the
to-be-debugged IDE to include -Xdebug
(and maybe
-classic
for HotSpot, and some sundry other flags for JPDA
as documented in general for the JPDA switches) and also include
tools.jar (from the JDK) in the boot class path. Start
the debuggee manually and use the connect-to feature of the IDE's
debugger to connect to the process as usual with the host name and agent
password (or for JPDA, socket or shared memory segment or whatever is required).
To avoid running the whole IDE in a debugger (this may be slow),
you may prefer to use the fallback method of including copious
debugging statements which print interesting information as the IDE
runs your module code. In practice this is feasible - most API
objects either have a sensible implementation of
Object.toString()
, or provide an obvious display name
that would identify them easily when printed. Printing to
System.err
will not only print to the console, but
will include the output in the netbeans.log file in
the installation's system/ directory, for later
perusal. See above for redirecting output to the Output Window.
If you use test modules, it is simple enough to insert
a few debug prints, reload, see what is going wrong, try to fix
it, verify that it is fixed, and then remove the statements again.
The scripting module (currently in NetBeans builds only) may be used to evaluate expressions and run commands interactively inside the IDE's VM.
The
ErrorManager
may be used to emit debugging information from modules at customizable
output levels, so that critical diagnostic information can be left in
production code and dynamically enabled when required.
If you are having problems related to Java security mechanisms,
there are a couple of things you can do. First, if
SecurityException
is being thrown, you can add
-J-Djava.security.debug=access,failure to the IDE's
command-line options to show the ProtectionDomain
that
failed. Second, if you are getting IllegalAccessError
,
try printing to standard error
IllegalClass.class.getProtectionDomain().getCodeSource(),
which will show the URL from which the class was loaded; if this URL
is outside the IDE's installation, it is likely you need to manually
add permissions to the relevant classloader.
Support module: many things about the IDE that you might wish to know (current settings and status of various objects, etc.) can be seen under Runtime | Bean Browser, without running a debugger.