« Previous month (Jan 2005) | Main | Next month (Mar 2005) »

20050228 Monday February 28, 2005

Privacy and Security

James Gosling's latest blog entry points to John Gilmore's fight for privacy, and in particular, airport rules. The requirement for all travellers to present IDs to fly helps security how exactly?

This story really struck a chord with me. A couple of months ago, I was going on a business trip from San Francisco airport. I had a million errands to get done before I left - so I brought my bills, envelopes and stamps to the airport. After checking in, I sat at the gate and filled out the payment slips. Then I figured I'd look for a mailbox. Surprise surprise - there are NO mailboxes ANYWHERE inside San Francisco airport. The only one is outside, on the curb! I thought this was unbelieavable - I have often mailed postcards to friends and family from airports while waiting for my flight. But when I talked to the security guards who were pointing me outside, they were telling me that this was for "security reasons".

That didn't make a lot of sense to me. I've brought the letters IN, THROUGH security. If there's a bomb, or anthrax or whatever in my letters, I've already got them with me, ready to take on board. How would having a mailbox for me to drop them in make for a security threat? What if I drop my letter in one of the thrashcans, or airport flower pots, instead?

Presented with this argument, the security guard just smiled and said knowingly "I wish I could tell you, sir, but this is classified and we don't want to give terrorists any ideas". So... I obviously don't have a mind made for terrorism because I can't figure it out.

(2005-02-28 21:33:38.0) Permalink Comments [3]

20050227 Sunday February 27, 2005

Mixed Table Columns

Before I begin: Creator Update 7 is out. This is a pretty small patch (from update 6) containing just a handful of bugfixes - but some of them are important, so do update.

Anyway, I just browsed the Creator forum and saw a couple of questions I thought would make an interesting blog entry. Here's the first question:

I would like to selectively have some items in the datatable be links and others not (e.g. some as simple outputtext, others as links). I need to make this decision at run time.

Is this possible to do? Is there an event to dynamically alter the table item output?

Yes, it's possible - with a little trick! You cannot change the types of components, but you -can- dynamically control whether a component is visible or not! Therefore, all you need to do is place BOTH types of components in the column, create a property which determines which type of output you want for the current row, and then cause exactly one of the two components to be made visible for this row. You control component visibility with the "rendered" property of a JSF component.

Let's take a specific example. I drop a Data Table component on the canvas, and then I drop the "PERSON" table from the Sample "Travel" database that ships with Creator. It has 4 columns: Id, Name, Jobtitle, and FrequentFlyer. I want to make the Name column use a hyperlink if that person is a Frequent Flyer. To do this, I drag a hyperlink and drop it in the Application Outline on top of "Column2" - this places the hyperlink in the second column in the table - the Name column.

Then I double click on the canvas to go to the Page bean for this file (the Java code) and add the following method to create a read-only boolean property:

    public boolean isFrequentFlyer() {
        Object o = getValue("#{currentRow['FREQUENTFLYER']}");
        return o instanceof Boolean && ((Boolean)o).booleanValue();
    }
Go back to the Page1.jsp file.

Finally, I go and update the value bindings:

When you run, you should see this:

Notice how the hyperlinks are only showing up when the FrequentFlyer value is true. And of course there's no reason you need to show the frequent flyer column in the table - you can hide it with the Table Layout context menu item on the table. And furthermore, you can obviously make the logic for deciding which type to use as complex as you want - your isFrequentFlyer() method can do anything you want.

(2005-02-27 21:37:56.0) Permalink Comments [3]

20050223 Wednesday February 23, 2005

Hello from Shanghai

Hi there,
here's just a little quick entry written from my hotel room in Shanghai, China. I'm here for a very quick trip - I arrived last night, I'm spending three days here and then flying home on Saturday. I'm here to talk to some potential Creator partners and customers. There won't be any time for sightseeing, which is too bad, given how interesting this city is. I would especially like to go to the historical museum. Perhaps I can cram it in before the flight on Saturday...

Now a couple of quick tips. I've written a couple of blog entries on expression evaluation. I heard from two readers that they couldn't get this to work when referencing their own beans - it only worked with the "builtin" page and session beans. The reason for this is that expression evaluation works with managed beans. These are beans that are managed by JSF - which means they are created on demand by the framework. You need to register your own beans in the managed-beans.xml file, which you can find in the Project Navigator.

Second, if you want to track the IDE's memory usage over time, you can enable the "Memory Meter". Right click in the toolbar (not over a toolbar button), and you'll see a list of available toolbar items. One is the "Memory" item. Select it, and your toolbar will now display a little graph showing you memory usage over time. Perhaps useful if you're observing occasional sluggishness and you're wondering if your project working set is using up your available heap space, or if you wonder if occasional pauses are related to garbage collection.

(2005-02-23 06:36:32.0) Permalink

20050215 Tuesday February 15, 2005

Data, but not Database Data

Some customers I met last week said that even though automatic databinding is handy (this is when rowsets dropped on visual components are automatically bound to these components), they don't want a tight coupling to the database in this way. They have their own middle tier, and they want to use it.

