Wednesday Nov 04, 2009

Goodbye Sun!

Today marks the end of a wonderful 9+ years at Sun for me.  I've been a Jiro Consultant, Network Storage Engineer, NetBeans Engineer, NetBeans Evangelist, and a Global Technology Manager.  I couldn't have asked for a more rewarding 9 years.

Sun has given the world so much for free (as in beer).  I'm happy that I was able to be part of that.  Sun has changed the world forever in a positive way.  Sun = Open Source.  Sun has set the standard for open source software.

 I have so many great memories working at Sun and cherish all the great Sunisms and Scottisms:

  • The Network IS the computer(for sure!)
  • .Not
  • "Kick butt and have fun!"
  • JavaOne
  • Beer bash Fridays
  • Sun Tech Days
  • SunTEA (made famous by IBIS)
  • Sun time (the real time people show up for meetings)
  • Work From Home, iWork, Open Work
  • "Please remove me from this alias" email storms
  • etc., etc.

 Thanks for the fabulous journey Sun!  I loved every minute.

Friday Jan 23, 2009

The Smart Phone Choice Just Got Tougher - Palm Pre

I saw something today that actually forced me to start blogging again.  It's not that I dislike blogging.  Mostly I don't have the time.  It seems like a luxury if its not a core part of your job.

So what brought me to blog.  I saw the press release screencast of the new Palm Pre at  CES.  Wow! I'm kind of shopping for a new smart phone.  Now my decision is much tougher.

So let me provide some context.  I've been carrying a Palm Treo 650 in my pocket for about 3.5 years now.  It mostly does what I need.  It has web browsing, email, all the PDA functions I've grown to love.  The web access is over WAP so things are very slow if you don't hit a WAP-friendly site.  I've been using PalmOS for as long as I can remember.  Remember the Palm V that made it's debute at JavaOne?  I had one of those.  I remember that conference everyone was walking into eachother and walls because they were staring down at their Palm.  So I'm pretty much a Palm-PalmOS guy.  Forget the Palm with Windows Mobile.  What possesed Palm?  Probably survival.

I've been lusting over the iPhone like everyone else.  I must admit things like no qwerty keyboard and no copy/paste kinda scare me.  But I was very ready to make the move.  Then I saw the AT&T plan rates, $30 for data and $30 for unlimited text messaging.  Yikes!  So on top of my base plan fee I have to add $60.  You see I have four kids who text me all the time and as you know you can't stop incoming text messages.  This is a mobile phone company conspiracy because they know that 98% of their revenue comes from teens texting (I'm making that up of course so don't use this for wikipedia).  So this stalled my compulsive urges to go with the iPhone.

Hey what about an Android phone?  Yeah!  The T-Mobile G1.  It comes with a touch screen AND a qwerty keyboard.  It's built on a much more open platform, Android, than the iPhone.  So I talked with my local T-Mobile store dude and he tells me to wait for a G2.  I asked when that's coming out.  He said the rumor was March but he doesn't have any real facts.  He said it's supposed to be way better and they got rid of the qwerty keyboard.  What?!  That's the one feature I really want.  Well so the G1's looking pretty good.  Then I look into T-Mobile's 3G network.  Or should I say the lack of it?  There's not even 3G coverage in the college town I live in.  Bummer!  So what's the point of having a 3G phone if I have to use EDGE or WAP to hit the internet.  I even thought about getting an unlocked iPhone and sticking with T-Mobile, my current carrier.  Then the T-Mobile store dude tells me that his unlocked iPhone doesn't work on the T-Mobile 3G network.  Huh?  Yep.  You can read all about what 3G really means for yourself on Wikipedia.

Then there's the Palm Pre.  I had to wipe the drool form the corner of my mouth as I watched the screencast because my brain was so intrigued with what I saw that it forgot to tell my mouth to swallow.  It has a touch screen AND a qwerty keyboard.  They kept the great Palm buttons like external volume controls, ringer off button, external speaker, and a new 3.0 MP camera with a flash.  The user interface is amazing.  The touch interface alone makes me want to get one to play with.  When you touch the screen, there's a mark on the screen where your finger is.  It also has this really cool feature called Synergy that does an incredible job at pulling your entire life together for the exact context you are currently in.  And the charger is over the top.  It's called the touchstone and there are no connections.  You get wireless charging through "inductive technology".  Now that's cool!   Here's the rain on my parade.  Palm has chosen Sprint to be the exclusive service provider.  I don't have anything against Sprint.  But if you travel outside the Americas, which I sometimes do, you can forget using your Sprint phone.  I experienced a similar pain when I went to Tokyo last year with my Palm Treo T-Mobile GSM phone.  I basically turned it off and put it away most of the time except for a few times I needed the PDA functions.  The Palm Pre is very "Sexy" though.  It might cause me to forget about GSM.  I really have to hand it to Palm.  I thought they were dead and now it looks like a great comeback move with the Pre.

In the end, maybe I'll stick with my Treo 650 for a while. :)


Wednesday Jun 25, 2008

I Have a New Job at Sun!

I just started a new job at Sun as the Technical Manager for the Sun Campus Ambassador program.  I'm really excited to broaden my scope of knowledge on Sun technologies.  So I hope to be blogging about more topics than just NetBeans.

I'm still planning to push one more version of the Plugin Portal so stay tuned for that.

Tuesday Apr 08, 2008

Improved NetBeans Plugin Portal


I just pushed a new version of the Plugin Portal.  This version has lots of new features.  The most important feature is the ability to reguest that your plugin gets verified for a version of NetBeans.  If the plugin is verified, it will show up in the "Plugin Portal".  I've also fixed some issues that most people will be very happy about.  You can now hit the "Enter" key when logging in or searching. :)  I know this seemed like an easy fix but believe me finding out how to do this was not easy.  I'll blog about it soon hopefully.  You can check out all the new features and fixed issues in the functional specification.

Wednesday Mar 26, 2008

NetBeans 6 Local History

As I was preparing to deliver a session on "New & Cool" for NetBeans 6, I realized I didn't really understand the benefits of a new feature called "Local History" so I did some investigation.  What is the real value of Local History over undo/redo?  Yes the visual differences window show below is nice.  But was is the real advantage?

Local History Diff


If you delete a chunk of code, you can restore it by reverting in local history.  I can easily do that with the undo.  I tested saving, deleting code, saving, then adding code and saving.  I expected local history to allow me to selectively undo the deleting code action while keeping my adding code action.  No dice.  Going back to a point in time adds back the deleted code but removes the added code.  

Answer

Local History is for entire file snapshots in time.  Think of it as a local SCM.  You can revert to a snapshot of a file at a certain time.  When is this useful?  Say you are coding away when you suddenly realize that you've followed an incorrect line of thinking.  You'd like to go back to where you were two days prior.  Well Undo is not going to get you there.  Local History saves the day!  Another Huge advantage of Local History is the "Revert Deleted".  Let's say you are doing some refactoring and you move major pieces of code out of a class and decide you can altogether delete the class from the project.  Then you realized that you forgot to move some critical code before deleting.  You can use Local History->Revert Deleted to restore every file you deleted in the project.  Again Local History has saved your bacon. :)

You can configure the number of days Local History holds on to versions of your files in the "Options-> Miscellaneous-> Versioning-> Local History" option.

Local History config

Wednesday Feb 06, 2008

Sun's Giving Away US$1 million to NetBeans Open Source Developers

