Download the JDK
Search the Tutorials
Hide the TOC
Trail: JavaBeans(TM)
Lesson: Properties
Properties
Simple Properties
Bound Properties
Constrained Properties
Indexed Properties
Home Page > JavaBeans(TM) > Properties
« Previous • Trail • Next »
Constrained Properties

> > A bean property is constrained if the bean supports the `VetoableChangeListener`(in the API reference documentation) and `PropertyChangeEvent`(in the API reference documentation) classes, and if the set method for this property throws a `PropertyVetoException`(in the API reference documentation).

> > Constrained properties are more complicated than bound properties because they also support property change listeners which happen to be vetoers.

> > The following operations in the `setXXX` method for the constrained property must be implemented in this order:

> > 1. Save the old value in case the change is vetoed.
> > 2. Notify listeners of the new proposed value, allowing them to veto the change.
> > 3. If no listener vetoes the change (no exception is thrown), set the property to the new value.

> > The accessor methods for a constrained property are defined in the same way as those for simple properties, with the addition that the `setXXX` method throws a `PropertyVetoException` exception. The syntax is as follows:

> >     	public void setPropertyName(PropertyType pt)
> >     	throws PropertyVetoException {code}

> > ### Handling Vetoes

> > If a registered listener vetoes a proposed property change by throwing a `PropertyVetoException` exception, the source bean with the constrained property is responsible for the following actions:
> > - Catching exceptions.
> > - Reverting to the old value for the property.
> > - Issuing a new `VetoableChangeListener.vetoableChange` call to all listeners to report the reversion.
> > The `VetoableChangeListener` class throws a `PropertyVetoException` and handles the `PropertyChangeEvent` event fired by the bean with the constrained property.

> > The `VetoableChangeSupport` provides the following operations:

> > - Keeping track of `VetoableChangeListener` objects.
> > - Issuing the `vetoableChange` method on all registered listeners.
> > - Catching any vetoes (exceptions) thrown by listeners.
> > - Informing all listeners of a veto by calling `vetoableChange` again, but with the old property value as the proposed "new" value.

> > ### Creating a Constrained Property

> > To create a constrained property, set the appropriate option in the New Property Pattern form as shown on the following figure.

> > Note that the Multicast Source Event Pattern - vetoableChangeListener was added to the Bean Patterns hierarchy.

> > You can also modify the existing code generated in the previous lesson to make the `title` and `lines` properties constrained as follows (where newly added code is shown in bold):

> >     import java.io.Serializable;
> >     import java.beans.PropertyChangeListener;
> >     import java.beans.PropertyChangeSupport;
> >     import java.beans.PropertyVetoException;
> >     import java.beans.VetoableChangeListener;
> >     import java.beans.VetoableChangeSupport;
> >     import java.awt.Graphics;
> >     import javax.swing.JComponent;

> >     /**
> >      * Bean with constrained properties.
> >      */
> >     public class MyBean
> >             extends JComponent
> >             implements Serializable
> >     {
> >         private String title;
> >         private String[] lines = new String[10];

> >         private final PropertyChangeSupport pcs = new PropertyChangeSupport( this );
> >         private final VetoableChangeSupport vcs = new VetoableChangeSupport( this );

> >         public String getTitle()
> >         {
> >             return this.title;
> >         }
> >     /**
> >      * This method was modified to throw the PropertyVetoException
> >      * if some vetoable listeners reject the new title value
> >      */
> >         public void setTitle( String title )
> >                 throws PropertyVetoException
> >         {
> >             String old = this.title;
> >             this.vcs.fireVetoableChange( "title", old, title );
> >             this.title = title;
> >             this.pcs.firePropertyChange( "title", old, title );
> >         }

> >         public String[] getLines()
> >         {
> >             return this.lines.clone();
> >         }

> >         public String getLines( int index )
> >         {
> >             return this.lines[index];
> >         }
> >     /**
> >      * This method throws the PropertyVetoException
> >      * if some vetoable listeners reject the new lines value
> >      */
> >         public void setLines( String[] lines )
> >                 throws PropertyVetoException
> >         {
> >             String[] old = this.lines;
> >             this.vcs.fireVetoableChange( "lines", old, lines );
> >             this.lines = lines;
> >             this.pcs.firePropertyChange( "lines", old, lines );
> >         }

> >         public void setLines( int index, String line )
> >                 throws PropertyVetoException
> >         {
> >             String old = this.lines[index];
> >             this.vcs.fireVetoableChange( "lines", old, line );
> >             this.lines[index] = line;
> >             this.pcs.fireIndexedPropertyChange( "lines", index, old, line );
> >         }

> >         public void addPropertyChangeListener( PropertyChangeListener listener )
> >         {
> >             this.pcs.addPropertyChangeListener( listener );
> >         }

> >         public void removePropertyChangeListener( PropertyChangeListener listener )
> >         {
> >             this.pcs.removePropertyChangeListener( listener );
> >         }
> >     /**
> >      * Registration of the VetoableChangeListener
> >      */
> >         public void addVetoableChangeListener( VetoableChangeListener listener )
> >         {
> >             this.vcs.addVetoableChangeListener( listener );
> >         }

> >         public void removeVetoableChangeListener( VetoableChangeListener listener )
> >         {
> >             this.vcs.addVetoableChangeListener( listener );
> >         }

> >         protected void paintComponent( Graphics g )
> >         {
> >             g.setColor( getForeground() );

> >             int height = g.getFontMetrics().getHeight();
> >             paintString( g, this.title, height );

> >             if ( this.lines != null )
> >             {
> >                 int step = height;
> >                 for ( String line : this.lines )
> >                     paintString( g, line, height += step );
> >             }
> >         }

> >         private void paintString( Graphics g, String str, int height )
> >         {
> >             if ( str != null )
> >                 g.drawString( str, 0, height );
> >         }
> >     }

« Previous • Trail • Next »
Previous page: Bound Properties
Next page: Indexed Properties