How can they use the Data Table component, with its paging features etc., and display arbitrary data as opposed to data fetched automagically from a databound rowset?

It's actually pretty straightforward. There is just one key concept you need to know: the JSF Data Table interacts with its data through the DataModel interface. You can supply your own data model, and the Data Table will happily display your own data.

When you drop a Data Table component in Creator, you automatically get a Data Model associated with the Data Table created. For dataTable1 you get dataTable1Model. This model is an instanceof javax.faces.model.ListDataModel, which wraps a simple java.util.List. Each row in the data table will come from a single item in this list.

How the row object is accessed depends on what you put in the table columns. You may have noticed that when you drop a database table on the Data Table, you by default get Output Text components with value bindings like these:

value="#{currentRow['FIRSTNAME']}
This lets each column in the table logically bind to different columns of the row object. To achieve the same effect, put a Map in each row of the data model, where the keys are keys to be used in the value binding expressions (like "FIRSTNAME" above), and the values are the actual values you want assigned as the value for the bound output texts.

Let's get specific. You've dropped a JSF Data Table component on your canvas, and you ended up with dataTable1, and its data model, dataTable1Model. Go to your page bean (double click on the canvas somewhere outside the Data Table), and modify the end of the constructor to

  1. Create a List object
  2. Populate the List with Hashmaps, one for each row, where each hashmap contains key/value pairs for all columns in this row
  3. When done, set this list as the wrapped data for the data model
  4. Return to the Data Table in the design view, and modify the value bindings for the columns such that they point to the new keys

For example, your code might look something like this:

        (Creator-managed Component Initialization here)
        // Additional user provided initialization code
        List rows = new ArrayList();

        // You would probably have a loop here to fetch your
        // data from your real storage or middle tier
        HashMap row1 = new HashMap();
        row1.put("FIRSTNAME", "Mickey");
        row1.put("LASTNAME", "Mouse");
        row1.put("FAVCOLOR", "Green");

        HashMap row2 = new HashMap();
        row2.put("FIRSTNAME", "Donald");
        row2.put("LASTNAME", "Duck");
        row2.put("FAVCOLOR", "Blue");

        rows.add(row1);
        rows.add(row2);

        dataTable2Model.setWrappedData(rows);
    }

Now return to the Design view, right click on the Data Table, bring up the Table Layout customizer. Get rid of all the existing columns that are there (using the << button), then use the New button to create your own columns. In my example, we'll want three columns. Choose the heading names, like "First", "Last", and "Favorite Color". Choose the component types - for example, Output Texts. And finally, set the value binding expressions. For example, for the first column, you should set the Value to #{currentRow['FIRSTNAME']}.

Voila! When you run you should see your own data displayed in the data table. If you enable Paging in the Table Layout customizer, that should work too.

Using ArrayList and HashMap (and one for every row at that) may strike you as wildly inefficient. But notice how you're supplying the List and Map objects! You don't have to use the default implementations; you can write your own class implementing java.util.List which maps directly into your own data storage for the data to be displayed, and similarly, the Map lookup from column name to column value can be done through smart computation rather than pre-storing all the row values in a series of HashMaps for the rows!

One final note - if the data being displayed can change as the page is displayed repeatedly (for example due to failed validation or because the user is interacting with other components on the page), you probably don't want to construct your wrapped list data in the constructor. Instead, make the List object a class member, such as

    private ArrayList rows;
and add a method which first calls rows.clear() and then updates the list to contain the current correct set of rows. Then call this update method both from the constructor as well as from beforeRenderResponse() (which is a method you should add to your page bean; its parent class has an empty implementation which is called.)

This (the need to call the update method from both places) is a bit ugly and is something we'll fix. Happy coding!

(2005-02-15 23:48:02.0) Permalink Comments [13]

20050214 Monday February 14, 2005

Creator is Java Tool of the Year!

Tool Of The Year Creator was just announced as the winner of the Java Tool of The Year category from developer.com! It was also a runner-up for the Tool of the Year award. Here's the detailed writeup of the candidates and winner of the Java tool category.

NetBeans also scored big, winning the Open Source Tool of the year award (its competitor Eclipse won the Tool of the Year award). NetBeans supports the new language features in JDK 5.0, which was the Technology of the Year winner.

Thanks to those who voted! And rest assured we're hard at work on the next release to have a great entry for next year's competition as well!

(2005-02-14 14:55:49.0) Permalink

20050210 Thursday February 10, 2005

Finally Centering Blocks

I'm in Prague this week, and having a great time. We're discussing architecture and the java model. It's really exciting, but too early to blog about...

I did find out about some cool new features in NetBeans 4.1 though. For example, if you hold the control key (or on my mac, the Command key) all method calls under the mouse turn into hyperlinks which when clicked jump to the referenced source.

Now for the nerdy technical digression of the week.... I've been doing some debugging at night. After somebody brought up the issue of the <center>> tag (which I've mentioned before), I decided to look into it again. A little debugging led me to the problem in the rendering code. Basically, let's say you're trying to center a table like this:

    <table style="margin-left: auto; margin-right: auto">
      <tr><td>Hello World</td></tr>
    </table>

