Javabeans
Javabeans
6. Event Handling: Beans can generate and respond to events, making them useful
in GUI applications.
JavaBeans Conventions:
• Properties: Defined by private fields with public getter (getX) and setter (setX)
methods.
Example
import java.io.Serializable;
// No-argument constructor
public PersonBean() {}
Benefits of JavaBeans:
• Ease of Use: With graphical tools, developers can manipulate JavaBeans without
needing to write extra code.
• Customization: Developers can easily extend and customize beans for specific
requirements.
Advantages of JavaBeans
1. Reusability:
2. Platform Independence:
4. Component-Based Development:
5. Graphical Manipulation:
6. Event Handling:
7. Persistence:
o JavaBeans are serializable, meaning their state can be saved and restored
later. This is particularly useful in scenarios where objects need to be
stored persistently (e.g., in files or databases) and retrieved later.
8. Standardized Architecture:
BDK Introspection refers to the capability provided by the Bean Development Kit
(BDK) to examine and manipulate JavaBeans during development. It allows developers
to explore the properties, methods, and events of a JavaBean dynamically at runtime
without needing the source code. This is a crucial feature in component-based
development, especially in environments where JavaBeans are used as reusable
software components.
2. Introspection Mechanism:
o The introspection process in JavaBeans allows a development
environment or application to discover:
3. JavaBeans Introspector:
o It uses the naming conventions (get, set, is, etc.) to discover the
properties and methods of the bean.
1. Automatic Introspection:
2. Explicit BeanInfo:
o If automatic introspection does not meet specific requirements,
developers can provide a custom BeanInfo class. This class explicitly
defines the properties, methods, and events of a bean.
Example of Introspection:
import java.beans.*;
} catch (Exception e) {
e.printStackTrace();
}
}
}
This program introspects a hypothetical PersonBean class, listing its properties and
methods by using the Introspector class.
A bound property is a property of a JavaBean that triggers events when its value
changes. Any object (usually another JavaBean or component) that is interested in
knowing about changes in the property can register itself as a property change
listener. When the property changes, a notification is sent to all registered listeners.
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public PersonBean() {}
Explanation:
1. PropertyChangeSupport: An instance of PropertyChangeSupport is used to
manage and notify listeners. It helps simplify the process of firing property
change events.
2. firePropertyChange: The firePropertyChange() method is called when a property
changes. It passes the property name, the old value, and the new value to the
listeners.
3. PropertyChangeListener: Other components can register themselves as
listeners to be notified of changes in the bean's properties.
Registering a Listener
To listen for changes in the bean's properties, you would add a listener like this:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
Output
Property name changed from null to Alice
Property age changed from 0 to 30
Key Classes:
• PropertyChangeListener: An interface that needs to be implemented by objects
that want to listen to property changes.
• PropertyChangeEvent: Encapsulates the details of the property change
(property name, old value, and new value).
• PropertyChangeSupport: A utility class that provides methods to add and
remove listeners and to fire property change events.
Advantages of Bound Properties:
1. Event-Driven Programming: Bound properties provide a way to implement
event-driven behavior, where one component can respond automatically to
changes in another.
2. Decoupling of Components: Components that use bound properties are
loosely coupled. The component that changes the property does not need to
know which other components are listening, making the design more modular
and maintainable.
3. Scalability: This pattern works well in applications where many components
interact and respond to state changes, such as in GUIs.
Real-World Use Cases:
• GUI Applications: For example, updating the display of a GUI element (e.g., a
text field) when the underlying data model changes.
• MVC Pattern: In a Model-View-Controller (MVC) architecture, the model can
notify the view when data changes, and the view can update automatically.
• Data Binding: Bound properties are essential in data-binding frameworks where
UI elements are automatically synchronized with the underlying data model.
The BeanInfo interface in Java is part of the java.beans package and is used to provide
explicit information about a JavaBean. The BeanInfo interface is used to override the
default introspection mechanism of JavaBeans, which uses reflection to infer
properties, methods, and events based on naming conventions (like get, set, is, etc.).
When developers want more control over the way a JavaBean is exposed to the outside
world, such as when building IDEs or GUI builders, they can implement the BeanInfo
interface to provide detailed metadata about the bean. By doing so, they can customize
how a bean’s properties, events, and methods are presented, potentially hiding certain
properties or providing custom property editors.
Purpose of BeanInfo Interface:
• Customization of Introspection: The BeanInfo interface allows developers to
customize the description of a JavaBean, specifying which properties, events,
and methods should be exposed or hidden.
• Custom Property Editors: You can specify custom editors for properties, which
allow users to interact with them in a more meaningful way, especially in visual
tools.
• Control over Default Introspection: It enables you to explicitly define the
behavior of introspection, rather than relying on default naming conventions.
Key Methods of the BeanInfo Interface:
The BeanInfo interface contains several methods that allow a developer to provide
specific metadata about a bean. The most important methods are:
• getPropertyDescriptors(): Returns an array of PropertyDescriptor objects that
describe the properties of the bean. Each PropertyDescriptor provides
information about a property, such as its name, type, getter, and setter methods.
• getMethodDescriptors(): Returns an array of MethodDescriptor objects, each
describing a public method of the bean.
• getEventSetDescriptors(): Returns an array of EventSetDescriptor objects,
which describe the events the bean fires and the listener interfaces for these
events.
• getBeanDescriptor(): Provides a general description of the bean itself (e.g., its
name, customizers, etc.).
• getDefaultPropertyIndex(): Specifies the index of the default property in the
array returned by getPropertyDescriptors(). A negative value indicates there is no
default property.
• getDefaultEventIndex(): Specifies the index of the default event in the array
returned by getEventSetDescriptors(). A negative value indicates there is no
default event.
• getIcon(): Allows you to specify a graphical icon for the bean, which can be
displayed in a visual bean builder.
Example: Implementing BeanInfo for a JavaBean
Here's how you would implement the BeanInfo interface for a PersonBean class to
provide explicit control over introspection:
The PersonBean Class:
import java.io.Serializable;
// No-argument constructor
public PersonBean() {}
@Override
public PropertyDescriptor[] getPropertyDescriptors() {
try {
// Define property descriptors for 'name' and 'age' properties
PropertyDescriptor nameDescriptor = new PropertyDescriptor("name",
PersonBean.class);
PropertyDescriptor ageDescriptor = new PropertyDescriptor("age",
PersonBean.class);
@Override
public MethodDescriptor[] getMethodDescriptors() {
return null; // Not customizing methods in this example
}
@Override
public EventSetDescriptor[] getEventSetDescriptors() {
return null; // No events in this example
}
@Override
public BeanDescriptor getBeanDescriptor() {
// Provide a basic descriptor for the bean
return new BeanDescriptor(PersonBean.class);
}
@Override
public int getDefaultPropertyIndex() {
return 0; // The 'name' property is the default property
}
@Override
public int getDefaultEventIndex() {
return -1; // No default event
}
@Override
public Image getIcon(int iconKind) {
return null; // No custom icon in this example
}
• getIcon(): In this example, we return null, but you can return an image to provide
an icon for the bean in a graphical tool (e.g., when displayed in a palette).
When using BeanInfo, you can also specify custom property editors by overriding the
getPropertyDescriptors() method to associate properties with specific editors. Custom
editors are useful when the default property editor (such as a text field for strings) is not
sufficient.
For example, if you wanted a property editor for a Color property, you could specify a
custom editor that allows the user to pick a color from a palette.
3. Hiding Properties: You can hide properties or methods that should not be
exposed by excluding them from the getPropertyDescriptors() or
getMethodDescriptors() methods.
Constrained Properties and Persistence in JavaBeans
Constrained properties in JavaBeans are properties that can prevent a change from
being made if certain conditions are not met. These properties allow listeners to veto
changes, making them particularly useful in cases where certain components or
objects should have the ability to reject or approve property modifications.
In the context of persistence, constrained properties can add complexity, since vetoing
a property change can prevent the property from being persisted (saved).
Understanding how to properly handle constrained properties and persistence is crucial
when designing beans that will be saved and restored later.
Key Concepts
1. Constrained Properties:
o If any listener vetoes the change, the property’s value will not be updated.
2. VetoableChangeListener:
3. Persistence:
Let’s look at an example where a JavaBean has a constrained property called age, and
listeners can veto the change if the new age value is not acceptable.
import java.io.Serializable;
public PersonBean() {}
return name;
this.name = name;
return age;
this.age = newAge;
vetoSupport.addVetoableChangeListener(listener);
vetoSupport.removeVetoableChangeListener(listener);
In this example:
Adding a VetoableChangeListener
Here’s how you can add a listener to veto the age property if it falls outside a specified
range:
public class VetoableChangeExample {
try {
person.addVetoableChangeListener(evt -> {
if ("age".equals(evt.getPropertyName())) {
});
} catch (PropertyVetoException e) {
Output:
Vetoed: Invalid age: 150
To persist the state of a JavaBean with constrained properties, the bean needs to
implement Serializable. However, there are additional considerations when dealing with
vetoable changes:
import java.io.*;
try {
person.setName("Alice");
person.setAge(25);
// Serialize the object to a file
oos.writeObject(person);
oos.close();
ois.close();
} catch (Exception e) {
e.printStackTrace();
Output:
Name: Alice
Age: 25