Putting in lots of hours doing open source development and not getting paid for it?  Well Sun is putting it's money where it's heart is, open source.   Sun is giving US$1 million way to open source developers in the form of the NetBeans Innovators Grants.  Get paid for all the extra hours and hard work you put into open source.  At the same time, contribute to a hot open source community, NetBeans.  Don't sit around and think about it too long.  You only have until March 3 to enter a submission.   Then you have to August 4, 2008 to complete the project.

Thursday Nov 29, 2007

NetBeans Visual Web - JSF, "Pretty" URLs and Multiple Instances of the Same Page

Since I introduced "Pretty URLs" in the NetBeans Plugin Portal, there have been some strange things happening like issues 119249, 122600, and 122340.  Once again I've been schooled on the JSF life cycle.  So here's what's happening.

Problem

When a button or link is clicked on a page and an action is associated on the pages backing bean, a post back occurs.  For the purposes of this discussion, a post back basically means a request is sent from the displayed web page to the server, the page backing bean action method is executed, a null is returned from the method telling the JSF framework not to navigate anywhere, and the page is redisplayed using the JSF Standard Processing Lifecycle.  If you look at the how I used the JSF life cycle in my earlier blog titled, "NetBeans Visual Web Pack - Real World Apps Tip #4 - "Pretty" URLs", I took advantage of the Visual Web application model "init" method.  In the details of implementing "Pretty" URLs, the key piece of information for rebuilding the state of the page in the "init" would logically be put on the SessionBean.  For example, for the Plugin Detail page I need the "currentPlugin".  So when I navigate to the Plugin Detail page I set the "currentPlugin" attribute on the SessionBean and use that for all the details.  So now what happens when someone right-clicks on my "Pretty" URL and chooses to open a different Plugin in another tab?  The Plugin Portal stores the new Plugin as the "currentPlugin" on the SessionBean.  Now on the first plugin, I do some action like click the download button.  Now to the important part!  Remember that a PageBean gets instantiated EVERY time a page is displayed.  This means the PageBean for the first Plugin is instantiated and gets the "currentPlugin" from the SessionBean.  Things are now bad because the second Plugin in the other tab set "currentPlugin".  So you have results like described in the issues above.

Solution

The solution for this seemed easy at first, save each page instance state per Plugin.  This turned out to be quite difficult to implement.  Again I realized that the biggest difficulty when using JSF is understanding the Standard Processing Lifecycle.  I somehow needed to save off state from a page with uniqueness and pull that state back.  For example, if a detail page was showing for a particular Plugin and the user opens another instance of the page with a different plugin, we need to have each page somehow maintain which plugin is which for a post back.  Remember we can't use the SessionBean for "currentPlugin" because each instance of the page will overwrite this attribute.  We can't use cookies because these are browser instance wide and not page specific.  The black magic is based on a nice class in the JSF framework called "UIViewRoot".  The "UIViewRoot" is the root of the component tree for all the components on the page.  And here's the best part, "UIViewRoot" is saved across post back calls.  This means on a post back, you can expect values set in components to be there when the page is rerendered.  This implementation does things like keeping form values across post backs to keep users form committing suicide after they've filled out a form for 3 hours only to hit the "submit" button and find out they missed a required field and now all the fields are blank.  The Visual Web application model has the "init" method that happens during the "Restore View" phase.

vw app model

The problem is that the UIViewRoot values don't get stuffed back into the components on the backing bean until "Update Model Values".  This means you can't do something like this,

this.getTxtPluginID().getText();

and expect to get the value you stuffed in there before a button was clicked.  So the trick is to pull the value out of the "UIViewRoot".  Here's the code that shows how I did this on the Plugin Detail page.

        /\*\*
\* Process a GET type request.
\*/
        HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
        String [] pluginids = request.getParameterValues("pluginid");

        if(null != pluginids && pluginids.length == 1) {
try {
Long pluginid = new Long(Long.parseLong(pluginids[0]));
currentPlugin = getApplicationBean1().getPluginSystem().getPlugin(pluginid);
if(null != currentPlugin) {
getSessionBean1().setCurrentPlugin(currentPlugin);
getRequestBean1().setCurrentPlugin(currentPlugin);
this.getTxtPluginID().setText(currentPlugin.getPluginid());
}
          } catch(NumberFormatException nfe) {}
        } else {
          if(null == this.getCurrentPlugin()) {
/\*\*
\* Process a post back.
\*/
           FacesContext fc = FacesContext.getCurrentInstance();
UIViewRoot viewRoot = fc.getViewRoot();
if(null != viewRoot) {
StaticText pluginid_text = 
(StaticText) viewRoot.findComponent("form1:center_container:page_border:fixed_contentarea:fixed_contextbox:topPanel:txtPluginID");
if(null != pluginid_text) {
Long pluginid = (Long)pluginid_text.getText();
if(null != pluginid) {
currentPlugin = getApplicationBean1().getPluginSystem().getPlugin(pluginid);
}
             }
           }
          }
        }
So you can see that for a "GET" style call with the "Pretty" URL we do what did before except we stuff the part of the state we want for the post back into a "Static Text" component.  In the case of the post back, we get a hidden field from the "UIViewRoot" and get its value to use.  So the one last piece is to create a "Static Text" component somewhere on the page and make it invisible.  As you can see from the code you have to fully qualify the name of the "Static Text" component.  In my case it's "txtPluginID".


Well I'm hoping another brick doesn't fall out the other side again. :)  If anyone has a better way to pull this off, please, please post a comment.


Thursday Nov 01, 2007

Mac OS X Leopard Black Screen of Death

What's this?  The Mac OS X Black Screen of Death?  I unplugged my USB 2.0 external drive and got this on the screen.  For the last year using Tiger I never saw this screen.

blackscreen


