Search |
||
How to veto a property change?Posted by malenkov on November 22, 2007 at 3:01 AM PST
Correct usage of constrained properties seems still remain unclear for many users. As is the convention in the Java, the With constrained properties, an outside object (either the source bean itself or a listener) can veto a property change. How the bean can veto a property change?It is quite simple. The property setter should declare that it throws public class SimpleBean {
private int value;
public int getValue() {
return this.value;
}
public void setValue(int value) throws PropertyVetoException {
if (value < 0) {
throw new PropertyVetoException(
"the value change rejected",
new PropertyChangeEvent(this, "value", this.value, value));
}
this.value = value;
}
}
How a listener can veto a property change?The JavaBeans API provides the event mechanism for handling constrained properties. The public class VetoableBean {
private final VetoableChangeSupport vcs = new VetoableChangeSupport(this);
public void addVetoableChangeListener(VetoableChangeListener listener) {
this.vcs.addVetoableChangeListener(listener);
}
public void removeVetoableChangeListener(VetoableChangeListener listener) {
this.vcs.removeVetoableChangeListener(listener);
}
private int value;
public int getValue() {
return this.value;
}
public void setValue(int value) throws PropertyVetoException {
this.vcs.fireVetoableChange("value", this.value, value);
this.value = value;
}
}
In this case, the bean examines all listeners. If one throws private static class Listener implements VetoableChangeListener {
public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException {
if (event.getPropertyName().equals("value"))
if ((Integer) event.getNewValue() < 0)
throw new PropertyVetoException("I object!", event);
}
}
Javadoc specification says: if anyone vetoes the change, then fire a new event reverting everyone to the old value and then rethrow the private static class Listener implements VetoableChangeListener {
public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException {
if (!isUndo(event))
if (event.getPropertyName().equals("value"))
if ((Integer) event.getNewValue() < 0)
throw new PropertyVetoException("I object!", event);
}
private static boolean isUndo(PropertyChangeEvent event) {
try {
return event.getNewValue().equals(getCurrentValue(event));
} catch (Exception exception) {
return false;
}
}
private static Object getCurrentValue(PropertyChangeEvent event) throws Exception {
Object bean = event.getSource();
String name = event.getPropertyName();
BeanInfo info = Introspector.getBeanInfo(bean.getClass());
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
if (pd.getName().equals(name)) {
return pd.getReadMethod().invoke(bean);
}
}
throw new IllegalArgumentException(name);
}
}
This common solution could be optimized for the specific case. JDK 7 changes the behaviourSpecification mentions that the new event will notify all listeners if the change is rolled back. I disagree with this statement. The "undo" events must be fired only for those listeners, which received and approved the property change event. This functionality is available in JDK7. For example, we have 3 listeners and the second listener vetoes the change. The following event sequence will be generated for this case:
Old behavior in JDK 6:
New behavior in JDK 7: In other words, the second listener will be not notified, because it vetoed the property change, while the third listener will not be notified, because it simply does not know about the change. »
Related Topics >>
J2SE Comments
Comments are listed in date ascending order (oldest first)
|
||
|
|