What you may not know is that JavaBeans properties are not limited to scalar (that is, single-valued) values. A JavaBeans property can also be an array of values, accessed by an integer index, called an indexed property.
This month, we're going to tackle creating a shiny new JavaBean with an indexed property, and a custom property editor that
allows the developer to manipulate the indexed property at design time. We'll start by creating a basic URLFileLoader bean that downloads a file from an arbitrary URL on the Web, and stores it in a disk file on demand (taking a quick side
excursion into boolean properties, a simple property type). Then we'll improve the URLFileLoader class loader, enabling it to fetch files using HTTP GET with parameters maintained by a new indexed property. (We'll go over GET later on in the text.) Next, we'll create a custom editor (so we can access the property graphically), and see how to specify
this custom editor with the builder tool (in our case, Sun's BeanBox.) We'll wrap up with a discussion of possible extensions
to this project.
Before we dive into creating a property editor for an indexed property, let's have a look at why indexed properties are useful.
As noted above, an indexed property is nothing more than a JavaBeans property whose value is an integer-indexed array, instead
of being a single scalar value like a String or an int. For example, a RelationalTable bean might have a property called Columns that returns an array of Column objects that describe the table's columns. A ScatterPlot bean could have a property called DataPoints, itself being an array of DataPoint objects that the bean displays. A SpreadSheet bean could have two properties: Rows, which manipulates a list of Column objects, and Columns, which manipulates a list of Row objects. Each Row (or Column) object could itself be a bean with an indexed property called Cells, an array of Cell objects.
Indexed properties provide enormous flexibility to JavaBeans. Implementing them can be confusing, though, as some of my e-mail from readers attests. I own five books on JavaBeans, and most explain what indexed properties are, but none provides sample code for an indexed property editor. This was mostly because the BeanBox, the standard JavaBeans test container, didn't support indexed property editors until quite recently. (For more on the BeanBox, see the links in Resources.)
For a tutorial example of creating a bean with indexed properties, let's start with a simple bean: the URLFileLoader. We'll first go over the requirements of this new class, and then extend it to include an indexed property and its associated
editor.
Requirements
Let's start by describing our new component's requirements in terms of functionality and properties. In the following description,
note that the properties we define are italicized.
On request, the URLFileLoader JavaBean fetches the content of a particular URL on the Web using the HTTP protocol. It stores the content it receives in a file in a directory on a local disk. By the way, this bean is intended to be used in Java applications, not with applets, as it accesses both
the filesystem and the network. Also, it optionally communicates through a firewall proxy, which listens at a specific port number. (If you don't know what a firewall is exactly, see the introductory article link to the World Wide Web Security FAQ in the
Resources section below.)
All the terms italicized above are bean attributes a user (meaning an application developer) may want to control at design or runtime. Developers do this by accessing the bean via the properties we define for it, which appear in the following table:
| Property | Type | Description |
|---|---|---|
| URL | String | The URL to load from the Web |
| File | String | The file in which to store the received content |
| Dir | String | The directory in which to create the file |
| UseFirewall | boolean (!) | Whether or not to connect through a firewall |
| Firewall | String | Firewall name |
| Port | int | The port number of the firewall http proxy |
Figure 2. URLFileLoader properties
The above properties customize the bean to get information from a certain place, storing it in a certain other place, optionally doing it a certain way. In short, customization is the use of properties to define what all of those "certain" things are.
Now that we've defined what the bean is going to do, let's define how it does it.
Implementation
I've chosen to implement URLFileLoader as a subclass of an abstract base class, because I know that eventually I'm going to extend that base class to handle other kinds of URL storing. Regardless of how
the data is accessed, there are three basic steps to fetching and storing a file with HTTP:
Somewhere in there, I also have to specify what to do if there's a firewall in the way. These are abstract operations; in other words, saying "connect to a server" does nothing about how that connection is made. Of course, if any particular operation (such as downloading and saving content from an open connection) has a reasonable default implementation, it makes sense to put it in the base class and let subclasses inherit and reuse it.
But when subclasses differ in how they implement abstract operations, the base class simply defines the signature (name, return type, and argument number and types) of the method, and then tags it with the abstract keyword. Java won't allow creation of an instance of a class that contains an abstract method declaration, so any subclass of an abstract base class must either define an implementation of every abstract method in all of its superclasses, or end up being abstract itself. There's no way to say "don't inherit" a method from a parent.
PropertyChangeListener, mentioned above, is one) are explained thoroughly in "Keep listening for upcoming events," available at http://www.javaworld.com/jw-10-1997/jw-10-beans.html
PropertyChangeListener, see "Double Shot, Half Decaf, Skinny Latte -- Customize your Java" at http://www.javaworld.com/jw-09-1997/jw-09-beans.html
HTTP POST and saves the results (based on URLDataLoader, of course,) check out JavaWorld's "Java Tip 34POSTing via Java" http://www.javaworld.com/javatips/jw-javatip34.html