I'm using horizontal margins as auto to cause centering, which is the CSS way to center - the <center> tag has been deprecated a long time.

In the above html, we have an element with "width", "margin-left" and "margin-right" all set to "auto". According to the width computation rules for CSS 2.1, section 10.3.3,

If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.

If both 'margin-left' and 'margin-right' are 'auto', their used values are equal. This horizontally centers the element with respect to the edges of the containing block.
My code was doing these rules in the order listed. In the above scenario, yes, width is auto, so the other auto values (margin-left and margin-right) become 0, and then it solves the equation
margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
This however means that the computed position is not centered. So instead I'm now first computing the preferred minimum width of the component (using the shrink-to-fit approach used for absolutely positioned elements), and then I split the remaining space in the containing block evenly between the two margins. This seems to give exactly the behavior needed.

After hooking this behavior up to the <center> tag, using page import on the Google home page shows that the google text field area is now correctly centered!

(2005-02-10 07:22:40.0) Permalink Comments [1]

Inheriting javadoc comments

I just learned something new - which I thought I would share.

I always avoid having javadoc comments on methods which implement an interface method. I add a full comment in the interface, explaining the method, its parameters and its return value. However, in the implementation class, I leave out the javadoc completely. That ensures that javadoc will copy the description from the interface instead, which in turn ensures that the comment is accurate since I only have to maintain it in one place. (Had I copied it in when I first implemented the method, and then later changed the description, the implementation copy would go stale. And yes, I've made that mistake in the past...)

This scheme works fairly well, but there are times when I want to add additional comments to the implementing method. For example, adding additional notes useful to clients calling this specific implementation of the interface. When I've done this, I've only included the specific documentation for this method, and then I refer to the interface method itself for the full method description. This is clearly not a good solution either, because when you view the documentation in an IDE javadoc popup, for example, it doesn't include the basic comment which is often more important than the supplemental information.

Well, it turns out there's a way to get javadoc to include the parent documentation, and you can surround it with your own specific comments! Just use "{@inheritDoc} " inside the documentation somewhere, and it will include the super documentation:

/**
 * {@inheritDoc}
 * <p>
 * For this specific implementation of the interface, you're better off
 * calling the more efficient {@link foo} method, provided you have the
 * additional arguments!
 * </p>
 */

More information on this can be found here.

@inheritDoc is available as of JDK1.4. In JDK 5 there's another cool tag to use as well (thanks to Peter von der Ahé, Mr. Javac, who's sitting next to me here in the Prague office, for pointing this one out to me.) Use the @code tag to include code samples inline in the javadoc. No more needing to escape all < and > characters in the javadoc comment as &lt; and &gt; ! And there was much rejoicing...

(2005-02-10 06:55:59.0) Permalink Comments [1]

20050201 Tuesday February 01, 2005

Fun With Value Binding

JSF supports Value Binding, which allows you to do some really cool things, really easily. For example, lets say you have a Data Table, and in one of the columns you want to show a name. However, that name is really two columns in the database: FIRSTNAME and LASTNAME. When you drop the datasource on the Data Table, you end up with two columns - one with the first name, and one with the last name.

How can you have the data table show "First Last" in a single column? Just go to the JSP and locate the section which looks something like this:

<h:outputText binding="#{MyPage.outputText1}" id="outputText1" value="#{currentRow['FIRSTNAME']}"/>
I've made the value binding expression in the above bold so it stands out. You can change the value binding expression to this
value="#{currentRow['FIRSTNAME']} #{currentRow['LASTNAME']}"
or if you prefer a "Last, First" format,
value="#{currentRow['LASTNAME']}, #{currentRow['FIRSTNAME']}"
When you run the application, the full value binding expresison (with multiple column lookups) will be computed and rendered into your single column in the data table. (Remember to delete the "other" column that we didn't modify - it's still showing the last name.)

Let's say you want to do something more complicated - you don't just want to concatenate these expressions with some text in between, you want to make dynamic decisions about what to include. For that, use property binding.

Let's say you have two columns in your rowset - "Location", and "OverrideLocation" (probably from a join on a couple of different database tables). Location is the default, but whenever OverrideLocation is nonempty, you want to use that instead. In this case, open your page's Java file (the so-called Page Bean), and add a method like this:

    /** Produce a location based on the default location and the location override */
    public String getLocation() {
        String override = (String)getValue("#{currentRow['OVERRIDELOCATION']}");
        if (override != null && override.length() > 0) {
            return override;
        }
        return (String)getValue("#{currentRow['LOCATION']}");
    }
Now, simply go and bind your database column to this property! That's easy - click on the OutputText component in the data table, then right click, choose Property Bindings..., and in the dialog, make sure the "value" property is selected on the left, and on the right, drill to this page's page bean, and locate the "location" property and select it. Hit ok and you're done.

This technique allows you to really easily "massage" your Data Table components (and obviously any other data bound components) to display the information in the way you want, regardless of the actual column layout in your database schema.

(2005-02-01 23:25:32.0) Permalink