Sun Java Solaris Communities My SDN Account Join SDN
 
Tutorials & Code Camps

JavaBeans 101, Part II

 
Online Training Index

101, Part II:

Introduction | Page 2 | Page 3 | Page 4



Creating a Bean

The easiest way to learn to build a Bean is to start with a basic Bean, then add a property to it. The simplest Bean must implement the java.io.Serializable interface. In fact, any Java class that implements the Serializable interface is a minimal JavaBean by default. A very simple Bean, such as one that merely displays a red rectangle, extends the AWT component java.awt.Canvas. The Bean itself needs only to define a constructor that sets the size of the rectangle and sets the background color to red.

Creating a Simple Bean

Let's begin with a simple Bean that defines a rectangle of a certain size and background color (red) in its constructor. Within this red rectangle, the Bean displays a smaller rectangle in green. In addition to the constructor, the Bean includes a simple property called color that it initially sets to green. Notice that the color property is declared private.

The Bean includes two public methods, one to get the value of the color property and the other to set the value of color. Because the color property is private, it cannot be accessed directly; it can only be accessed via these getter and setter methods. Let's take a look at the code for a SimpleBean JavaBean:

import java.awt.*;
import java.io.Serializable; public class SimpleBean extends Canvas implements Serializable { private Color color = Color.green; //getter method public Color getColor() { return color; } //setter method public void setColor(Color newColor) { color = newColor; repaint(); } //override paint method public void paint (Graphics g) { g.setColor(color); g.fillRect(20,5,20,30); } //Constructor: sets inherited properties public SimpleBean() { setSize(60,40); setBackground(Color.red); } }

The Serializable Interface

First of all, a Bean must implement the Serializable interface. Objects that support this interface can save and restore their state from disk. Beans that have been customized (usually by editing their properties in builder tools) must be able to save and restore themselves on request. To implement the Serializable interface, import the java.io.Serializable package and declare that your Bean implements Serializable in the class definition. Because this Bean is also visible, it extends the AWT component java.awt.Canvas.

The Color Property

The color property is a private instance variable that we initialized to green:

private Color color = Color.green;

Get and Set Methods

There must be get and set methods to access each private variable. Note that the names of the getter and setter methods follow a particular format. The method names begin with either "get" or "set" and are followed by the name of the property, with the initial letter of the property name capitalized. (It is important that this format be followed so that the Bean introspection tools work.)

Thus, get and set methods have the following format:

public <returntype> get<Propertyname>
public void set<Propertyname> (parameter)

For the SimpleBean color property, we define the following pair of methods:

public Color getColor() { ... }
public void setColor(Color c) { ... }

Testing and Editing your Bean

This Bean is almost ready to be dropped into the BeanBox, where it will appear on the palette of ToolBox components.

Dropping into the BeanBox

First, you compile the Java source code. Next, create an executable JAR file. Here are the steps to do this:

  1. Compile the source code for the Bean and generate the SimpleBean.class:
  2. javac SimpleBean.java
    
  3. Create a manifest file in a text editor.

    The manifest file specifies the name of the class file and indicates that it is a JavaBean. The manifest file becomes part of the JAR file. You can name the manifest file manifest.tmp. It contains the following two lines:

    Name: SimpleBean.class
    Java-Bean: True
    

    (On Windows, be sure to include a carriage return at the end of the text in the manifest file.)


  4. Create the executable JAR file.

    Use the form of the jar command to include the manifest file along with the SimpleBean.class file (Type the command on one line):

    jar cfm SimpleBean.jar manifest.tmp 
                            SimpleBean.class
    


  5. Load the JAR file into the BeanBox. (Part 1 of this tutorial explained how to start and use the BeanBox to test your JavaBeans.)

    From the BeanBox File pull-down menu, select LoadJar.

    This brings up a file browser.


  6. Locate the SimpleBean.jar file and choose it. Notice that SimpleBean appears at the bottom of the list of Beans in the ToolBox.

  7. To drop the new Bean into the BeanBox, click on SimpleBean in the ToolBox.

    The cursor changes to a cross hair.



  8. Move the cursor to any spot within the BeanBox, then click.

    SimpleBean appears as a painted red rectangle with a hatched border enclosing a smaller green rectangle. The hatched border indicates that SimpleBean is selected; its properties appear in the Properties sheet.

Simple Bean

You can reposition SimpleBean within the BeanBox by dragging on any noncorner portion of the hatched border. When repositioning a Bean, the cursor changes to crossed arrows. Because SimpleBean inherits from Canvas, you can resize it. To do so, drag a corner.

Editing the Bean's Properties

The Properties sheet displays the selected Bean's properties. SimpleBean has four properties:

  • color
  • background
  • foreground
  • name

SimpleBean declared the color property, but it inherits the other three properties from Canvas. Click on a property, such as color, to bring up a property editor in which you can change property values. The BeanBox provides default property editors for primitive types, as well as for Font and Color types.

It's easy to add other properties to the Bean.

  1. Declare a new property to be a private variable.

    You may initialize it to some default value when you declare it, but this is not required.

  2. Declare a pair of public getter and setter methods to retrieve the property's value and set it to a new value.

    Remember to form the name of the these methods using "get" and "set" followed by the name of the variable, with the variable's initial letter capitalized.

New properties you add to the Bean appear in the Properties sheet when the Bean is opened in the BeanBox, assuming that you correctly defined the get and set methods for the property. Through the introspection mechanism, the BeanBox finds the get and set methods that match the property name and displays the property in the Property sheet.

Next we'll see how to add other kinds of properties to a Bean and to have the Bean fire events and listen for event occurrences.

JavaBeans and Packages

Typically, Beans (whether bought from a third party or create yourself) should be installed in a unique location relative to other Beans. Java packages help you keep everything in its proper place. Java packages are a good way to organize related classes and keep them together.

Putting Your Beans in a Package

To put your Bean in a package:

  1. Add a package statement to the top of your file. The package statement must be the first line in the class file.

    A package statement specifies the directory path which holds the compiled Bean class file, and the path is relative to the current working directory. Subdirectories are separated by periods (.) rather than slashes.

    For example, for compiled Beans in the \acme\Beans directory, add the following line to the top of your file:

    package acme.Beans;
    

    The Acme03Bean, a simple JavaBean with a color property, utilizes packages. In this example you must create a directory structure so the Java compiler can put the generated class files in the proper locations. You'll also want to define the package name for classes that go in your package.

  2. Import the package to files that use classes from the package.

    Include the full name of the package and class when making a JAR file to include Beans that are part of a package. (JAR files are short for Java Archive files—an archive file introduced in JDK 1.1.) JAR files are the preferred packaging mechanism for shipping Beans that are built from multiple files—including both class files and image files.

  3. Create the appropriate directory structure for the acme.Beans package below the current working directory.

    First create two separate directories, one for the Java source files and the other for the Java class files:

    mkdir -p ./src/acme/Beans
    mkdir -p ./classes/acme/Beans
    


  4. Copy the Java source file (or files) to the source directory in the source tree. On a UNIX system:
    cp -p Acme03Bean.java ./src/acme/Beans

    When you compile the JavaBean, be sure that you designate the compiled class file to go to the class directory. If you use a makefile to do your compiles, then modify the makefile accordingly.

Adding Labels to Beans

In this part of the lesson, you add an instance variable to the same AcmeBean. This new variable holds a String label for the Bean. (Acme04Bean for the complete source code for this Bean.)

Adding the Label

  1. Define a private variable called label:
    private String label;
    


  2. Once the instance variable is defined, assign it a default value in the Bean's constructor. It makes sense to also set the font used to render the label. Add the following two lines to the constructor:
    this.label="Bean"
    setFont(new Font("Dialog"; Font.PLAIN, 12));
    

    Eventually, this Bean will be crafted to behave like a button. You'll want to be able to customize the label for the button from within a builder tool (BeanBox, for example).

  3. To enable design-time customization, make label a Bean property by adding get and set methods for it. To do this, add getLabel and setLabel methods to the Bean class.
    public String getLabel() {
    		return label;	
    }
    public void setLabel(String newLabel) {
    		String oldLabel = label;
    		label = newLabel;
    }

    The approach is identical to adding the color property.


  4. While you're at it, you can render the Bean to look more like a button by adding a few lines to the end of the paint callback method.
    g.fillArc(5, 5, 30, 30, 0, 360);
    g.fillArc(25, 5, 30, 30, 0, 360);
    g.setColor(Color.blue);
    int width = size().width;
    int height = size().height;
    FontMetrics fm = g.getFontMetrics();
    g.drawString(label,
       (width - fm.stringWidth(label)) / 2, 
    		(height + fm.getMaxAscent() 
    		 - fm.getMaxDescent()) / 2);
    		 

    The definition for the paint method should look like this:

    public void paint(Graphics g) {
    	g.setColor(BeanColor);
    	g.fillRect(20, 5, 20, 30);
    	g.fillArc(5, 5, 30, 30, 0, 360);
    	g.fillArc(25, 5, 30, 30, 0, 360);
    	g.setColor(Color.blue);
    	int width = size().width;
    	int height = size().height;
    	FontMetrics fm = g.getFontMetrics();
    	g.drawString(label, (width - 
    	          fm.stringWidth(label)) / 2, 
    	(height + fm.getMaxAscent() - 
    	          fm.getMaxDescent()) / 2);
    }
    

Finishing Touches

Now when the button is drawn in the BeanBox, it looks something like a Bean. The property sheet shows fields for both the color and label properties. You can customize either one of these properties at design time by editing the property sheet. Notice that the color of the button has changed to cyan. This was done by changing the initializer for the BeanColor instance variable.

private Color BeanColor = Color.cyan;

This new Bean-like shape is due to the two new calls to fillArc in the Bean's paint method

g.fillArc(5, 5, 30, 30, 0, 360);
g.fillArc(25, 5, 30, 30, 0, 360);

These calls add a rounded left and right side to the original square rendering of the Bean. The remaining code in the paint method ensures that the String label is centered within the button's bounding box:

int width = size().width;
int height = size().height;
FontMetrics fm = g.getFontMetrics();
g.drawString(label, 
  (width - fm.stringWidth(label)) / 2, 
		(height + fm.getMaxAscent() - 
		 fm.getMaxDescent()) / 2);

Coffecup Logo

Introduction | Page 2 | Page 3 | Page 4