Creating JavaBeans with BeansExpress

BeansExpress is the fastest way to create JavaBeans. It consists of a set of wizards, visual designers, and code samples that help you build JavaBeans rapidly and easily. Once you have a JavaBean, you can use BeansExpress to make changes to it. Or you can take an existing Java class and turn it into a JavaBean.

This chapter covers these topics:


What is a JavaBean?

A JavaBean is a collection of one or more Java classes, often bundled into a single .JAR (Java Archive) file, that serves as a self-contained, reusable component. A JavaBean can be a discrete component used in building a user interface, or a non-UI component such as a data module or computation engine.

At its simplest, a JavaBean is a public Java class that has a constructor with no parameters. JavaBeans usually have properties, methods, and events that follow certain naming conventions (also known as design patterns).


Why build JavaBeans?

Like other types of components, JavaBeans are reusable pieces of code that can be updated with minimal impact on the testing of the program they become a part of. JavaBeans have some unique advantages over other components, however:


Generating a bean class

To begin creating a JavaBean using BeansExpress,

  1. Choose File|New to display the Object Gallery.

  2. Double-click the JavaBean icon to start the JavaBean Wizard.

The JavaBean Wizard

You use the JavaBean Wizard to specify the name of your bean, the package it will be in, and the class it extends.

Within the JavaBean Wizard,

  1. Specify the package you want the bean to be part of in the first text box.

    By default, this will be the name of your current project.

  2. Give your bean a name in the second text box.

  3. Use the Base Class to Inherit From drop-down list to choose a class to extend.

    The drop-down list presents a list of convenient classes to use for constructing a new JavaBean. You can use one of these classes, or you can click the adjacent button to display the Package browser and use it to specify any existing Java class you want.

    If you want only core JDK and Swing components to display in the drop-down list, check the Show Only Core JDK and Swing Classes option below the list.

    To read about the types of classes convenient to use as a starting point for a new JavaBean and to help you choose the class you need, see Creating original components.

  4. Choose the remaining options you want; none of them are required:

  5. Choose OK.

    JBuilder creates a JavaBean with the name you specified, places it in your current project, and displays the source code it generated. This is the code JBuilder generates for the settings shown here:

package beans;

import java.awt.*;
import borland.jbcl.view.BeanPanel;

public class BeanieBaby extends BeanPanel {
  BorderLayout borderLayout1 = new BorderLayout();

