Geertjan's Blog

  • January 31, 2007

JavaMail Client on the NetBeans Platform (Step 2)

Geertjan Wielenga
Product Manager
So, let's move our simple JavaMail client to the NetBeans Platform. At the end of this procedure, NetBeans IDE (or any application on the NetBeans Platform) will have a new "Mail Window", as shown in the "editor" area of the screenshot below:

The IMAP server, in this case, is accessed, the e-mails are retrieved, and displayed in their folders. Some can also be opened for reading, but as pointed out yesterday, there's some problem with that part of it in the original application. For a larger screenshot, click here.

When porting (i.e., migrating your Swing application to the NetBeans Platform), there are three really important principles. Only three? Yes. Only three. Here they are:

  1. Decide whether to reproduce or leverage. Ask yourself this question: Do you want to replicate your existing user interface and functionality or do you want to leverage the NetBeans Platform's idioms and infrastructure? This is an important question. A few blog entries ago, when I wrote about porting a movie player to the NetBeans Platform, I simply dumped the JFileChooser, because the NetBeans Platform's Favorites window provides the same (in fact, better) functionality... for free. No programming required. However, in this case, where the application is quite a lot more complex, let's begin by simply replicating (i.e., keeping as much of the original functionality as possible) the functionality, since that requires less re-work than the leveraging (i.e., where possible, replacing the original functionality with better functionality provided by the NetBeans Platform) approach. Also, I don't really know the simple JavaMail client so well, and I don't know JavaMail very well either, therefore I'd rather not mess around with the internals of the application. However, the downside of this approach is that my application will not integrate very well with the NetBeans Platform. Ideally, each folder and e-mail would be represented by a node provided by the NetBeans Nodes API. But, since I'm not going to go down that route, I'll not have nodes. This means that it will be much more difficult to extend the module once I've created it. I mean, I could extend the module itself, but I won't be able to plug new functionality into the ported mail client, because I will have no extension points at my disposal. However, doing it the simplest way is probably the best way to go initially. Once everything is working okay, I can begin replacing the pieces with NetBeans API equivalents, such as a NetBeans API TreeTableView, for example.

    However, as you can see from this, porting is not a trivial task. It basically means, in many cases, if you want to do it properly, rewriting your application. And I can't imagine a wizard that would be helpful in automating the process. Not every JFrame should become a TopComponent, for example. (And you may as well use the Window Component wizard instead, anyway.) Despite the fact that porting isn't trivial, the further you port (i.e., the more you integrate) the greater will be the benefits that you gain, especially in the sense that you'll be able to expand your functionality in a modular, sustainable, scalable way -- even after distributing the module that contains the original functionality, without needing to redistribute the module.

  2. Get to know the entry point. Even if you don't know the application you're going to port very well, you can at least find its entry point. That is the hook to your application. You need to create some NetBeans API class that will access your application's entry point. That's really all you need, at the simplest level. In the case of the simple JavaMail client, the SimpleClient class is the starting point for everything else. Its constructor sets everything up, builds a JSplitPane from various other GUI elements, and then adds it to a JFrame. However, we're not going to use a JFrame. We'll use a TopComponent instead. So, what I've done is I've rewritten the constructor to return a JSplitPane (see my rewritten SimpleClient.java). In my TopComponent, I have a simple JButton (not shown in the screenshots above) that does the following in the actionPerformed():

    //Find simple.mailcap (needed
    //by activation.jar for finding viewers),
    //which is a workaround because the module
    //couldn't find it by itself:
    String mailCap = null;
    JFileChooser fc = new JFileChooser();
    int returnVal = fc.showOpenDialog(this);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
    mailCap = fc.getSelectedFile().toString();

    //Hard code the URL to the server,
    //which needs to be replaced by an Options window extension:
    String argsv[];
    argsv = new String[2];
    argsv[0] = "-L";
    argsv[1] = "imap://gw12345:password@my-mail-server.com";

    //Create new instance of SimpleClient, passing the
    //arguments defined above,
    //and return the JSplitPane,
    //which you add to a JPanel,
    //which you drag-and-dropped on the TopComponent:
    SimpleClient client = new SimpleClient();
    JSplitPane jSplitPane1 = client.main(argsv, mailCap);
    jPanel1.add(jSplitPane1, java.awt.BorderLayout.CENTER);

    By the way, maybe, instead of under the JButton, the above code would fit better in the action that opens the TopComponent.

  3. Start loving TopComponents. If you are going to port a Swing application to the NetBeans Platform, and you have some user interface that you want to migrate, you better start loving the TopComponent. This NetBeans API class is going to be your best buddy. It is simply a component that integrates into NetBeans Platform applications, providing the window you need. The JButton described above is in a TopComponent. (For non-GUI oriented applications, see the upcoming NetBeans Platform book for an excellent chapter by Jens Trapp, about porting a command-line-driven application to the NetBeans Platform.) So, just run the Window Component wizard, add a JButton to the TopComponent, stick in the code above, and then copy all the simple JavaMail client's classes into your module. Remember to replace the SimpleClient.java with my rewrite. There will be one or two minor tweaks in other files, because you are using a TopComponent instead of a JFrame. For example, the simple authenticator now applies to the TopComponent instead of the JFrame. Next, create a module suite project to which you add this module. Also add a library wrapper module containing the JavaMail JARs, as well as the Activation JAR. In your functionality module, set a dependency on the library wrapper, so that the JavaMail JARs (and Activation JAR) can be found by your code.

That's it. You're done. The Projects window should now show this (below I have selected only the additional files, i.e., those needed in addition to those provided by the original simple JavaMail client, to show how little needed to be added):

Note that all the additional files were created by wizards and required no coding for this porting procedure to work, other than the simple JButton described above.

By the way, in general, it is better to have a bug free and stable application, prior to porting it to the NetBeans Platform. Probably obvious, but worth pointing out. That way, you'll know that all your bugs relate to the ported version and not to the original.

Even though the ported simple JavaMail client has a lot of defects, described in item 1 above, it is already more useful than the original. Why? Well, I don't need to start up a separate process to read my e-mails... Also, now that the mail client is integrated in a TopComponent, it is part of a window system. As a result, it can be moved around and minimized, for example, just like any other window in the NetBeans IDE (or whatever application you've added it to). Importantly, this movement and minimization is a free gift that the mail client receives, for being in a TopComponent.

An easy next step is to create an Options Window extension where the user can set the username, password, protocol, and mail server. After that, one probably needs to take a deep breath and then... integrate the NetBeans Nodes API and replace the JSplitPane with a TreeTableView. Using the Nodes API, you would add nodes for the e-mail folders to a new explorer window. Then you would add menu items on the folders, for opening them in a TopComponent. How to do that will be described in a future installment in this series.

In other news. Have you made your NetBeans predictions for 2007 yet? No? Do so here.

Join the discussion

Comments ( 4 )
  • Tom Wheeler Wednesday, January 31, 2007
    This means that the NetBeans platform is now compliant with
    Zawinski's Law.
  • Geertjan Friday, February 2, 2007
  • Michael Kunta Sunday, July 15, 2007
    Ok, I finally got the modules to compile. Where I was going wrong was that I had to compile the mail Library Wrapper Module first to create the required files for the other modules.
    I have the program running but when I press the button a file chooser opens. I select the simple.mailcap in the NBPlatformMailClientUI folder but I do not get the SimpleClient displayed in the top component window.
    I know that the client has been created due to println statements.
    Any ideas?
  • guest Saturday, May 3, 2008

    Where's the code?

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.