Monday Jun 30, 2008

Spring RCP Meets NetBeans IDE

Spring RCP tooling in the Plugin Portal, since today, which makes sense in combination with Getting Started with Spring RCP, a tutorial that is available on Javalobby.

Friday Jun 27, 2008

User FAQ Search Inside NetBeans IDE

Over on NetBeans Zone today, I speculated about one interesting scenario that is possible in relation to the new Quick Search feature—plugging the NetBeans User FAQs into the Quick Search. Well, I figured out how to do it and this would be the result:

So, the user would be curious about CVS in NetBeans IDE. The user would then type "CVS" and get (1) all the related FAQs, as well as (2) the action for opening the CVS window. Many similar results could be imagined, combining actions (and types) in the IDE with FAQs which, when clicked, would open in the browser.

The parsing code is very slightly different, i.e., just the code in bold below is different to that found on NetBeans Zone:

Document doc = tidy.parseDOM(url.openStream(), null);
//Get all "a" elements:
NodeList list = doc.getElementsByTagName("a");
//Get the number of elements:
int length = list.getLength();
//Loop through all the "a" elements:
for (int i = 0; i < length; i++) {
    String href = null;
    if (null != list.item(i).getAttributes().getNamedItem("href")) {
        //Get the "href" attribute from the current "a" element:
        href = list.item(i).getAttributes().getNamedItem("href").getNodeValue();
    //Get the the node value, i.e., <a href="foo">value</a>:
    if (null != list.item(i).getChildNodes().item(0)) {
        String title = list.item(i).getChildNodes().item(0).getNodeValue();
        //If the node value matches the requested text:
        if (title.toLowerCase().indexOf(request.getText().toLowerCase()) != -1) {
            //Add the runnable and the title to the response
            //and return if nothing is added:
            if (!response.addResult(new OpenFoundArticle(href), title)) {

Now imagine if we plugged the NetBeans Developer FAQ into the Quick Search feature too. You'd be able to get a lot of information from searches that combined both these FAQs. Then add tutorials, community docs, and NetBeans Zone. For very little work the user would end up with an incredibly powerful search mechanism across all our documentation... and all of it right inside the IDE, with the Quick Search constantly only a Ctrl-I click away.

Wednesday Jun 25, 2008

Quick Search API

The 6.5 Milestone 1 New and Noteworthy document (which is a work in progress since 6.5 M1 has not yet been released and is scheduled for release during the coming weeks) talks, among many other things, about something called "Quick Search".

The description says: "Quickly search for action or type is now easy. Use Ctrl-I." The two related documents are in the Wiki and on So, wherever you are in the IDE, you're able to press Ctrl-I, then you find that the cursor is in the Quick Search, you type the letter of something you're interested in opening into the Quick Search, and the results are shown:

Select an item and the related action is invoked, in the case of the actions, or the type is opened in the editor, in the case of the types. That's all very nice. What's nicer is that there's a new API that lets you plug your own items into the Quick Search functionality. Even better is the fact that there's a new wizard to support this. Take the following steps (using a build from today or later):

  1. Create a new module.

  2. Click Ctrl-N to bring up the New File dialog and then choose Module Development | Quick Search Provider:

  3. Click Next and then fill out the last step of the template:

  4. Click Finish and then look in the layer.xml file and you should see this:

        <folder name="QuickSearch">
            <folder name="Beatles">
                <attr name="command" stringvalue="Beatles"/>
                <attr name="position" intvalue="0"/>
                <file name="org-nb-beatles-BeatleSearchProvider.instance">
                    <attr name="SystemFileSystem.localizingBundle" 

  5. Then look at the generated class and you should see this:

    package org.nb.beatles;
    import org.netbeans.spi.quicksearch.SearchProvider;
    import org.netbeans.spi.quicksearch.SearchRequest;
    import org.netbeans.spi.quicksearch.SearchResponse;
    public class BeatleSearchProvider implements SearchProvider {
         \* Method is called by infrastructure when search operation was requested.
         \* Implementors should evaluate given request and fill response object with
         \* apropriate results
         \* @param request Search request object that contains information what to search for
         \* @param response Search response object that stores search results. Note that it's important to react to return value of SearchResponse.addResult(...) method and stop computation if false value is returned.
        public void evaluate(SearchRequest request, SearchResponse response) {
            //sample code
            //for (SearchedItem item : getAllItemsToSearchIn()) {
            //    if (isConditionSatisfied(item, request)) {
            //        if (!response.addResult(item.getRunnable(), item.getDisplayName(),
            //	      item.getShortcut(), item.getDisplayHint())) {
            //	      break;
            //	  }
            //    }

  6. Now begin working with the generated class so that it will do something useful. Begin by setting a dependency on UI Utilities API so that you can use the URLDisplayer class, which will open the browser with the URL to the Wikipedia entry of the selected Beatle, which is simply the little scenario we'll go through below. Then change the class above to the following:

    package org.nb.beatles;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import org.netbeans.spi.quicksearch.SearchProvider;
    import org.netbeans.spi.quicksearch.SearchRequest;
    import org.netbeans.spi.quicksearch.SearchResponse;
    import org.openide.awt.HtmlBrowser.URLDisplayer;
    public class BeatleSearchProvider implements SearchProvider {
        public void evaluate(SearchRequest request, SearchResponse response) {
            String[] beatles = {"john", "paul", "ringo", "george"};
            for (String beatle : beatles) {
                if (beatle.toLowerCase().indexOf(request.getText().toLowerCase()) != -1) {
                    if (!response.addResult(new BeatleFoundResult(beatle), beatle)) {
        private static class BeatleFoundResult implements Runnable {
            private String beatle;
            public BeatleFoundResult(String beatle) {
                if (beatle.equals("john")) {
                    this.beatle =
                } else if (beatle.equals("paul")) {
                    this.beatle =
                } else if (beatle.equals("ringo")) {
                    this.beatle =
                } else if (beatle.equals("george")) {
                    this.beatle =
            public void run() {
                try {
                    URLDisplayer.getDefault().showURL(new URL(beatle));
                } catch (MalformedURLException ex) {
                         getName()).log(Level.SEVERE, null, ex);

  7. Install it (do a restart if installing into the development IDE) and then press Ctrl-I anywhere and you'll find the cursor in the Quick Search field where you can start typing. If the letter you type is anywhere in one of the items you added to the Quick Search, the item is shown. So here I typed "o", which is found in "john", "ringo", and "george", but not in "paul":

    Select the item, the browser opens, displaying the Wikipedia entry on the selected Beatle.

  8. Once you've selected an item, it is automatically stored in the "Recent Searches" category, so that it is easier to see next time you do a quick search.

How useful is it to be able to search for the Beatles inside NetBeans IDE? Not very. But this is just a simple example. Imagine that this was not NetBeans IDE, but your own application with its own domain-specific data. Being able to plug relevant parts of that data, or ui from the application itself, into the Quick Search feature could be a pretty powerful aid to your end users.

Tuesday Jun 24, 2008

NetBeans and BlackBerry Development

One of the many people I met at the NetBeans booth in Manila last week was Nestor Fernandez:

Nestor is interested in using NetBeans for BlackBerry development. Can someone tell him what he should do to get started?

One thing is to google for answers. I found several articles and blog entries, including these:

However, there doesn't seem to be a BlackBerry plugin for NetBeans IDE 6.x. At least, that's the way it seems to be from my googling. Can someone clarify on this point and give Nestor some place to start with NetBeans and BlackBerry development?

And thanks for sending the pic, Nestor!

Options Dialog Framework in NetBeans Platform 6.5

The Options Dialog and SPI is nothing less than a complete framework for providing your user with a dialog for customizing the application you've created for them. As such, it gives you a complete dialog, i.e., the Options window, into which you can plug additional JPanels and then use the NbPreferences API to let the user set/store/retrieve the customizations you've let them set in the JPanels.

The good news is that this framework will be improved in three significant respects for NetBeans Platform 6.5:

  • The new org.netbeans.api.options.OptionsDisplayer class lets the user programmatically open the Options window with a specific category/subcategory selected.

  • The new OptionsController.createAdvanced method lets you create new subtabs within any tab that makes use of this method, so that any of your own tabs can have subtabs just like the Miscellaneous panel already does.

  • The Options Panel wizard has been changed so that a primary panel can be created that makes use of the item described above, so that any secondary panel that is created (either via the same wizard or manually) can (optionally) be a subtab within one of the primary panels that allow secondary panels.

The related JavaHelp and tutorials will be changed accordingly.

Together, these changes allow for more flexibility in the creation of Options windows, as well as the ability for the plugin/application developer to specify exactly which of the categories/subcategories should be opened at any point in time, which especially makes sense in the context of an ever-growing Options window. Perhaps you've created support for framework XYZ, for example, so that now you'll be able to let the user (via some action, for example) open a very specific XYZ-related category/subcategory within the Options window, one that is enriched with a range of subcategories, which was never possible before. Hurray.

Monday Jun 23, 2008

Notes for NetBeans Platform 6.5 Milestone 1

I've been looking at recent builds for a few weeks, making changes to the JavaHelp in the NetBeans Platform area. Here are my notes, which will be formalized later so currently is just a draft:
  • API Changes: See NetBeans API Changes Since Last Release.


    • New Code Generator SPI
    • User can drop text into palette
    • Loaders are registered in layer
    • No need for DataLoaders anymore
    • New OutlineView component replaces TreeTableView component
    • New resource bundle properties for window system customization
    • Image methods in Utilities class now replaced by new ImageUtilities class

  • NetBeans Platform Tooling Changes:

    • Code Generator wizard. New, supports the new Code Generator SPI.

    • Window component wizard. New field in wizard for keeping preferred size when minimized.

    • Options Panel wizard. "Create Secondary Panel", i.e., upper part of the wizard, lets you add a subpanel to an existing panel, not just the Miscellaneous panel.

    • File Type wizard. No more DataLoader and BeanInfo class generated. Instead, this is how DataObjects are now registered:
      <folder name="Loaders">
          <folder name="text">
              <folder name="x-abc">
                  <folder name="Actions">
                      <file name="org-openide-actions-CopyAction.instance">
                          <attr name="position" intvalue="500"/>
                      <file name="org-openide-actions-CutAction.instance">
                          <attr name="position" intvalue="400"/>
                      <file name="org-openide-actions-DeleteAction.instance">
                          <attr name="position" intvalue="700"/>
                      <file name="org-openide-actions-FileSystemAction.instance">
                          <attr name="position" intvalue="200"/>
                      <file name="org-openide-actions-OpenAction.instance">
                          <attr name="position" intvalue="100"/>
                      <file name="org-openide-actions-PropertiesAction.instance">
                          <attr name="position" intvalue="1300"/>
                      <file name="org-openide-actions-RenameAction.instance">
                          <attr name="position" intvalue="800"/>
                      <file name="org-openide-actions-SaveAsTemplateAction.instance">
                          <attr name="position" intvalue="1000"/>
                      <file name="org-openide-actions-ToolsAction.instance">
                          <attr name="position" intvalue="1200"/>
                      <file name="sep-1.instance">
                          <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
                          <attr name="position" intvalue="300"/>
                      <file name="sep-2.instance">
                          <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
                          <attr name="position" intvalue="600"/>
                      <file name="sep-3.instance">
                          <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
                          <attr name="position" intvalue="900"/>
                      <file name="sep-4.instance">
                          <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
                          <attr name="position" intvalue="1100"/>
                  <folder name="Factories">
                      <file name="AbcDataLoader.instance">
                          <attr name="dataObjectClass" stringvalue="org.nb.demomodule5.AbcDataObject"/>
                          <attr name="instanceCreate" methodvalue="org.openide.loaders.DataLoaderPool.factory"/>
                          <attr name="mimeType" stringvalue="text/x-abc"/>

      Here's what you get when you now complete the File Type wizard:

      Related document:

    • Project Properties dialog box. Right-click an application, choose Properties, and now you have a new tab in the Project Properties dialog box, called "Window System". Use it to tweak whether the windows should be draggable, resizable, maximizable, etc.

I will get the above notes verified and they'll be part of some kind of release notes at some point.

Sunday Jun 22, 2008

Typhoon Frank

Typhoon Frank hit Manila during the 2nd day of the NetBeans Platform Certified Engineering course, i.e, Saturday, 21 June. At some point I remember asking one of the students: "So I've been told there's a typhoon in the Philippines. Do you know where?" And he replied: "Outside that window." It was raining pretty hard but I wouldn't have ascribed that to a typhoon.

Back in the hotel, at about 2 A.M, I followed the Holland-Russia match via a Dutch Internet radio station on my laptop. Very exciting stuff, though Holland didn't get into the game at all, from what I gather. (Chuk's comment that Holland does well at the start of competitions like this one and then does badly afterwards, makes sense now, and aligns with comments that Holland peaked too soon.) One of the radio commentators, Jack van Gelder, is a really great commentator. It was almost as if I was there, his descriptions and excitement was so vivid, to the point where the other commentators on the program paled into nothingness in comparison. I'm sure Guus Hiddink's Dutch football experience played a big role in Russia's victory. I think it's great that he has another big success in his illustrious career. Is there another coach in the world that has a track record that comes even close to his? South Korea, Australia, and now Russia. He's put them on the map as footballing nations. I've heard that a museum in his honor has been set up in his birthplace in Holland and that the most frequent visitors there are from South Korea. That's kind of funny. I think he's less appreciated in Holland than he is elsewhere because he is so typically Dutch. There's nothing too special about him apart from his Dutchness and his Dutch approach to things. That's what enabled him to cut through the age hierarchies between players in South Korea, for example.

Then in the morning as I was checking out, I was told the airport was closed because of the weather. Eventually I got there, with a taxi, through flooded streets (the taxi had to stop several times to take a deep breath before plunging into yet another long stretch of ankle-deep water) accompanied by someone else from the hotel who was going there too. As I got in through security at the entrance to the airport, the power failed and everyone (thousands of waiting passengers in the check-in queue) found themselves in pitch darkness (and stifling heat, without any kind of air conditioning or the smallest breath of wind). Many hours later I managed to check in. The commercial lights of western capitalism beyond the customs control section, behind the check-in counters, were like beacons of hope in the almost inhumane situation in the check-in queue. Through an odd twist of fate I ended up sitting in the emergency row, i.e., the row with most leg room. The KLM cabin crew were exceptionally hospitable, at least partly because they'd seen the conditions in which we'd been queueing at the check-in counters.

But then my flight arrived in Amsterdam a few hours later than planned and so I missed my connecting flight. Via a small trick I managed to get into the airport lounges that Roumen had introduced me to when we flew back from JavaOne. Life is much more sane here and there are free snacks and liquor as well as wireless. I'll return to Prague first thing in the morning.

However, I hope Tim got out of Manila ok, because he left the day after me, so he must have felt the effect of the typhoon far more than I did. Also, of course, my mind is with the people in the Philippines who are undergoing these extreme weather conditions. Pretty wacky to experience a typhoon first hand for the first time, even though only a very early stage of it. But the full brunt of the storm must be another thing altogether.

Before I forget, here's a pic I received from one of the people who visited the NetBeans booth at the Manila Sun Tech Days, after I demonstrated the Shakespeare/FreeTTS demo (mentioned in previous blog entries) to this group:

More pics from the same series can be found here!

Saturday Jun 21, 2008

Philippines on the NetBeans Platform

Tim and I spent the last two days (yesterday and today) delivering the NetBeans Platform Certified Training to instructors from the JEDI project in Manila, at the University of the Philippines. JEDI is a collaborative courseware project that aims to make free Computer Science instructional materials based on Java. It started in 2005 and now has 180 member schools throughout the Philippines.

Here's a pic of the whole group at the end of the course:

And this is a pic of the lecture room where we did the presentations:

In the afternoons, we did exercises in the department's computer lab, shown below:

Thanks a lot to the very energetic Rom Feria and the rest of the class, we had a very good time and managed to communicate a lot about the platform. Since the majority of our students are trainers themselves, at least some of them will be delivering the course to others in the region, once the certification process has come to an end. We're looking forward to that—it will be very cool to have some of our students pass on the message of the NetBeans Platform, making use of the materials that we presented in the last two days. By that time, there should be work books with exercises and so on for students and the website will be used to exchange customized lesson plans, teaching tips, and so on.

The dedicated site for this particular course, which includes more photos, can be found here.

In other news. Tomorrow I fly back to Prague via Amsterdam. I predict that by that time Russia will have been pulverized (i.e., something like 4-0) by Holland in the upcoming quarter final match in Euro2008. On the other hand, in the unlikely event that Russia wins, I wouldn't be extremely upset, because I really like their coach (Guus Hiddink, from Holland) and it would be yet another feather in his very large cap.

Friday Jun 20, 2008

My First Plugin Officially in the Plugin Manager

In How to Get a Plugin into the Plugin Manager, I reported on the general process for promoting your plugin into the update center of the Plugin Portal. The Plugin Portal update center is registered in the 6.1 Plugin Manager by default, so that your plugin will be available to users, on an equal footing with all other plugins, but only if you manage to get your plugin into the Plugin Portal update center.

So a few days ago I noticed on my Zip NBMs plugin page on the Plugin Portal that a majority of the verifiers had positively verified it:

When I then went to the Plugin Manager, I made sure that the Plugin Portal update center is enabled:

And then... I saw my plugin in the Plugin Manager, for the 1st time!

Now I will never need to tell users to download the plugin from the Plugin Portal. They'll simply need to get it from the Plugin Manager.

By the way, I wonder if there's some convenient way in the plugin's Plugin Portal page to say "there's no need to click the Download button anymore". Maybe plugins that are available in the Plugin Portal need to have some clear message like that because simply the fact that something is noted as being verified is not enough information for the uninformed user to know that that means that the plugin is now automatically available in the Plugin Manager.

Today on NetBeans Zone. On NetBeans Zone, I interviewed Allan Harris, who is creating support for Python in NetBeans IDE. Click here to get to the interview and, if you like the interview, please vote it up (i.e., click the green arrow in the top left of the article) so that it will increase in popularity and draw more people's attention. Seems to me that Allan is doing some great work creating the Python support and I will be trying it out soon.

In other news. Remember the Breadcrumb plugin that Tim was making at the NetBeans booth in Manila a few days ago? Well, now it's become really sophisticated. Whenever you open a new document, it is added to the breadcrumb list, which is now in the bottom right of the IDE:

When you click any of the entries, the related document opens. When you hover over the entries, they scroll left and right automatically. When you right-click an entry, you get a popup with the options shown below:

Pretty cool stuff. It will be in the Plugin Portal soon! (In fact, here it is.)

Wednesday Jun 18, 2008

Sun Tech Days, Day 2, Manila, 2008

I spent the day at the NetBeans booth and learned the following things:

  1. MySQL VP Kaj Arnö likes NetBeans. A lot. I met Leonid, who is Vladimir Voskresensky's manager at Sun in St. Peterburg. Vladimir is known in the NetBeans community as the main engineer behind the C/C++ support for NetBeans IDE. He learned Java from scratch while writing the plugin for C/C++ in NetBeans and he was interviewed some years ago here. Anyway, Leonid told me that yesterday Vladimir demoed how MySQL can be developed within NetBeans to Kaj Arnö. As a result, Kaj Arnö has a new favourite answer to the request "so tell me an example of technical advantages resulting from Sun’s acquisition of MySQL". Read all about his rave review of Vladimir's demo yesterday here in his blog. By the way, Vladimir's also in the final stages of having a completed Russian translation of "Rich Client Programming: Plugging into the NetBeans Platform". Is he a rock star or what.

  2. Today I saw more teachers in one room than I've seen since leaving high school. Seriously, every other person I spoke to handed me a business card from a university. Several of them were introduced to and will start participating in it soon—contributing Java lesson plans and downloading those provided by others. That's great news and completely unexpected. Several of them will be in the NetBeans Platform Certified Engineering course tomorrow and seemed to be really looking forward to it. Plus, a few random people who Tim and I met will also be joining the course, so it sounds like there should be around 25 people there in total, tomorrow and Saturday from 9.00 to 14.00.

  3. Ruth's Tips & Tricks book is the hottest thing in town. I feel sorry for Ruth—I must have sent her something like 15 different e-mails today with the names of people who want to beg, borrow, or steal the 100 NetBeans Tips & Tricks book. And that was only those who asked about it after I decided to write to her every time someone came to ask the question, rather than write it down in my notebook and postpone forever the actual sending of the emails in question. I hope the book will be publicly available soon, with its own site and so on, but I believe that that hasn't quite happened yet.

  4. JFugue and FreeTTS are great for demos. I did a fun demo (described elsewhere in this blog some years ago), consisting of a web service client that integrates with a Shakespeare text retrieval web service, with the results recited by "kevin16", once of the voices provided by FreeTTS, who then recites the returned Shakespeare text. Similarly, I did a demo where the user types some letters into a text field (from A to G) which is then played back as notes by means of the JFugue JAR. These are fun demos to do, highlighting the fun aspect of Java programming while enabling you to promote open source and showing how a variety of different technologies and tools can be mashed up together to create relatively useful results.

  5. Groovy is hot in the Philippines, Wicket is hot in Singapore. At some point I thought I should count the number of people who asked me about Groovy and NetBeans. Apart from the questions "can I have a NetBeans t-shirt" and "can I have a tips and tricks book", one of the next most common questions must have been about Groovy. And get this—I met two Wicket enthusiasts from Singapore who work there for Sun. So I demoed the Wicket plugin to them. They said that they can see a clear increase in interest in Wicket, not just in Singapore but more generally too. It's lightweight and clean and you avoid the intricacies of JavaScript when doing Ajax. So, they were very favorably impressed about it and have been discussing it with their customers.

I'm hoping to be able to publish several photos taken at the booth, during the coming days. Inevitably, my camera's battery died at the moment I tried to take my first pic of the day, but several of the booth's visitors took pictures and should be sending them to me soon. It was really cool to meet them all.

Finally, I demoed two hidden NetBeans features, both of which are very impressive. I learned about both of them in the last two days and, no, neither of them are keyboard shortcuts. They're extremely substantial features that have been part of NetBeans for a while... and I'll discuss them here (or on NetBeans Zone) soon.

Sun Tech Days, Day 1, Manila, 2008

It was a funny day where many things happened, i.e., day 1 of Sun Tech Days 2008 in Manila, Philippines. Most of the day I was at the NetBeans booth in this sumptious hotel where we're all staying and where the conference is being held. The cool thing about that was that I was able to prepare my presentation for 17.30 this afternoon, named "Using NetBeans for Your Existing Projects", while sitting at the booth. (I also did quite a bit of work for Javalobby while there.) The problem statement is that it's easy for NetBeans enthusiasts to say "just download NetBeans and start it up, then you'll be able to use it right away". However, in the real world, you have existing projects, rather than new ones. How can you bring those existing projects into NetBeans (or use them from within NetBeans)? That's what my presentation was about and here it is:


About 500 attended (the photo would have been almost the same as yesterday's, so I didn't make one) and I gave away several of Ruth's "100 NetBeans IDE Tips & Tricks" books (which were in great demand), as well as some t-shirts, to those who answered my obscure questions correctly. Two t-shirts were given away to people who got the anagram in the Anagram Game correct (one of the answers was "unabstentious", which is a bizarre word in every sense). I showed how the NetBeans Ant-based project system works, how to work with JUnit sources in Eclipse and NetBeans, via the Eclipse importer, how to work with Spring (or any web application) in Eclipse and NetBeans, how to import an application (JEdit) that already has a build.xml file, as well as how to work with a Maven project in Eclipse and NetBeans. The argument wasn't so much that "you should move from Eclipse to NetBeans", but "both Eclipse and NetBeans are great tools, and this is how you can benefit from the best of both of them".

Wen Huang, from the Sun marketing area, was also at the booth. He told Tim and I about the fact that Eclipse's latest release comes with "breadcrumbs" for opened documents. That I remembered seeing (and liking) in IntelliJ:

Tim immediately set about creating the same functionality for NetBeans IDE. His version consists of JLabels, but I've been playing with JCheckBoxes instead:

And here's the two of us in a mock pose, i.e., the pose that one typically finds in brochures that include computers:

We met lots of nice people, some of whom wanted to be in a photo with us or get our autographs, which was always fun:

I talked to Chuk Munn Lee for the first time in forever. He's one of my favorite Sun speakers. I attended part of his Groovy/Grails session (the only session other than my own that I attended today). He said he knew about the new NetBeans support for Groovy/Grails but that he hasn't had the time to play with it yet. I'm hoping that his next Groovy/Grails session will include NetBeans tooling. By the way, Chuk doesn't think that Holland has much of a chance in the Eurocup. Seems like he thinks the first two MASSIVE victories were flukes or something. He does fancy Portugal, though. His prediction is Portugal-Holland in the final, after I spent some minutes persuading him of Holland's newly found brilliance. I mean, come on, 3-0 against Italy followed by 4-1 against France. How can you argue about that?

The evening ended with Tim and me at the hotel bar, listening to a skimpily dressed trio of girls (backed by three guys on drums and guitar) singing selected items from the genre that includes "smooth operator" and "as soon as forever is through, I'll be over you". I made a picture but it ended up looking a bit dubious so I decided not to post it here. :-)

Tuesday Jun 17, 2008

NetBeans in Manila

Click the pic above for details...

Monday Jun 16, 2008

Limiting the NetBeans Window System in NetBeans Platform 6.5

If you're building your application on top of NetBeans Platform 6.5 M1 and above (or, since M1 isn't released yet, just get the very latest development build from, you'll be able to limit your window system's functionality. Your application's window system comes straight from the NetBeans Platform, but you've never been able to tweak it much. That's been something several people have asked for. They want to, for example, create a fixed layout for their application's user interface. Therefore, they don't want the end user to move the windows around (and/or to undock them, slide them into the sides of the application, etc).

Until a few days ago, there were several nasty hacks you could make use of in this situation. In the most extreme case, you'd want the window system to be frozen, while in less extreme cases you'd only want some of the functionality to be unavailable to the end user. Reading Window System API guru Stan Aubrecht's blog today, you'll quickly see that this will now no longer be a problem. On suites (i.e., either the container for modules or the NetBeans Platform Application project type itself), there'll be a new tab in the Project Properties file, as follows:

By default, all the checkboxes are selected, so all the powerful features of the window system are available by default. But, depending on which checkboxes you uncheck, one or more of the features will be removed. By the way, the Help button in the screenshot above currently returns no content because it needs to be added (by me).

If ALL the checkboxes are selected, a properties file with this content is generated in the "branding" folder (which is visible when you look in the Files window, for NetBeans Platform applications):


If all of the above are set, the small X in the tab of all the windows will not be there, so that the windows can't be closed, as well as all the other features being disabled. The above file is found (i.e., it is created for you when you select one/more of the checkboxes above) in the following location:


You could create that file yourself and add the content above yourself, however, using the checkboxes in the new tab is obviously easier.

For further reading, go as always to the NetBeans API Changes document and there read the item Added a group of resource bundle properties for customization of window system behavior.

Sunday Jun 15, 2008

From FileObjects to Projects

Finding the Project that the FileObject belongs to and then getting information about the Project, in this case in a class that extends
public void targetStarted(AntEvent event) {
    File buildImplXML = event.getScriptLocation();
    FileObject buildImplXMLFo = FileUtil.toFileObject(buildImplXML);
    String targetName = event.getTargetName();
    //Get the project that the FileObject belongs to:
    Project proj = FileOwnerQuery.getOwner(buildImplXMLFo);
    if (null != proj) {
        //Get the project information from ProjectUtils:
        ProjectInformation info = ProjectUtils.getInformation(proj);
        //Get the project display name from the project information:
        String projectName = info.getDisplayName();
        //Get the project icon from the project information:
        Icon icon = info.getIcon();
        //Process the information further, depending on your needs:
        if (targetName.equals("run")) {
            ListDeployedAppsAction.setProjectNames(buildImplXML, projectName, icon);

As a result, there's no need to parse the project.xml as I had been doing a few days ago, for the project name and type. Thanks to Jesse for recently pointing the above out to me.

Saturday Jun 14, 2008

Holland 4 - France 1

Some celebratory pics from last night:

Thursday Jun 12, 2008

News from

I'm visiting Wouter van Reeven at AMIS Technology in Nieuwegein, Holland (because guess what major world sporting event is happening tonight?) and walked him through the sources of the project. As a result, he updated the RichFaces JARs to the latest release and added one RichFaces code snippet to the JSP palette. Now that he knows how to do that, there should be nothing stopping him—expect many more code snippets in the coming days/weeks/months.

Here he is in action, right before he committed his snippet and the latest JARs:

He's also going to be sharing project ownership of with me.

On top of that, the good news is that Holland is going to beat France 2-1 tonight. You heard it here first.

In other news. Read Wouter's version of the above story here!

Wednesday Jun 11, 2008

Keyboard for the JFugue Music NotePad!

The JFugue Music NotePad received a big code contribution a few hours ago—a complete, functioning keyboard! See the bottom window in the screenshot below:

The contribution comes from Mark Valeri, who has been an active contributor for quite some time already.

It's really cool. Whenever you press a key on the keyboad, the note is added to the music sheet and to the JFugue command window.

Also this morning, the project moved from JFugue 3.2 to JFugue 4.02, which is the latest release of the API. However, we're still on NetBeans Platform 5.5 and need to move to 6.0 in the coming weeks. You can check out the sources from CVS and then run it from the IDE to get the above result.

In other good news, for a mere $25, you can get the very recently released "The Complete Guide to JFugue", by Dave Koelle, the API's author. I have a copy and it is really good, well written, lots of code samples, etc. The absolute Bible to JFugue and a must have for any music programmer:

Click the above to get to the book's page, where you'll also find some free sample chapters.

Tuesday Jun 10, 2008

Statistics: They Can't Be Serious (Part 2)

I've mentioned the stupidity of surveys and statistics before, in Statistics: They Can't Be Serious. Today they Guardian has another one (again relating to tennis):

Go here to read it online or page 17 of the printed version.

What bugs me in particular is encapsulated in this sentence: "Swiss neuro-scientists found regular players were better at spotting subtle differences in speed, location and trajectory than others."

Isn't that the same as saying: "Regular swimmers can swim better than those who don't swim regularly?" Or: "People who read books regularly read better than those who don't?"

Or: "Stupid people who regularly put together silly statistics come up with dumber statistics than those who don't and aren't?"

Code for Rerun DropDownButtonFactory

I made some serious progress with my redeploy plugin today. Since it was inspired by Gareth Uren, who liked this functionality in Eclipse and misses it in NetBeans IDE, I decided I should try to make it as similar as possible to how it works in Eclipse. So, here it is, no longer in a separate window, but using the NetBeans org.openide.awt.DropDownButtonFactory class:

Let's step through the code required for this functionality. First, I have extended, which is exposed in META-INF/services, in a file called "":

public class StoreDeployedApps extends {

    public boolean interestedInSession(AntSession session) {
        return true;

    public boolean interestedInAllScripts(AntSession session) {
        return true;

    public String[] interestedInTargets(AntSession session) {
        return AntLogger.ALL_TARGETS;

    public void targetStarted(AntEvent event) {
        BufferedReader br = null;
        try {
            //Get the build-impl.xml:
            File buildImplXML = event.getScriptLocation();
            //From the build-impl.xml parent, get the project.xml:
            File projectXML = new File(buildImplXML.getParentFile(), "project.xml");

            String targetName = event.getTargetName();
            String projectName = null;
            String projectType = null;
            //Read the Dom and figure out the project name and type,
            //where the type is a string like "":
            InputSource source = new InputSource(new FileInputStream(projectXML));
            org.w3c.dom.Document doc = XMLUtil.parse(source, false, false, null, null);
            org.w3c.dom.NodeList nodeList = doc.getElementsByTagName("\*");
            int length = nodeList.getLength();
            for (int i = 0; i < length; i++) {
                org.w3c.dom.Node currentNode = nodeList.item(i);
                String nodeName = currentNode.getNodeName();
                if ("name".equals(nodeName)){
                    projectName = currentNode.getTextContent();
                if ("type".equals(nodeName)){
                    projectType = currentNode.getTextContent();
            //If the target name is run, send the build-impl.xml, the project name,
            //and the project type to our action class:
            if (targetName.equals("run")) {
                ListDeployedAppsAction.setProjectNames(buildImplXML, projectName, projectType);
        } catch (SAXException ex) {
        } catch (IOException ex) {
        } finally {
            try {
            } catch (IOException ex) {

    public void targetFinished(AntEvent event) {

And here's the action class, which is registered in the layer.xml file, just like any other action class that we want to be able to invoke from a toolbar button:

public class ListDeployedAppsAction extends CallableSystemAction {

    private static JButton dropDownButton;
    private static JPopupMenu popup;
    static JMenu menu;
    static void setProjectNames(File buildImplXML, String projectName, String projectType) {

        Image icon = null;

        if (projectType.equals("")) {
            icon = Utilities.loadImage("/org/netbeans/modules/java/j2seproject/ui/resources/j2seProject.png");
        } else if (projectType.equals("org.netbeans.modules.web.project")) {
            icon = Utilities.loadImage("/org/netbeans/modules/web/project/ui/resources/webProjectIcon.gif");
        } else {
            icon = Utilities.loadImage("/org/netbeans/modules/project/ui/resources/runProject.png");

        ImageIcon image = new ImageIcon(icon);

        menu = new JMenu();
        JMenuItem subItemRun;


        subItemRun = new JMenuItem("Run \\"" + projectName + "\\" again");
        subItemRun.addActionListener(new RunActionListener(buildImplXML));



    static class RunActionListener implements ActionListener {

        File file;

        public RunActionListener(File file) {
            this.file = file;

        public void actionPerformed(ActionEvent e) {
            try {
                ActionUtils.runTarget(FileUtil.toFileObject(file), new String[]{"run"}, new Properties());
            } catch (IOException ex) {
            } catch (IllegalArgumentException ex) {

    public Component getToolbarPresenter() {

        Image iconImage = Utilities.loadImage("/org/netbeans/modules/project/ui/resources/runProject.png");
        ImageIcon icon = new ImageIcon(iconImage);

        popup = new JPopupMenu();

        dropDownButton = DropDownButtonFactory.createDropDownButton(
                new ImageIcon(
                new BufferedImage(32, 32, BufferedImage.TYPE_BYTE_GRAY)),


        return dropDownButton;


    public void performAction() {

    public String getName() {
        return "Deployed Apps";

    public HelpCtx getHelpCtx() {
        return null;

That's it. Next I need to add a submenu item for removing menu items. Maybe also a configuration dialog for tweaking the launch configurations that are registered in the list. By the way, in the process of moving my code from a window to a dropdown button factory, I was able to improve my code in several ways. Refactoring rocks. It really lets you look at your old code afresh.

Monday Jun 09, 2008

Rerun Deployed Applications

Playing with Eclipse launch configurations yesterday reminded me of my Deployment History window, which I mentioned a while ago (here and here), inspired by someone I met at the Sun Tech Days in South Africa. It does what it should do, nothing too fancy, so I uploaded it to the Plugin Portal:

You'll get a new window that reflects the applications that you've deployed, updated at each new deploy, and then you can right-click to rerun or remove the application from the list:

I'd like to rewrite it to use the NetBeans org.openide.awt.DropDownButtonFactory sometime.


Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.


« June 2008 »