Even more annoying is the fact that Leopard doesn't recognized my USB 2.0 drive enclosure that I used in Tiger.  If it's a power management issue, please at least give me the option of giving more power to USB even if my battery won't last as long.  BTW, I was not running on battery.  I'm wonder if Apple wants to sell their own external drives so they've cranked the output of the USB ports down to eliminate many devices.  I would hope they wouldn't go this low but who knows. :(  Has anyone else seen this problem?  I found a  similar issue listed on the Apple site but it remains unanswered.

I really would like to stick int out on the Mac but without Java 6 and having to power the machine is worse than being on Windows.  I never thought I would say that.

Saturday Oct 27, 2007

No Java 6 on Mac OS X Leopard

This picture says it all!

no jdk6


If you're thinking about upgrading to Leopard and you do Java development on your Mac (at least try to), don't bother.  I searched for hours trying to find Java 6 on Leopard and it just isn't there.  I did install some documentation pack but I can't even find it after I installed.  Honestly, I only bought the Leopard upgrade for Java 6.  There's really nothing else that is noticably worth it so far.  My fan control stopped working.  I have about a 1 year old Macbook Pro "17 with the core duo.  So now I have a hot Mac again. :(  Things actually seem more sluggish than before.  I already had to restart Finder which I NEVER had to do on Tiger.  All in all, as a Java developer, I might have to move off the Mac OS X platform.  This hardware is just too expensive to boot into some inferior OS like Windows.

Tuesday Oct 16, 2007

NetBeans 6.0: Ask The Experts on SDN October 22, 2007

Remember that burning question you had about NetBeans 6.0?  Well now is your chance to get that question answered.  I will be involved in a Sun Developers Network "Ask the Experts" starting October 22, 2007.   Brian Leonard, a fellow NetBeans Evangelist, as well as Judith Lilienfeld, my manager and Director of Tools Evangelism at Sun will also be on the panel.

Saturday Oct 13, 2007

NetBeans 6.0: Making Me a KeyBoard Junkie

I was recently at a conference giving a demo for the new NetBeans 6.0 editor features.  In preparing for the demo and actually doing it,  I realized that reducing keystrokes is huge for developers.  I've been so accustomed to broken IDEs where I had to cursor and mouse around that I didn't realize how much NetBeans 6.0 editing has improved until I was in the middle of this demo.  I actually got a rush hitting the "Enter" key and seeing smart code completion save me lots of keystrokes.  I'm becoming a keyboard junkie (no sneering from the emacs crowd) so now I'm looking for more keystroke saving key bindings.  A great resource to get started on Java editor enhancments in NetBeans 6.0 is the Java Editor User's Guide on the NetBeans public Wiki.  Two keystroke and mouse saving features I recently found useful are AST (Abstract Syntax Tree) selection and Next/Previous Tab.

The AST (Abstract Syntax Tree) keymap is listed in the "Tools->Options" (Preferences on Mac OS X) under the "Keymap" heading.  The actual setting is "Other->Select Next Element/Select Previous Element".  This lets you select things like a keyword, a line, and a block of code.  The default key mapping is "Alt-Shift-PERIOD" (Ctrl-Shift-PERIOD on Mac OS X) to select more and "Alt-Shift-COMMA" (Ctrl-Shift-COMMA on Mac OS X) to select less.

I found out about Next/Previous Tab in Gregg Sporar's blog.  But I couldn't get this to work so I did some investigation.  On Mac OS X the default key binding to do a Next Tab is "Meta-PAGE_DOWN".  To get this to work you need to press "Meta-Fn-PAGE".  Pressing three keys at once really doesn't save me much so I remapped this to "Meta-DOWN" and "Meta-UP".  Note that you will have to "Remove" these key mappings from the "Other->Insertion Point to End of Document" and "Other->Insertion Point to Beginning of Document".

mapping1


Above all, trying hitting the "Enter" key when you're doing code completion and you'll be amazed at just how smart the code completion really is.  Happy keyboarding!


Monday Oct 01, 2007

Code to Make a Tag Cloud in Wicket

 
       Form form = new Form("form");
        add(form);

        final TextField field = new TextField("field", new Model(""));
        form.add(field);

        final Label label = new Label("selectedValue", new Model(""));
        label.setOutputMarkupId(true);
        form.add(label);

        CategoryCount[] counts = getPluginSystem().getCategoryCounts();
        List countsList = Arrays.asList(counts);

        final DataView repeater = new DataView("cloud", new ListDataProvider(countsList)) {

            protected void populateItem(final Item item) {

                MyLink link = new MyLink("link");

                item.add(link);


                String categoryName = ((CategoryCount) item.getModelObject()).getCategoryName();

                String categoryStart = getCurrentPrefix();
                if (null == categoryName) {
                    link.setVisible(false);
                    return;
                }
                /\*\*
                 \* If the category doesn't begin with the typed in prefix, don't add it to the cloud.
                 \*/
                if (null != categoryStart && null != categoryName) {
                    if (!categoryName.toUpperCase().startsWith(categoryStart.toUpperCase())) {
                        link.setVisible(false);
                        return;
                    }
                }

                Label label = new Label("text", ((CategoryCount) item.getModelObject()).getCategoryName());
                Model model = new Model() {
                };
                AttributeModifier am = new AttributeModifier("style", new Model() {

                    @Override
                    public Object getObject() {
                        return getLinkStyle((CategoryCount) item.getModelObject());
                    }
                });
                label.add(am);

                link.add(label); //the Caption property ought to be picked up by reflection
                //or you could create a subclass of AbstractReadOnlyModel to
                //fetch it if reflection bothers you
            }
        };

        add(repeater);
        /\*\*
         \*  We need to set the output markup id so it can be used as an AJAX target
         \*/
        setOutputMarkupId(true);
        /\*\*
         \*  Now set up the AJAX handling
         \*/
        OnChangeAjaxBehavior onChangeAjaxBehavior = new OnChangeAjaxBehavior() {

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                setCurrentPrefix(field.getModelObjectAsString());
                target.addComponent(getCloudPanel());
            }
        };
        field.add(onChangeAjaxBehavior);

Tuesday Sep 04, 2007

Tim's Hitting the U.S. in the NetBeans Mobile

My fellow NetBeans Evangelist, Tim Boudreau, told me he was moving from California to Massachusetts, and he had purchased a truck to make the trip. When I saw the truck I come up with this crazy idea to have Tim do some advertising for NetBeans and also let the world follow him by using a GPS device and a web site.  Well Tim went for the idea and my manager Judith Lilienfeld supported the idea so Tim spent many hours getting the truck ready for action.  Here's a picture of the truck just to get you interested.

tims van
More details about the truck can be seen on Tim's blog.

Tim took off from Nairobi (East Palo Alto) last night but didn't make it too far.  He only made it across the Dunbarton Bridge. Check out everything including his route at the official trip web site.

Tuesday Aug 07, 2007

NetBeans Visual Web Pack - Real World Apps Tip #4 - "Pretty" URLs

Problem


One issue that's been plaguing the NetBeans Plugin Portal from the beginning is the lack of direct URLs to portions of the web application.  As many of you know, JSF page navigation creates some pretty horrendous URLs.  Besides being "Ugly", as one user put it, you can't use the URLs to reference pages in the web application.  Without going into the design considerations for JSF, I will mention that one of the main issues is state.  Yes I know.  In any web application development managing state is always an issue.  If you read my JavaOne 2007 BOF slides, you will see that I had somewhat of a solution on slides 54-55 by providing a "Permanent Link" then dispatching through my main page.  This worked but when you ended up on the page, the URL was still ugly.  I've Googled many times on the subject but always seem to wind up in the same place with the solution.  Winston Prakash in the NetBeans visual web engineering group did a blog entry on another real world application built on Visual Web Pack.  A few weeks ago I was looking at what Joshua van Aalst had done with his web site.  Joshua had a goal of making much of the web site Search Engine Optimized (SEO) so he needed to replace the ugly URLs.  His technique included using a servlet filter and converters.  In looking at his solution and doing some testing, I realized that my original solution was very close with one critical mistake.  I was sending everything through the main page then doing a redirect to the PluginDetailPage after setting up state.  

Solution

The solution - change all the links in the web app to point to the real pages and set up the state in each page "init()" method.  The solution involves still using "GET" style URLs.  So the first step is to design the URL for each page that you will provide direct linking to.  The URL will need to contain adequate information for the given page to build the web application state on the fly.  For example, to provide direct linking to the category list page, I designed the following URL.

http://plugins.netbeans.org/PluginPortal/faces/CategoryPage.jsp?categoryname=Tools

As you can see, the URL has a parameter named  "categoryname" and a value of "Tools".  In the "init" method of the CategoryPage class,  I use the following code.

        /\*\*
\* Process a GET type request.
\*/
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
String [] categories = request.getParameterValues("categoryname");
if(null != categories && categories.length == 1) {
getSessionBean1().setCurrentCategoryName(categories[0]);
}


The above code is what the Plugin Portal needs to set up state for the category list page.  That's all that's really needed.  The major refactoring I had to do was to change all the hyperlinks to be in this "Pretty" format.

Tuesday Jul 10, 2007

NetBeans Plugin Portal Project Web Site

I've just finished putting together the NetBeans Plugin Portal project page on netbeans.org.  You can get there by going to http://pluginportal.netbeans.org.  This site will be the project for the current NetBeans Plugin Portal.  From this site you can navigate to the source code, join mailing lists, see latest design artifacts, etc.

I just published the functional specification for Phase III.  Please check it out and send your comments about the spec to the users@pluginportal.netbeans.org mailing list.

