 |
Deliver your beans in a NetBeans module (the hard way)
Posted by timboudreau on April 05, 2006 at 05:13 PM | Comments (6)
In Monday's blog, I announced a webstart-enabled standalone tool that will generate a NetBeans plug-in module that takes a JAR of Swing components, putting them on the component palette for users to drag and drop. Here I describe how to do the same thing using the plug-in development tools inside NetBeans.
I had actually written this up a couple of weeks ago, and it was my friend and colleague Trung Duc Tran who said "there should be a tool to do that." He was right. So I held this blog and wrote BeanNetter.
Nonetheless, the step-by-step here is worth posting, since you can see what's being generated by the tool under the hood, and it's useful if you're making a module already. So here's how you'd do the same things by hand:
- The first thing you want to do is set your JavaBean up as a Library in NetBeans - that's a library that can be shared among projects you're working on. Go to Tools | Library Manager, and add your component's JAR as a library you'd use in normal development - you'll see why in a minute
- The second thing you want to do is create a plug-in project. That's easy and it's built right into NetBeans. Just go to New | New Project, and choose NetBeans Plug-In Modules | Module Project
- On the next screen, provide a name - short and clear is usually good, same name as your component would also make sense
- For code name base, just use the fully qualified name of your component. Don't worry about it too much, it just needs to be unique.
- For module display name, type in some nice human readable name for your component(s)
- Your project will open, and you'll have a package with the same name as the code name you entered. Select the package and choose New | File
- Select NetBeans Module Development | J2SE Library Descriptor. What's that?
Well, NetBeans already has a way to embed "libraries" in a module and have them show up in the list of libraries a user can use. So the only thing we're going to need to do in addition is add a little metadata to put the bean(s) on the Component Palette
- Click next and finish. You'll see an XML file is created. Don't worry about it, we're not going to need to touch that.
- Now we get to add a little bit of metadata that puts an entry on the component palette.
- Select your package again and choose File | New, and in the new file dialog, create a new empty XML file. Call it something like MyBeanPaletteItem. Paste the following content into it, substituting the fully qualified name of one JavaBean and the name of the library:
<?xml version="1.0" encoding="UTF-8"?>
<palette_item version="1.0">
<component classname="org.netbeans.swing.colorchooser.ColorChooser" />
<classpath>
<resource type="library" name="ColorBean" />
</classpath>
</palette_item>
- There's only one step left - open the layer.xml file in your package. Add the highlighted portion you see below, substituting the palette item xml file you just created for the one listed here.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
<filesystem>
<folder name="org-netbeans-api-project-libraries">
<folder name="Libraries">
<file name="ColorBean.xml" url="ColorBean.xml"/>
</folder>
</folder>
<folder name="FormDesignerPalette">
<folder name="Beans">
<file name="ColorChooser.palette_item" url="ColorBeanPaletteItem.xml"/>
</folder>
</folder>
</filesystem>
- Right click the project and choose Create NBM. When it's done, you've got a NetBeans module that will auto-install your JavaBean into a user's component palette. Try it out on an instance of NetBeans that knows nothing about your library - just start NetBeans from the command line, e.g.
nb -userdir /tmp/foo. When it comes up, choose Tools | Update Center. Select the Install Manually Downloaded Modules option, and find the NBM file that was created (hint: look in the output window of the instance of NetBeans you built it in).
And poof, you've got a NetBeans plugin that delivers your components right onto the component palette of any NetBeans 5.0 user.
If you have some problems, this usually means one of the strings in one of the XML files is not correct. Try starting the instance of NetBeans you install the module in, from the command line, and add the line switch -J-Dnetbeans.logger.console=true to get an idea of where the problem might be.
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Hi,
If the name of the file in step 10 is "MyBeanPaletteItem.xml" then I think the highlighted section in step 11 should read something like:
<folder name="FormDesignerPalette">
<folder name="Beans">
<file name="ColorChooser.palette_item" url="MyBeanPaletteItem.xml"/>
</folder>
</folder>
Am I right?
Thanks for explaining this!!. I am still a little bit confused between "J2SE Library Descriptor" and "Module Library Wrappers", though. Would you please explain what is the difference between these?
And another question: if my Bean installs a custom property editor (say ColorChooserPropertyEditor), may I do that available to the rest of beans? Will the form editor find the class for that if I just install it inside a "J2SE Library Descriptor"? Or shall I use a "Module Library Wrapper" instead?
Thanks (and thanks for these posts!!),
Antonio
Posted by: vieiro on April 06, 2006 at 04:13 AM
-
Yes, to be consistent, that would be correct.
Re custom property editors: If your Bean uses custom property editors, as long as the BeanInfo specifies them correctly, they should work automatically in the property sheet.
Re confusion:
.J2SE Library Descriptor - this is embedding a library that users of the IDE can include in/use in/call from their projects on disk
Library wrapper module - this is where you have a library (like perhaps you're using Apache commons stuff or such) and your module wants to use it - it's not visible to users of the IDE, their projects don't call it, it's something your module needs in order to operate.
So the former is for users - making a library available for user projects, and the latter is a thing you might want to call from your module.
Posted by: timboudreau on April 06, 2006 at 09:06 AM
-
Hi Tim,
nice work - the only decent information I've seen anywhere about this stuff.
One question: can I make a custom property editor a FormAwareEditor also? Or how about impementing ExPropertyEditor? Would those methods get called? And how would I structure such a thing, since to get visibility to those interfaces I'd need the editor to be in a module, and not a library.
Any ideas?
TIA, Paul.
Posted by: pszego on December 10, 2006 at 05:02 PM
-
Basically you'd just need to compile your design-time JAR with ExPropertyEditor on the classpath; however, I'm not sure how nicely that would behave in *other* IDEs - generally ExPropertyEditor, etc. is intended for use by modules which want to show bean properties of their own objects in the property sheet, not for ad-hoc JavaBeans (but the beans spec is horribly underspecified when it comes to property editors and something like these subinterfaces is sadly necessary - hopefully the Beans 2 JSR will improve the situation).
What you *might* be able to do is to provide a module that includes the ExPropertyEditor subclass and a custom BeanInfo it registers for your bean class. The utility in the blog here won't help much with that, but if you unzip the nbm it generates (just use command line unzip or unjar) and then unzip the module JAR inside it, that JAR's contents are the skeleton of the module you'd need - you'd just want to add a ModuleInstall class that registers your beaninfo or something like that. I think that would work.
Posted by: timboudreau on December 10, 2006 at 05:15 PM
-
Many thanks - using that approach I've managed to get the customer property editor recognised (the installer registers it with FormPropertyEditorManger).
The next problem however is ClassLoader related: in the setAsText() method of my custom property editor, I'm getting a class mismatch. Basically I have two instances of MyBean.class that have come from different class loaders, and therefore are not considered the same. The one that is being passed in to the setValue() method is loaded by org.netbeans.modules.form.project.ProjectClassLoader, but the one that is referenced in the editor itself is loaded from a org.netbeans.StandardModule$OneModuleClassLoader instead.
Now I am waaaay over my head. I cannot understand the class loader chains from the Developer FAQ entries, and there seems to be little else in the way of documentation for this.
Any advice on where to go from here?
Thanks, Paul.
Posted by: pszego on December 10, 2006 at 07:46 PM
-
These things are fun :-/
Send me an email and I will point you to the right person to get you an answer (I don't want to blog anyone's email address but my own - which is tboudreau at sun dot com). Or ask on the openide dev mailing list.
Here's a start, perhaps: You can get a global classloader with access to all modules' classes via Lookup.getDefault().lookup (ClassLoader.class). Not sure that will help you since it may not control when the class is loaded.
You might get somewhere with registering your property editor with plain-old PropertyEditorManager, but I'm not sure and that may already be happening anyway.
Posted by: timboudreau on December 10, 2006 at 08:08 PM
|