  public BeanieBaby() {
    try {
      jbInit();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
  void jbInit() throws Exception(
    this.setLayout(borderLayout1);
  }
}
If you examine the code JBuilder generated, you’ll note that:

Even in this rudimentary state, your class is a valid JavaBean.


Designing the user interface of your bean

Not all JavaBeans have a user interface, but if yours does, you can use JBuilder’s UI Designer to create it.

To create a user interface for your bean,

  1. Select the bean file JBuilder created for you in the Navigation pane.
  2. Click the Design tab to display the UI Designer.
  3. Use the UI Designer to build the user interface for your bean.

For information on creating a user interface, see Designing a user interface.


Adding properties to your bean

Properties define the attributes your bean has. For example, the backgroundColor property describes the color of the background.

JavaBeans properties usually have both a read and a write access method, also known as a getter and a setter, respectively. A getter method returns the current value of the property; a setter method sets the property to a new value.

To add a property to your bean,

  1. Select your component in the Navigation pane and click the Bean tab to display the BeansExpress designers.

  2. Click the Properties tab to display the Properties Designer.

    The Properties Designer

  3. Choose the Add Property button.

    The New Property dialog box appears.

  4. Specify the name of the property in the Property Name box.

  5. Specify a type in the Type box.

    You can type in one of the Java types or use the Package browser to select any object type, including other JavaBeans.

  6. Leave both Getter and Setter check boxes checked if you want JBuilder to generate the methods to both get and set the property value.

    If you want to make a property read-only, uncheck the Setter check box.

  7. Choose OK.

JBuilder generates the necessary code for the property and adds the property to the Properties Designer grid. You can see the read and write access methods added to the Component Tree for your bean. If you click the Source tab, you can see the code JBuilder generated.

Here is the New Property dialog box with all the required fields filled in:

New Property dialog box

The Display Name and Short Description are filled in automatically with default values. This is the resulting source code:

package beans;

import java.awt.*;
import borland.jbcl.view.BeanPanel;

public class BeanieBaby extends BeanPanel {
  BorderLayout borderLayout1 = new BorderLayout();
  private float price;           // Added a private price field

  public BeanieBaby() {
    try {
      jbInit();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
  void jbInit() throws Exception(
    this.setLayout(borderLayout1);
  }

  public void setPrice(float newPrice) {  // Added a method to change the price value
    price = newPrice;             
  }

  public float getPrice() {               // Added a method to obtain the price value
    return price;
  }
}

JBuilder added a private price field to the BeanieBaby class. The price field holds the value of the property. Usually a property field should be declared as private so that only the getter and setter methods can access the field.

It also generated a setPrice() method that can change the value of the new field, and it generated a getPrice() method that can get the current value of the field.

When your bean is installed on JBuilder’s Component Palette and users drop the bean on the UI Designer, the price property will appear in the Component Inspector so that users can modify its value. All the code to get and set the price property is in place.

For more information about declaring properties in JavaBeans and the read and write access methods, see Defining simple properties in the Component Writer’s Guide.

Modifying a property

Once you’ve added a property to your bean, you can modify it at any time with the Properties Designer.

To modify a property,

  1. Select your bean using the Navigation pane.

  2. Click the Bean tab to display the BeansExpress designers.

  3. Click the Properties tab.

  4. Select any of the fields in the Properties Designer grid and make the changes you want.

    For example, you can change the type of the property by entering another type.

JBuilder reflects the changes you make in the Properties Designer in the source code of your bean. You can also make changes directly in the source code and the BeansExpress designers will reflect the changes if the changes have been made correctly.

Removing a property

To remove a property from your bean,

  1. Select the bean that contains the property in the Navigation pane.

  2. Click the Bean tab to display the BeansExpress designers.

  3. Click the Properties tab.

  4. Select the property you want removed in the Properties Designer grid.

  5. Click Remove Property.

The property field and its access methods are removed from the source code.

Adding bound and constrained properties

BeansExpress can generate the necessary code to create bound and constrained properties.

To add a bound or constrained property,

  1. From the Properties Designer, click the Add Property button to display the New Property dialog box.

  2. Specify a property name and type.

  3. Use the Binding drop-down list to specify the property as bound or constrained.

  4. Choose OK.

If the property you added is a bound property, JBuilder adds the private property field to the class and generates its read and write methods. It also instantiates an instance of the PropertyChangeSupport class. For example, here is the code added for a bound property called allTiedUp:

public class BeanieBaby extends BeanPanel {
...
private String allTiedUp;
private transient PropertyChangeSupport propertyChangeListeners = new
  PropertyChangeSupport(this);
...
public void setAllTiedUp(String newAllTiedUp) {
    String oldAllTiedUp = allTiedUp;
  allTiedUp = newAllTiedUp;
  propertyChangeListeners.firePropertyChange("allTiedUp", oldAllTiedUp, newAllTiedUp);
}
public String getAllTiedUp() {
    return allTiedUp;
}

Note that the setAllTiedUp() method includes the code to notify all listening components of changes in the property value.

JBuilder also generates the event-listener registration methods that are called by listening components that want to be notified when the property value of allTiedUp changes:

public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
  propertyChangeListeners.removePropertyChangeListener(listener);
}
public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
  propertyChangeListeners.addPropertyChangeListener(listener);
}

The code JBuilder generates for a constrained property is similar except the listeners have the opportunity to reject the change in property value. To read about bound and constrained properties, see Defining bound properties and Defining constrained properties in the Component Writer’s Guide. To learn about events and listeners for events, see Working with events in the Component Writer’s Guide.


Creating a BeanInfo class

You can customize how your bean appears in visual tools such as JBuilder using a BeanInfo class. For example, you might want to hide a few properties so they don’t appear in JBuilder’s Component Inspector. Such properties can still be accessed programmatically, but the user can’t change their values at design time.

BeanInfo classes are optional. You can use BeansExpress to generate a BeanInfo class for you to customize your bean. If you are going to use a BeanInfo class, you should specify more detailed information for each new property you add to your bean.

Specifying BeanInfo data for a property

You can specify BeanInfo data for a property as you use the New Property dialog box as shown here.

To hide a property so it does not appear in visual design tools such as JBuilder’s Component Inspector, make sure the Expose through BeanInfo option is unchecked.

To provide a localized display name for this property, enter the property name you want to use in the Display Name field.

To provide a short description of this property, enter the description in the Short Description field. JBuilder displays this text as a tool tip in the Component Inspector for this property.

If you have created a property editor that can edit this field, specify the property editor in the Editor field. The Editor field displays all editors in scope that match the given property type.

For more information about property editors, see Creating a property editor.

Working with the BeanInfo Designer

The BeanInfo Designer provides a way to modify BeanInfo data for a property, lets you specify the icon(s) you want to use to represent your bean in an application builder such as JBuilder, and generates the BeanInfo class for you.

Block diagram of internal workings of a simple model-view-painter component.

The BeanInfo Designer displays all the properties you have added to your bean. If you change your mind about the BeanInfo data you entered for a property, you can edit one or more of these fields in the grid. Only the name of the property can’t be changed.

To provide an image to use as an icon to represent your bean, specify one or more images in the Icons boxes.

The Icon boxes let you specify different icons to use for both color and mono environments and for different screen resolutions. Fill in the boxes that meet your needs.

If the superclass of your bean has a BeanInfo class and you want its BeanInfo data exposed in the BeanInfo class for your bean, check the Expose Superclass BeanInfo check box. The generated code will include a getAdditionalBeanInfo() method that returns the BeanInfo data of the class your bean extends.

To generate a BeanInfo class for your bean, click the Generate Bean Info button.

JBuilder creates a BeanInfo class for you. You’ll see it appear in the Navigation pane. To see the generated code, select the new BeanInfo class in the Navigation pane and the source code appears.

Modifying a BeanInfo class

You can change the BeanInfo class for your bean with BeansExpress.

  1. Select your bean in the Navigation pane.

  2. Click the BeanInfo tab to display the BeanInfo Designer.

  3. Make your changes in the grid.

  4. Click the Generate Bean Info button again.

You are warned that you are about to overwrite the existing BeanInfo class. If you choose OK, the class is overwritten with the new BeanInfo data.

For more information on BeanInfo classes, see Specifying component information with BeanInfo classes in the Component Writer’s Guide.


Adding events to your bean

A JavaBean can

BeansExpress can generate the code that makes your bean capable of doing one or both of these things. To read about events, see Working with events in the Component Writer’s Guide.

Firing events

To make your bean capable of sending an event object to listening components,
  1. Select your bean in the Navigation pane.

  2. Click the Bean tab to display the BeansExpress designers.

  3. Click the Events tab to display the Events Designer.

    The Events Designer

  4. Select the events you want your bean capable of firing in the left window.

The Events Designer adds the event-registration methods to your bean. These methods are called by components that want to be notified when these types of events occur. For example, if you select Key events, these methods are added to your bean:

package myBeans;

import java.awt.*;
import borland.jbcl.view.BeanPanel;
import java.awt.event.*;
import java.util.*;

public class BeanieBaby extends Beanpanel {
  public BeanieBaby() {
  }
  private transient Vector keyListeners;
  
  public synchronized void addKeyListener(KeyListener l) {
    Vector v = keyListeners == null ? new Vector(2) : (Vector) keyListeners.clone();
    if (!v.contains(l)) {
      v.addElement(l);
      keyListeners = v;
    }
  }
  
  public synchronized void removeKeyListener(KeyListener l) {
    if KeyListeners != null && keyListeners.contains(l)) {
      Vector v = (Vector) keyListeners.clone();
      v.removeElement(l);
      keyListeners = v;
    }
  }
When a component wants to be notified of a key event occurring in your bean, it calls the addKeyListener() method of your bean and that component is added as an element in KeyListeners. When a key event occurs in your bean, all listening components stored in KeyListeners are notified.

The class also generates fire<event> methods that send an event to all registered listeners. One such event is generated for each method in the Listener’s interface. For example, the KeyListener interface has three methods: keyTyped(), keyPressed(), and keyReleased(). So the Events Designer adds these three fire<event> methods to your bean class:

protected void fireKeyTyped(KeyEvent e) {
  if (keyListeners != null) {
    Vector listeners = keyListeners;
    int count = listeners.size();
    for (int i = 0; i < count; i++)
    ((KeyListener) listeners.elementAt(i)).keyTyped(e);
  }
}
protected void fireKeyPressed(KeyEvent e) {
  if (keyListeners != null) {
    Vector listeners = keyListeners;
    int count = listeners.size();
    for (int i = 0; i < count; i++)
    ((KeyListener) listeners.elementAt(i)).keyPressed(e);
  }
}
protected void fireKeyReleased(KeyEvent e) {
  if (keyListeners != null) {
    Vector listeners = keyListeners;
    int count = listeners.size();
    for (int i = 0; i < count; i++)
    ((KeyListener) listeners.elementAt(i)).keyReleased(e);
  }
}

Once you’ve made your bean capable of generating events, those events will appear in JBuilder’s Component Inspector when the user drops your bean on the UI Designer.

Listening for events

You can also make your bean a listener for events that occur in other components.

To make your bean a listener, select one of the event types to listen for in the Events Designer.

As soon as you check one of the event types, the Events Designer implements the associated listener interface in your bean. For example, if you checked java.awt.event.KeyListener, the phrase implements KeyListener is added to the declaration of your bean and the KeyPressed(), KeyReleased(), and KeyTyped() methods are implemented with empty bodies. Here is a bean that includes the generated code to implement the KeyListener interface:

package myBeans;

import java.awt.*;
import com.sun.java.swing.JPanel;
import java.awt.event.*;

public class JellyBean extends JPanel implements KeyListener { // implements KeyListener
  BorderLayout borderLayout1 = new BorderLayout();
  public JellyBean() {
    try {
      jbInit();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  void jbInit() throws Exception {
    this.setLayout (borderLayout1);
  }
  
  public void keyTyped(KeyEvent parm1) {         // Adds new method
  }
  
  public void keyPressed(KeyEvent parm1) {       // Adds new method
  }
  
  public void keyReleased(KeyEvent parm1) {      // Adds new method
  }
}

If your bean is registered with another component as a listener (by calling the event-registration method of the component), the source component calls one of the methods in the listening component when that type of event occurs. For example, if a KeyPressed event occurs in the source component, the KeyPressed() method is called in the listening component. Therefore, if you want your component to respond in some way to such an event, write the code that responds within the body of the KeyPressed() method, for example.

For more information on generating and listening for events, see Working with events in the Component Writer’s Guide.

Creating a custom event set

Occasionally you might want to create a custom event set to describe other events that can occur in your bean. For example, if your bean implements a password dialog box, you might want the bean to fire an event when a user successfully enters the password. You also might want the bean to fire another event when the user enters the wrong password. Using BeansExpress, you can create the custom event set that handles these situations.

To create a custom event set,

  1. Select your bean the property in the Navigation pane.

  2. Click the Bean tab to display the BeansExpress designers.

  3. Click the Events tab.

  4. Click the Create Custom Event button.

    The New Event Type dialog box appears.

  5. Specify the name of the event set in the Name of New Event Type box.

    The names of the event object and the event listener are generated from the name of the event set; they are displayed in the dialog box.

  6. Select the dataChanged item and change it to the name of your first event.

  7. To add more events, choose the Add New Event button for each event and change the added item to the names of your remaining events:

    New Event Type dialog box

  8. Choose OK.

The new event set is added to list of event types that can be fired in the Events Designer.

JBuilder generates the event object class for the event set:

package myBeans;

import java.util.*;

public class PasswordEvent extends EventObject {
  public PasswordEvent(Object source) {
    super(source);
  }
}
JBuilder also generates the Listener interface for the event set:
package myBeans;

import java.util.*;

public interface PasswordListener extends EventListener {
  public void passwordSuccessful(PasswordEvent e);
  public void passwordFailed(PasswordEvent e);
}
For more information on events sets and creating new ones, see Working with events in the Component Writer’s Guide.