Wednesday Jun 27, 2007

NetBeans Plugin Portal Source Code Open Sourced

For those of you who haven't found the code yet, I thought I would officially announce that I've published the source code for the NetBeans Plugin Portal on netbeans.org.  The URL to browse the source is http://www.netbeans.org/source/browse/pluginportal/.  So now you can see all the good, the bad, and the ugly code that went into making the Plugin Portal.  I'll continue to blog in detail about the experience but if you can't wait and you need to see how something was done, please go look at the source code.  The code is under a CDDL license if you decide to use any of it wholesale.  If you see any blatant errors in the code or better ways of doing things, please open an Issue.

Friday Jun 22, 2007

NetBeans Visual Web Pack - Real World Apps Tip #3 - Tag Clouds

Finally I've found the time to show you how to do tag clouds in NetBeans 5.5 with Visual Web Pack.  In my last blog, I showed you how to create dynamic Hyperlinks.  In the blog before that, I discussed how to do dynamic content.  Both of those topics provide necessary background information for creating a tag cloud.

First, let me provide a little background on how I tackled creating a tag cloud.  Since I really didn't know what a tag cloud was, I started with the Wikipedia's definition.  Next, since my task was not to be an expert on tag clouds but to implement one on the web site, I simply needed an algorithm to get me started.  I found an excellent white paper by Kevin Hoffman called, "In Search Of...The Perfect Tag Cloud".   Based on the Plugin Portal needs and Kevin's explanation, I decided to use the "Linear Distribution Algorithm".

Plugin Portal Details


The goal is to basically have a set of words that are displayed in different font sizes based on how many "things" there are for that word.  With the Plugin Portal, the words represent categories.  The bolder, bigger font category names are the ones with more entries in the category.  The sample project I'll include will include hard coded data but I thought I would take a moment to talk about the query behind the Plugin Portal that gave me the results I needed.  In the case of the Plugin Portal, I needed to define a type that contained a category name and a category count.  I created a class called "CategoryCount".  Here's the code including the query that creates the "CategoryCount" instances.

        String select = "select distinct o.categoryname, cc.cat_count from othercategoryimpl o," +
" (select distinct categoryname,count(categoryname) as cat_count from othercategoryimpl cc group by categoryname) as cc" +
" where o.categoryname=cc.categoryname order by o.categoryname";
Query query = em.createNativeQuery(select);
List resultList = query.getResultList();
Iterator resultIterator = resultList.iterator();
Vector currentResult = null;
while(resultIterator.hasNext()) {
currentResult = (Vector)resultIterator.next();
String categoryName = (String)currentResult.get(0); //category name.
Integer categoryCount = (Integer)currentResult.get(1); //count
CategoryCount currentRecord = new CategoryCount(categoryName, categoryCount.intValue());
newCache.add(currentRecord);
}

You can see from this SQL query that I really have to do two passes of the data.  The "from" target:

(select distinct categoryname,count(categoryname) as cat_count from othercategoryimpl cc group by categoryname) as cc
gets the actual count for each category.  Believe me this query took a while to get right. :)  I don't claim to be a SQL expert so if someone knows of an easier method, please let me know.

Creating the "Comparator"

Part of the goal also is to have the words sorted alphabetically so I chose to use "Arrays.sort".  To use this method, we need to create a specialized "Comparator" that knows how to compare our "Count" type.  For my simplified example, I will be creating "CategoryCount" as the "Count" type.  Here's the code.

public class CategoryCount {

/\*\* Creates a new instance of CategoryCount \*/
public CategoryCount() {
}

public CategoryCount(String inName, int inCount) {
setName(inName);
setCount(inCount);
}

/\*\*
\* Holds value of property name.
\*/
private String name;

/\*\*
\* Getter for property name.
\* @return Value of property name.
\*/
public String getName() {
return this.name;
}

/\*\*
\* Setter for property name.
\* @param name New value of property name.
\*/
public void setName(String name) {
this.name = name;
}

/\*\*
\* Holds value of property count.
\*/
private int count;

/\*\*
\* Getter for property count.
\* @return Value of property count.
\*/
public int getCount() {
return this.count;
}

/\*\*
\* Setter for property count.
\* @param count New value of property count.
\*/
public void setCount(int count) {
this.count = count;
}

}

Also we need a Comparator to sort this type.  Here's the "CountComparator".

import java.util.Comparator;


public class CountComparator implements Comparator {

/\*\* Creates a new instance of CountComparator \*/
public CountComparator() {
}
/\*\*
\* This method is used to compare o1 and o2.
\* @param o1 The first object to compare to o2
\* @param o2 The second object to compare to o1
\* @return a negative integer, zero, or a positive integer if o1
\* is less than, equal to, or greater than o2
\*/
public int compare(Object o1, Object o2) {

String o1categoryname = ((CategoryCount)o1).getName();
String o2categoryname = ((CategoryCount)o2).getName();
return o1categoryname.compareToIgnoreCase(o2categoryname);

}
}

The Linear Distribution Algorithm Details

The idea behind this algorithm is to figure out a range for a set of "Buckets" then distribute your items in the buckets according to where they fit into the range.  The first step is to decide on the number of buckets to use.  In a tag cloud you'll be deciding how many font size ranges you want.  For the Plugin Portal, we chose six buckets.  So to figure out the range, you need to take the max count of the items - the min count of the items and divide by the number of buckets.  This gives you the range to use for each bucket.  Here's the code I'll use in my sample to figure out the range.

    private long getCloudRange(int min, int max) {
/\*\*
\* For this tag cloud we will use the linear distribution algorithm with six different "buckets".
\* The algorithm is:
\* category weight = max number/category - min number/category
\* range = category weight/number of buckets (6).
\*
\*/
long weight = 0;
long range = 0;

weight = max - min;
if(weight < 6) {
/\*\*
\* We don't have a very big range of numbers in categories so we need to increase the
\* weight so the range will be bigger.
\*/
range = 1;
} else {
range = weight/6;
}


return range;
}
The other key piece of the implementation is to assign a font based on which bucket the item fits into.  Here's my sample method to do that.

    private String getFont(CategoryCount inCount,long bucketRange) {
String fontsize1="font-size: 10px; font-weight: normal;";
String fontsize2="font-size: 11px; font-weight: normal;";
String fontsize3="font-size: 12px; font-weight: normal;";
String fontsize4="font-size: 13px; font-weight: normal;";
String fontsize5="font-size: 14px; font-weight: normal;";
String fontsize6="font-size: 15px; font-weight: normal;";

/\*\*
\* Determine which of the buckets the count falls into.
\*/
if(inCount.getCount() >= 0 && inCount.getCount() <= bucketRange) {
return fontsize1;
} else if(inCount.getCount() >= (bucketRange\*1) +1 && inCount.getCount() <= (bucketRange\*1)+bucketRange) {
return fontsize2;
} else if(inCount.getCount() >= (bucketRange\*2) +1 && inCount.getCount() <= (bucketRange\*2)+bucketRange) {
return fontsize3;
} else if(inCount.getCount() >= (bucketRange\*3) +1 && inCount.getCount() <= (bucketRange\*3)+bucketRange) {
return fontsize4;
} else if(inCount.getCount() >= (bucketRange\*4) +1 && inCount.getCount() <= (bucketRange\*4)+bucketRange) {
return fontsize5;
} else {
return fontsize6;
}
}

Leveraging our dynamic Hyperlink experience, we will need a block of code like this create the actual Tag Cloud.

        /\*\*
\* Sort the CategoryCounts
\*/
Arrays.sort(counts,new CountComparator());

