|
JavaSoft
Online Training has some good links to tutorials to learn and understand JavaBeans (and other topics).
If you haven't already, you need to register and set up a password to get into the
Java Developer Connection (JDC) page.
For people at Chico State, I have a copy of these locally and will be referencing
them heavily throughout this page. Their copyright.
|
If you have used Delphi, or Visual Basic, you are already familiar with the notion of a bean. The idea is the same; the programming language is different. A Java Bean is a reusable software component that works with Java. More specifically: a Java Bean is a reusable software component that can be manipulated in visual design tools. Beans may be visible objects, like AWT components, or invisible objects, like queues and stacks. A builder/integration tool manipulates Beans to create applets and applications.
Definition: A Java Bean is a reusable software component that can be visually manipulated in builder tools. To understand the precise meaning of this definition of a Bean, clarification is required for the following terms:
The simplest kind of a bean is really nothing more than a java class that follows some fairly strict naming conventions for its event listeners and its methods.
There is no base bean class that you need to extend to build beans. "Visual beans obviously have too extend from Component or a subclass of Component, but non-visual beans can simply extend implicitly from Object. Remember that a bean is simply any class that can be manipulated in a visual design tool." (Core Java V2)
The best way to build a bean is to start with a simple example. Start with the most basic possible bean, then add a property to it. First the basic bean (Acme01Bean ...hmmm actually resize(int, int) was deprecated and we need setSize(int, int)) and a little more interesting basic bean
Another "simple example" can be found in Java in a Nutshell the MultiLineLabel. Note a couple of things in this example:
Basically, it's the same idea as public and private information: the idea is that there are properties that you want the Application GUI's Designer to have control over, so you give them access via the methods.
And sometimes the "application" might not even be visible, but
you want a designer to be able to link it to some other object in
an easy way (without getting into code).
AI example: Programmers, System Designers, Knowledge Engineers, Users: who knows what? Since here, we are doing all (providing for tool building, application building, use (running a case)), we need to think of the design capabilities at each level.
So, in designing your bean, you need to think about what you want the GUI builders to be able to manipulate. These must have the get/set methods.
Actually, it is simply a good programming practice to allow public variables to have specific design patterns for accessors and mutators.
Now a question might arise as to the difference between who you want to easily access these. (I.e, should public variables that will be accessed in user system building be seen in the bean's property list?) You, as the designer and desirer of much fame from people using your stuff, need to decide the easiest and best way to have your bean used. When we get to customization techniques will be clearer.
In general, a method or methods in the following design pattern defines a property:
public void setPropertyName(PropertyType value); public PropertyType getPropertyName();Where PropertyName is the name of the property, and PropertyType is its datatype. If only a get method is present, the property is read-only (set missing) (similarly, write-only if get missing).
There is one exception to the get/set naming pattern. Properties that have Boolean values should use a naming convention as follows:
public boolean isPropertyName(); public void setPropertyName(boolean b);
Also be careful with the capitalization pattern you use for your method names. JavaSoft decided that the name of the property in the above example would be propertyName, with a lowercase p, even though the get and set methods contain uppercase P (getPropertyName, setPropertyName). The bean analyzer performs a process called decapitalization to derive the property name. (Core Java, V2).
The above (lowercase propetyName) is what shows up on the properties list in the BeanTool. In reality, the actual name of the instance variable modified or retrieved by the pair does not matter! This actually makes perfect sense, since the properties for the property list are determined by the introspection mechanism in the BeanBox finding the method get/set patterns that define the properties which are to be capable of visual manipulation. Adding Properties and Acme02Bean.java
Also, the MultiLineLabel.java from "Java in a Nutshell" defined variables:
"Java in a Nutshell" 2nd Edition has a table for Naming Patterns and Conventions...we will see specifics of some of these in the following.
Note (if you looked at the naming conventions) the different types of properties:
Notice the read-only property of this bean ( getPreferredSize()). You would not normally be able to see read-only properties at design time in a Property Sheet.
Note all of the NOTEs and TIPs in CoreJavaVol2. Make sure to initialize private data members explicitly...
With indexed properties, you supply two pairs of get/set methods. The design pattern for these properties is:
public void setPropertyName (PropertyType[] list) public void setPropertyName (PropertyType element, int position) public PropertyType[] getPropertyName () public PropertyType getPropertyName (int position)In particular, in Core Java, the ChartBean is an example. Look at it in the Beanbox. (v2ch7, v2ch8) And also the Bean , the Bean being edited , the Bean changed
public void setValues(double[] v) { values = v; }
public void setValues(int i, double value) {values[i] = value;}
public double[] getValues() { return values; }
public double getValues(int i) {return values[i];}
...
private double[] values;
See Core Java. Also note NOTE (seems to be corrected now but still
says problem in Java2 book)).
Suppose there is a property in an object that a number of different objects want to know about. The example in the tutorial (changing an Employee Bean's salary property) is an example of a bound property. Here, they suggest that both the boss and the spouse would want to know. Geez.
Things to note to make this idea simple
For examples, I will show both not using Swing and using Swing. I think it is good to see everything implemented to get a good feel for what is there.
The fileName in the FileNameBean is an example. When the file name changes, then the ImageViewerBean is automatically notified and it loads the new file.
An example of items 3 and 4 (above) from this bean is seen in the code from the
FileNameBean class:
The java.beans package has a convenience class, called PropertyChangeSupport that manages the listeners.
And here is the Swing FileNameBean
( edition 7)
and its ImageViewerbean
( edition 7)
Note
public void setFileName(String newValue)
{ String oldValue = nameField.getText();
firePropertyChange("fileName", oldValue, newValue);
nameField.setText(newValue);
}
The class inherits the firePropertyChange method (and the add and remove Listeners) from its superclass JComponent JPanel.
(See note in CoreJava)
Basically, for bound properties we see two new mechanisms:
Then the firePropertyChange() method of the PropertyChangeSupport object is used to deliver an event to all the registered listeners. Note:
Don't forget, other beans that want to be notified must implement the PropertyChangeListener interface - which means implement the propertyChange method.
The book says the, "In this case the BeanBox registered itself as a
property change listener to the FileNameBean, and it called
the setFileName method of the ImageViewerBean."
I don't know about you, but I don't like this... For a "homework",
Never mind - changes in 1.4 for the listeners and support
Demo: (the FileName bindproperty filename to the ImageViewer filename)
added Beans,
FileNameBean,
ImageViewerBean ,
fileNameChooser ,
BindProperty ,
BindPropSourceChoices ,
BindTargetProperty ,
A selected image
Finally, a given Bean may be a listener for more that one object. Make sure your listener's propertyChange method checks the property name via getPropertyName to see if you received the PropertyChangeEvent you were expecting.
Another finally: for a bean to generate or receive property change events, you must add the following import statements to the top of the file.
Constrained properties should also, obviously, be bounded since some other bean might be notified (via the event) to potentially perform this veto. Apparently, this is not a "requirement":
IntTextBean , IntTextBean Properties , RangeBean , vetoChange , RangeBean Properties
The RangeBean has two IntTextBeans that are constrained such that the "from" field must be smaller than the "to" field. It will not let you change otherwise (reverts back to original number) and the console where you opened the beanbox says:
WARNING: Vetoed; reason is: from > to
Make sure to check the VetoableChangeListener before the PropertyChangeListener so that you don't change the property value until all the registered vetoable listeners have agreed. Conversely, a vetoable change listener should never assume that a change that it agrees with is actually happening. The only reliable way to get notified when a change is actually happening is through a property change listener.
So, constrained have the same needs as bounded with a couple more requirements. Specifically, as before:
public void addPropertyNameListener (PropertyChangeListener p); public void removePropertyNameListener (PropertyChangeListener p); public void addPropertyNameListener (VetoableChangeListener v); public void removePropertyNameListener (VetoableChangeListener v);So what are we talking about?
Vetoable properties can be thought of as a producer (someone is using the interface and wants to produce a new value for this Object/variable) and a consumer (only certain values are allowable so the consumer can veto). So here, a bean must notify its consumers of the new value and give the consumers a chance to veto the change. Thus, additional VetoableChangeListeners (receivers) are needed.
Often, the Object that implements the veto is a container (has IVs) of the Objects that are going to be changed.
For example, the the IntTextBean is the producer of the vetoable event (it is the Object that is changing) and the RangeBean is the consumer.
In IntTextBean (1) note one can edit from the property field (setValue) or (2) the text field; see the low-level event handling of the text field. Note also that the editComplete catches the exception thrown from the firePropertyChange/vetoableChange call whereas the setValue does not (the Beanbox again???- someone must catch it to make the value go back)
If change from text-field, doesn't really change unless valid, but doesn't veto either. getFocus() is inherited from Component and "Requests that this component get the input focus." Changes in property list occur immediately in text-field or immediately give veto (note where exception is handled). Changes in text-field are only shown in property list if valid. This is all OK (i.e., works) but I think something is not working correctly since they both ultimately throw PropertyVetoException in vetoableChange method
Also notice in the Listener (RangeBean) (which contains the IntTextBeans instances of to and from):
Notice, again, the lack of a PropertyChangeListener and propertyChange method. Beanbox??
The JComponent versions are here: the IntTextBean
and the RangeBean . Tips from Core Java:
The JComponent class has some support for constrained properties, but it is not as extensive as that for bound properties. The JComponent class keeps a single listener list for vetoable change listeners, but not a separate list for each property. And the fireVetoableChange method is not overloaded for basic types. If your bean extends JComponent and has a single constrained property then the listener support of the JComponent superclass is entirely adequate, and you do not need a separate VetoableChangeSupport object.
This page is getting too long. See this page for the rest of the Beans story.