/\*\*
\* Get the range to use for the tag cloud.
\*/
long range = getCloudRange(minCategory,maxCategory);

/\*\*
\* Create all the hyperlinks and add them to the dynamic panel.
\*/
ArrayList<Hyperlink> hyperlinks = new ArrayList();
Hyperlink dynamicHyperlink = null;
for(int ii=0; null != counts && ii < counts.length; ii++) {
dynamicHyperlink = new Hyperlink();
dynamicHyperlink.setText(counts[ii].getName());
dynamicHyperlink.setActionListenerExpression(listenerMethod);
dynamicHyperlink.setActionExpression(actionMethod);
/\*\*
\* Get the font for this link which will be calculated based on the
\* count and where it falls into a range for each bucket.
\*/
String font = getFont(counts[ii],range);
dynamicHyperlink.setStyle(font);
dynamicPanel.getChildren().add(dynamicHyperlink);

}

The Finished Product

Running my sample project, you can see that we get a small cloud.

cloud

You can use my sample project for a good starting point.  I really wish I new how to create components.  This would make a great component wouldn't it!

Thursday Jun 07, 2007

NetBeans Visual Web Pack - Real World Apps Tip #2 - Dynamic Hyperlinks

In my last blog I covered creating Dynamic Content in NetBeans VWP (Visual Web Pack).  In this blog, I'll show you how to create "Hyperlink" components dynamically in VWP.

Creating the Hyperlink component and adding it is really not difficult.  But, hooking the Hyperlink component up to a Java backing beans is a different story.  This took me a while to figure out.

Creating the Hyperlink

Actually creating the "Hyperlink" component is easy.  Here's the code.

Hyperlink link = new Hyperlink();

Using the Hyperlink to Pass Data


As with most cases developing on the JavaServer Faces framework, you can't ignore the standard processing lifecycle.  Remember VWP uses a modified "Application Model" based off the one used by Java Studio Creator 2.  Why is this important?  In the case of a Hyperlink on a page, if you want something about the Hyperlink to be passed as data to the actual page bean method that will process the hyperlink click, you either need to use the SessionBean or the Hyperlink component itself.  The technique I'm about to show you uses the Hyperlink component.  Remember you can't use state on the page bean because a new instance of the page bean will be created on a postback.

To explain this, I'll use the example of the Plugin Portal when the categories are in list form rather than tag form.  Here's a snapshot of that area of the screen.

List

You can see that the Hyperlink has the category name and the number of items in that category.  In the Plugin Portal code, I needed the category name so I could show a category list of that category.  To pass that name to the method that would deal with the selection, I used the "Hyperlink.type" property.  The "type" property is used to set the MIME type of the hyperlink.  Since we are handling the link, we don't care about the MIME type so we can use this property to pass values.

So here is some code that creates the Hyperlinks using the type property.

        /\*\*
\* Now create the hyperlinks to add
\*/
Hyperlink dynamicHyperlink1 = new Hyperlink();
dynamicHyperlink1.setText("list1(" + list1.size() + ")");
dynamicHyperlink1.setType("list1");
Hyperlink dynamicHyperlink2 = new Hyperlink();
dynamicHyperlink2.setText("list2(" + list2.size() + ")");
dynamicHyperlink2.setType("list2");
Hyperlink dynamicHyperlink3 = new Hyperlink();
dynamicHyperlink3.setText("list3(" + list3.size() + ")");
dynamicHyperlink3.setType("list3");

/\*\*
\* Create a grid panel so we have one column.
\*/

HtmlPanelGrid listPanel = new HtmlPanelGrid();
listPanel.getChildren().add(dynamicHyperlink1);
listPanel.getChildren().add(dynamicHyperlink2);
listPanel.getChildren().add(dynamicHyperlink3);
/\*\*
\* Add the list grid panel to the layout panel.
\*/
dynamicPanel.getChildren().add(listPanel);

Mapping the Hyperlink to Backing Beans Methods

Now to the difficult part, at least before knowing what I'm about to show you. :)  Many times you want Hyperlinks to invoke some action on your Java backing bean.  To accomplish this, you'll need to know how to create a "MethodExpression".  A Hyperlink component has two properties for dealing with an action:

The ActionExpression is the method JavaServer Faces uses to determine page navigation.  The ActionListenerExpression will wrap the Hyperlink in the event and let us use the "Type" field as a way to pass data.  When a user clicks on the Hyperlink, the methods will be called in this order.

  1. ActionListener method
  2. Action method
To create a MethodExpression, you need the "ELContext".  You can get the "ELContext" from the "FacesContext".  You use the "ExpressionFactory" from the "Application" to create the MethodExpression.

So here's the code to create the ActionListenerExpression.

       /\*\*
\* Create the MethodExpressions for the Hyperlinks
\*/

/\*\*
\* First get the ExpressionFactory from the Application
\*/

ExpressionFactory expressionFactory = this.getApplication().getExpressionFactory();

/\*\*
\* Next get the ELContext
\*/

ELContext elContext = FacesContext.getCurrentInstance().getELContext();

/\*\*
\* Now create the MethodExpressions
\*/
MethodExpression listenerMethod = expressionFactory.createMethodExpression(elContext,
"#{Page1.category_action}",
null,
new Class[] {ActionEvent.class});

MethodExpression actionMethod = expressionFactory.createMethodExpression(elContext,
"#{Page1.category_action}",
String.class,
new Class[] {});

dynamicHyperlink1.setActionListenerExpression(listenerMethod);
dynamicHyperlink1.setActionExpression(actionMethod);
dynamicHyperlink2.setActionListenerExpression(listenerMethod);
dynamicHyperlink2.setActionExpression(actionMethod);
dynamicHyperlink3.setActionListenerExpression(listenerMethod);
dynamicHyperlink3.setActionExpression(actionMethod);
Lastly, you need to create the methods that will be invoked by clicking the link.  These methods will go on the page bean.  

Let me talk about the "createMethodExpression" method signature for a moment because that's important for understanding the methods.

The first parameter is the ELContext.  We've already discussed that.

The second parameter is the binding expression.  If you look at the code above, you'll see that the page is hard coded in the binding expression.
#{Page1.category_action}
You will also notice the method name "category_action".  

The third parameter is the method return type.  You'll notice in the code above for the ActionListener, we don't define a return type.  For the Action we do define a "String".  This method signature, "String action_method()" called by an action will cause JavaServer Faces navigation to check the outcome to see if a navigate is needed.

The fourth parameter of the "createMethodExpression" call is the list of arguments that will be passed to the method.  Again notice for the ActionListener the "ActionEvent" is passed.  Remember this is how we will pass data.

Here are the methods you need to define on the page.

    public String category_action() {
return "page2";
}

public void category_action(ActionEvent ae) {
String selectedListName = ((Hyperlink)ae.getComponent()).getType();
getRequestBean1().setSelectedList(selectedListName);
return;
}

You can see the "return "page2"" in the Action method.  This corresponds to this navigation file which will cause a page navigation to "Page2".

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<navigation-rule>
<from-view-id>/Page1.jsp</from-view-id>
<navigation-case>
<from-outcome>page2</from-outcome>
<to-view-id>/Page2.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/Page2.jsp</from-view-id>
<navigation-case>
<from-outcome>case1</from-outcome>
<to-view-id>/Page1.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>

Conclusion

So here's what the page will look like.

dynalink1

In my next blog, I'll use this blog and the previous blog to show you how to create a "tag cloud".

You can download my sample "DynamicHyperlinks" project to get started.  As before, I used NetBeans 5.5 with Visual Web Pack.


Monday Jun 04, 2007

NetBeans Visual Web Pack - Real World Apps Tip #1 - Dynamic Content

I promised I would start blogging about my experiences developing the NetBeans Plugin Portal when I gave my BOF at JavaOne this year.  So this blog is the start of that series.  To get some background on the project, you really should look through my slides for the BOF.

There seemed to be the most interest around building a "Tag Cloud" using NetBeans VWP (Visual Web Pack).  So I thought I would start with that topic.  In order to do tag clouds in VWP, you need to understand how to create two things first, dynamic content and dynamic hyperlinks.  This blog will cover the details of creating dynamic content with NetBeans VWP.  I'll then follow up with blogs for dynamic hyperlinks and finally tag clouds.

I do plan to put the source code for the Plugin Portal out on netbeans.org soon but I have to get through another phase and do some cleanup first.  In order to demonstrate these topics, I'll be building simplified projects to be downloaded.

First, what is "Dynamic Content"?  My use of this term focuses on the distinction between the design time UI design and the run time UI.  Content that can not be visually created during design time is content that I refer to as "Dynamic Content" or content that is created during run time.

Representing the Content in the Design Time

One of the greatest features of using VWP is the visual designer.  The designer gives you a pretty good idea what the page will look like at runtime.  So obviously you'd like to use the designer to even help with the dynamic content.  To do this, use a "Layout Panel" as a placeholder for the dynamic content.  Here's a screenshot of the project we will build.  You can see the outline of the "Layout Panel" which I named "dynamicPanel".

layout panel

Creating the Content at Run Time

Now that you have a placeholder for the dynamic content, "dynamicPanel", you can create the content at run time.  We'll target the "preprocess" method of the page backing bean.  For more information on the VWP application model, please see the article, "The Java Studio Creator 2 Application Model".  As you may already know, VWP incorporates most of the Java Studio Creator 2 functionality. The application model in VWP is the same as Java Studio Creator 2.

For this first example, let's simply add a button as dynamic content.  Here's the code to do that.

    public void prerender() {
/\*\*
\* First clear out the layout panel
\*/
if(null != dynamicPanel.getChildren()) {
dynamicPanel.getChildren().clear();
}
/\*\*
\* Now create the button to add.
\*/
Button dynamicButton = new Button();
dynamicButton.setText("My Button");
/\*\*
\* Add the button to the layout panel.
\*/
dynamicPanel.getChildren().add(dynamicButton);
}

Note 1 - If you don't know the type for the component you want to add, visually add the component to the designer and look at the Java source to find the type.

Note 2 - The content you add MUST be a subtype of "UIComponent".

Conclusion

Here's what our page will look like.

page

Now that I have covered the basics of creating dynamic content, in my next blog I'll cover creating dynamic hyperlinks.


You can download the sample "DynamicContent" project I used to get started.  I used NetBeans 5.5 with Visual Web Pack installed to create the project.


Saturday May 19, 2007

NetBeans Day Mexico City 2007

I'm on the plane returning from NetBeans Day Mexico City.  The turnout was great!  We had 455 people attend.  This was my first time to Mexico City and Mexico as well.  The people were very friendly.  I'd like to go back some time and see some sites.  I really wasn't supposed to be on this trip.  Gregg Sporar was supposed to go but got sick with the flu.  He called me on a Tuesday, I flew out on Wednesday, looked at the slides and demos for the first time on Thursday, and gave the sessions on Friday.  Overall everything went pretty well.  I did have some editor problems with NetBeans 6.0 M9.  Of course I had gone through the demos many times the day and moments before with no problems.  My Google Tool Bar demo didn't work for some mysterious reason.  I was really frustrated by this so I opened my laptop at the airport about one hour later, ran the demo and it worked.  Here's the proof.

working

The only explanation I can think of is that I was running in a lower resolution which might have caused the edit tool bar to truncate somehow.  I tried to reproduce the problem by changing the resolution but I could not reproduce this.  Oh well!

The crowd was wonderful.  They asked many good questions and were very much in tune with development issues.  Here's some shots of the actual conference

1

Entrance to NetBeans Sessions - picking  up translation devices

2
The crowd.  Do you see yourself?

3
The venue - Centro Banamex



Wednesday May 09, 2007

JavaOne 2007 BOF 9055 Slides

Thanks to everyone who attended my BOF Tuesday night.  I'm not sure how many people showed up.  I would guess somewhere around 30.  As promised, here are the slides from my BOF.  As soon as I get settled from JavaOne, I'll start blogging all the details.

Friday May 04, 2007

NetBeans Day On The Brain!

Got NetBeans Day on the Brain?  You should.  Don't forget it's happening Monday, May 7, 2007 at the Moscone Center in San Francisco.  This will be a great opportunity to see what's up and coming for NetBeans.  The NetBeans 6.0 Preview  will be showcased heavily.  One of the great aspects of this years NetBeans Day is getting a free day at JavaOne.  That's right!  You get one day, Tuesday, access to JavaOne.  Here's the paragraph from the flier.

"CommunityOne attendees who are, or become, Sun Developer Network members are also invited to experience the 2007 JavaOne Conference on Tuesday, May 8. Enjoy the complimentary one-day access to the general sessions, the JavaOne Pavilion and Welcome Reception, and two (2) technical and/or BOF sessions. RSVP early to reserve your place. Please Use
Priority Code C71AWM. "

The JavaOne Pavilion is where you get all the good Swag.  Remember when you're going for Swag, try not to have the glazed look in your eyes while you eye the Swag.  This is a dead giveaway that you really don't care about things like, "Clustering in the New Time Space Continuum". :)

Also, there will be some great prizes given out at NetBeans Day.  Check out Roman's blog for more info.

It's not too late!  Get registered now.


Thursday Apr 26, 2007

Check Out The New NetBeans Plugin Portal!

I can finally tell you what I've been working on for the past 5 months!  We reworked the netbeans.org "Plugins" tab from the ground up into the New NetBeans Plugin Portal.  


New Plugin Portal

And I did it all with Sun Tools and Technology!

Here are some highlights of the things you can now do with the NetBeans Plugin Portal.

  • Add your own plugins with a netbeans.org userid.
  • Comment on plugins
  • Rate plugins
  • Add the Plugin Portal as an Update Center to your NetBeans IDE.


Stay tuned!  I'll be blogging about my experience frequently giving lots of information.  I'll be giving out some of this information at my BOF (session id 9055) at JavaOne.

I'm looking forward to sharing the details!

-David

I'm Still Alive! Getting Ready for JavaOne...

Yes I'm still alive!  I've been working feverishly on a project since about last November and I can almost talk about it.  Many of you have already seen it (Hint: the paragraph below).  Anyway, hopefully very very soon I'll be able to open up the bloggate (my new word!) and share my experiences with everyone.

Also, my BOF (Birds-Of-A-Feather) session for JavaOne has been accepted.  The title is, "Developing a Real-World Web Application with NetBeans Release 5.5 Visual Web Pack" and the session ID is BOF-9055.  I'm currently scheduled for Tuesday, May 8, 8-8:50PM in Gateway 104.  There are lots of good BOFs in that same time slot but please show up if you can.

Friday Jan 05, 2007

Five Things About Me...Even If You Don't Care

I've been tagged by The Tutorial Divas!  I've never passed on the emails that claim someone will die if I don't but I felt compelled to keep this tagging chain going for some odd reason.  Perhaps deep down I want to divulge more private information about myself and was just waiting for the chance to do so.  Yeah right! :)

So here are five things that you probably don't know about me.
  • I lived in Germany for three years in the late 80's while I was in the Army.  While I was on a weekend trip to Berlin (remember the wall was still up in the 80's), Libya-backed terrorists bombed a discotheque in West Berlin.  Two U.S. soldiers were killed and 50 injured. Fortunately I've never been into the disco scene. You couldn't walk anywhere near a U.S. installation without having the proper identification the rest of my trip.  The U.S. subsequently bombed Libya.
  • Upon graduating High School in 1981, I participated in the Fort Lewis College Japan program.  I lived with a family in Tsukatsuki-shi Japan (Between Osaka and Kyoto) for six months.  I took a semester of Japanese before going but soon learned the difference between learning a language from books and tapes and understanding a native speaker.  I was with a family in Tokyo the first three days in Japan.  I was standing naked in the shower/bath area trying to figure out how to work everything when the home stay mother opened the door and rattled off something in Japanese and shut the door.  I don't know what she said to this day.  She probably said something like, "Don't take a long shower because we don't have huge hot water tanks like you Americans." :)
  • My Great Grandfather, Tom Botterill, started the first Pierce Arrow Automobile Company in Salt Lake City, Utah and later Denver, Colorado.  That's ultimately how I wound up being from Colorado.
Botterill auto company
  • Do you remember the story of the boy who had is arm bitten off by a shark in Florida?  On July 6, 2001 we were vacationing near Pensacola, Florida.  We'd been at the beach most of the week and it was very hot.  The beaches there are incredible, white powder sugar sand and warm water.  Near the end of our vacation, the people we were visiting there said they usually go to the beach in the evening because it's less crowded and much cooler.  So there we were on the beach at Gulf Island National Seashore about 6:00 PM.  My four kids were out in the water playing in the waves.  I was standing in the surf watching them.  There were only a few groups of people there that evening.  All of a sudden some women came running down the beach towards us yelling, "A boy's been bitten by a shark get out of the water!".  First I thought, "That's not even funny."  Then the reality that it might  be true struck me.  I started frantically yelling at my kids and my friends' kids to get out of the water.  Two Japanese women farther out couldn't understand what I was shouting at them.  They finally came in.  I instructed everyone to stay put and I went toward where Jessie Arbogast was getting CPR.  It was surreal.  Jessie was on the sand without an arm while his aunt gave him CPR.  About five feet away from him was a 7 foot bull shark.  No blood was coming out of his wound so I knew he had bled out in the water.  A helicopter landed and rushed him to a nearby hospital.  I returned to my family and regretfully informed them that he probably wouldn't live.  I was surprised to hear the next day that he was expected to recover.  My wife had strolled up the beach about 10 minutes before the attack and taken a picture up the beach.  The picture included Jessie's group's area.  This picture was later used by the park ranger to deny the claims that Jessie's uncle was shark fishing.  I spoke with the park ranger and confirmed to him that I never saw Jessie's group fishing but did see a man and boy fishing farther up the beach earlier.  Here are a couple of good pages with more info if you're interested.
  • I live with my mom.   Actually, my mom lives with us.  My mom's health has taken a bad turn in the past couple of years and she really can't live alone anymore.  I'm glad I can do this for her after all she did for me growing up.  I won't lie and say it's been easy for us.  This hasn't been easy for my mom either.  She's lost her freedom and is in constant pain from a bad hip.
"Dear children, let us not love with words or tongue but with actions and in truth" - 1 John 3:18

I'm tagging these five people: Marco Walther, Greg Ziebold, Tor Norbye, Sandip Chitale, and Gregory Murphy

Friday Dec 15, 2006

Creating Use Cases with the NetBeans 5.5 UML Tools

I'm currently working on a project that has given me the opportunity to use the NetBeans tools I evangelize.  I'm in the beginning part of a software project when modeling is critical.  The obvious tool choice was the NetBeans 5.5 UML feature.  This blog entry will give you some "tips and tricks" on how to effectively create Use Cases using the NetBeans 5.5 UML feature.  Here's a Use Case that might apply to a blogger tool just to get you in the mood.

usecase sample




Getting the UML Modeling Feature

Before you can use the UML functionality in NetBeans 5.5, you have to add it to the IDE.  The UML functionality used to be bundled in the Enterprise 5.5 Pack but now it's available as a standalone feature via the NetBeans Beta Update Center.  I think this was a great move for the feature which will hopefully allow it to grow and mature more rapidly.

First, go to the Update Center, from the menus choose "Tools->Update Center".  You'll see something like this.

update center

Notice the "NetBeans Update Center Beta" is selected.

Press the "Next >" button and you'll see this.

update center 2

Select "UML Modeling" and "Add >" it.  Continue through the process until the UML Modeling feature is installed.


Creating the Project

Now that you have the UML Modeling feature installed, create the project.  In the new project dialog, choose "UML" for the category and "Platform-independent Model" for the Project.  Here's what the new Project dialog will look like.

new project

When you "Finish", you'll be presented with a diagram dialog asking what type of diagram you want to create.  Choose "Use Case" and give it a name.  Here's what that dialog will look like.

new diagram

Use Case Refresher

If you're like me, you don't spend enough time modeling so you tend to forget some of the basic tenants of UML.  First, I believe all documentation should be useful.  I know many developers are afraid of "paralysis analysis" but too many swing the other way to "hacking before thinking".  I recently read some of the Agile stuff and was generally impressed.  I especially like Scott W. Ambler's discussion on documentation.  UML when done correctly is more than "just pretty pictures".

Remember there are really two artifacts around Use Cases; the textual Use Case and the Use Case Diagram (UML).  Here's a good resource to get you started with Use Cases
http://www.agilemodeling.com/artifacts/systemUseCase.htm.

The textual Use Case describes expected and exceptional courses of interaction between actors and the system.  The Use Case Diagram graphically represents the interaction.  The real meat and potatoes is really behind the textual representation.  Ideally, the Diagram and the textual description could be kept together.  I'll show you how to do that with NetBeans 5.5 UML.

Creating the Use Case Diagram

Before we can fill in the textual use case information, we need to create the diagram.  From the steps above you should be staring at a blank Use Case diagram in NetBeans 5.5.  First, let's add an "Actor".

actor

Important!

There is a feature of the UML feature that might take some getting used to.  When you drag and drop a component on the drawing service, the pointer is in what I call "semi-automatic" mode like a semi-automatic pistol.  All you have to do to fire is pull the trigger again without cocking.  In this mode, every time you click the mouse on the drawing surface you'll get another instance of the component you chose from the palette.  To get back to "manual" or "pointing" mode, simply hit the "ESC" key.  You can also select the pointer on the toolbar at the top.

Name the "Actor" "Bank Customer" by double-clicking on the "unnamed" label and typing in the new name.

Next, add a "Use Case" and name it "Login to Bank Account".  As you can see we're going to model a bank customer interacting with an online banking system.  Add another "Use Case" and name it "Transfer Funds".  

Now let's add some dependencies showing the actor - system interaction.  Choose a "Usage" dependency and drag it from the "Bank Customer" to the "Login to Bank Account" Use Case.  Also drag a "Usage" from "Bank Customer" to "Transfer Funds".  Lastly, drag a "Permission" dependency from "Login to Bank Account" use case to "Bank Customer" actor.  At this point, your diagram should look something like this.


diagram1

Adding the Real Meat

As I said, the real meat of a Use Case is the textual description of the interactions.

We will use the "Documentation" property of Use Case element to document the interactions.   The "UML Documentation"  window looks tempting but I currently recommend against using it for a couple of reasons.  First, as issue 80014 describes, you can type a lot of text in the "UML Documentation" window then loose it if you don't click on the right part of the IDE.  Also, I filed issue 91102 for this behavior.   If you put blank lines in the "UML Documentation" window between your text, the IDE adds a line each time you leave the window.   Because of these two issues, I recommend you use the "Documentation" property to enter the textual use case.  The "Documentation" property expects HTML to be entered.  You don't need a proper HTML page with "<html></html>" tags.  You only need to focus on using HTML for formatting purposes.  To open the "Documentation" property editor, click the "..." next to the property.

doc property


Important Notes About Property Editor!

The property editor deals strangely with line ends.  In particular, when you have a <li> for a list, make sure the text for the <li> is right next to the tag and not split onto the next line.

For example:

This HTML-

<li>
Bank Customer enters userid/password.
</li>

Yields this display-

1.
   Bank Customer enters userid/password.

Notice how the text is below the number for the list item.

Similarly, if you enter this:

<li>
Bank Customer enters
userid/password.
</li>

You will see this-

1.
   Bank Customer enters
   userid/password.

To get the desired results, enter the HTML like this.

<li>Bank Customer enters userid/password.
</li>

Also, the property editor does NOT have an undo feature.  So if you accidentally wipe out a bunch of text, too bad.  Hit the "OK" button frequently to save the contents.


Here's a template to use for the Use Case Text.

<u><b>Main Flow of events:</b></u>
<ol>
<li>
</li>
</ol>
<u><b>Exceptional Flow of events:</b></u>
<ol>
<li>
</li>
</ol>
Filling the details for the "Login to Bank Account" would look something like this displayed in a browser.

formatted text

Sharing With Others

The make or break for any UML tool is its ability to output its model in a usable format.  The NetBeans 5.5 UML Modeling feature does a great job of producing a HTML UML report.  To run the report, right-click on the project node and choose "Generate Model Report".  This will cause the IDE to create a HTML report and open it in the web browser.


Bummer!

The report feature doesn't seem to work correctly on Mac OSX.  According to issue 82394, there are also problems on Linux and Solaris.

Thanks to Parallels, I was able to run NetBeans 5.5 on Windows XP Pro on my Mac to produce the report correctly.  Here's what our little Use Case example looks like.

report2

report1

Future blog entries will include more of my modeling experiences with NetBeans 5.5 UML Modeling.  Until then, remember modeling is worth the time.  Do just enough documentation to fulfill the needs of the project team and the future system maintenance.  

Wednesday Dec 06, 2006

Expanding Evangelism Role, NetBeans 5.5 Visual Web Pack

I'm used to writing more technical blogs and thought I would try, once again, to relay some personal, not-so-technical information.  As many of you know I've been the Java Studio Creator evangelist for almost one year now.  Thanks to all of you that have made that a very enjoyable job!  I'm now expanding my evangelism duties to cover more of NetBeans.  So probably a better title at this point would be "Java Tools Evangelist".  I guess I better order different business cards. :)  

"So what's with the new picture on the blog?"  This is a picture of me next to Juggy in the Czech Republic.  "What about the hat?"  The Czech Republic is very cold in November and I don't have any roofing (hair) so I needed some warmth.  A couple of my Sun co-workers/managers had hats like this so I just had to get one.  Yes it is very warm!  I was in the Czech Republic meeting NetBeans people.  Since I'll also be evangelizing the NetBeans 5.5 Visual Web Pack , I met up with the other NetBeans evangelists and NetBeans engineers.  While I was in Prague, Roman Strobl and Gregg Sporar recorded NetBeans Podcast Episode #17 live!  Roman dissed me trying to explain what wasn't in NetBeans 5.5 Visual Web Pack Technical Preview that was in Java Studio Creator. :) I'll get him back someday somehow. :)
Cheers for now!
-David

NetBeans 5.5 Visual Web Pack Released

NetBeans 5.5 Visual Web Pack is here!  Check out the news at http://www.netbeans.org/community/news/.

There are lots of enhancements and fixes from the TP (technical preview) version.  Check it out!

Sunday Oct 29, 2006

NetBeans 5.5 and Visual Web Pack Technical Preview Are Out!

NetBeans 5.5 is out!  If you haven't checked out NetBeans in a while you really really must.  Also out today is the long awaited Visual Web Pack.

its out
Now you can use all the power of the NetBeans IDE with many of the great visual web application development features from Java Studio Creator.  To get started developing a Visual Web Application, create a new project then choose "Web->Visual Web Application" like this.

vwp project

You can even open a Java Studio Creator 2 Update 1 project.  Just be aware that once the project conversion is done to Visual Web Project, you can't open the project again in Java Studio Creator.  When you try to open a Java Studio Creator project, you'll get the following dialog.

vwp warning


Enjoy!
-David

Saturday Oct 14, 2006

Java Studio Creator - Changing the Table Columns from A Dropped Web Service

I talked to a developer the other day that had some problems with the results of dropping a web service method on a table.  The table columns were the high level attributes of the returned values but he wanted different values to show up in the table.  This blog will show you how to dig into types returned from web services and display the pieces you want in the table columns..


First, a little about the sample web service.  I created a simple web service to return an array of type "Car".  Here is a class diagram of "Car" as well as the web service end point interface and the implementation.

uml diagram
If you add this web service to Java Studio Creator, you get something like this.

add web service


If you drag the web service method "getCars" onto a table, you'll get a table looking like this.

wrong table stuff

As you can see, the dataprovider was created from the high-level attributes of Car; body, engine, frame and model.  This is really all the code that does the data provider can do to guess at what to show.  But, suppose you really wanted to show the "engine" attributes in the table?  Here's how to do it.

First, drag and drop an "Object Array Data Provider" onto the designer.  This should create "objectArrayDataProvider1" in the Outline window.


object array data provider

At this point, we need to do some coding to fill the new dataprovider with the "engine" attributes.   Here's the code that goes in the "init" method.

public void init() {
...
 // Perform application initialization that must complete
 // \*after\* managed components are initialized
// TODO - add your own initialization code here
/\*\*
 \*  We need to build an Array from the subparts of the car to use in the dataprovider
 \*/
 ArrayList engines = new ArrayList();
 try {
boolean moreRows = myWebServiceGetCars1.cursorFirst();
RowKey currentRowKey = null;
FieldKey engineKey = myWebServiceGetCars1.getFieldKey("engine");
while(moreRows) {
currentRowKey = myWebServiceGetCars1.getCursorRow();
Engine currentEngine = (Engine)myWebServiceGetCars1.getValue(engineKey, currentRowKey);
engines.add(currentEngine);
moreRows = myWebServiceGetCars1.cursorNext();
}
} catch (DataProviderException dpe) {
error("DataProviderException=" + dpe);
}

this.objectArrayDataProvider1.setArray((Engine [])engines.toArray(new Engine [0]));
}

You could just call the web service to get the "Car" array and go through and build the Array.   You will, however, be making another call across the wire which can be expensive.  The web service data provider is created in the "_init" method called in the first part of "init".  When the web service data provider is created, it tries to make a call to the web service to fill in the data.

Now we need to add an "engine" property to the "Page1" of type Engine.  This will allow us to point our new Object Array Data Provider to it.  Add a property to Page1 by drilling down in the Project window

add property

Add a property, "engines" of type "Engine".  Now select the "objectArrayDataProvider1" form the Outline window and change the "array" property to be "engines"

change data provider


Next, select the table, right-click and select "Bind to Data".  From the "Get From Data:" dropdown, select "objectArrayDataProvider1" and press the "Apply" button.  You should see something like this.

changed table


That's it!  You've not successfully created a new data provider and used a different set of values in the web service return to populate the table.


About

David Botterill

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today