0% found this document useful (0 votes)
9 views21 pages

Javabeans

Uploaded by

Shreyans Jaiswal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views21 pages

Javabeans

Uploaded by

Shreyans Jaiswal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

Introduction to Java Beans

JavaBeans is a reusable software component model in Java, allowing developers to


create modular and reusable objects. A JavaBean follows certain conventions, enabling
it to be manipulated visually in a builder tool. JavaBeans are used in enterprise-level
applications due to their ability to simplify development by promoting reusability,
scalability, and maintainability.

Key Features of JavaBeans:

1. Encapsulation: JavaBeans encapsulate multiple objects into a single bean,


making it easier to handle.

2. Reusability: JavaBeans are reusable components, allowing for better code


modularity and maintenance.

3. Platform Independence: JavaBeans are platform-independent, as they are


written in Java and can be run on any platform that supports the Java Runtime
Environment (JRE).

4. Serializable: JavaBeans implement the Serializable interface, enabling their


persistence (i.e., saving the state of a bean and restoring it later).

5. Property Manipulation: JavaBeans support getter and setter methods for


manipulating their properties, allowing external access in a controlled manner.

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.

• No-argument Constructor: Every JavaBean should have a no-argument


constructor to allow easy instantiation.

• Serializable Interface: Implementing this interface allows a bean to be saved


and restored across different environments.

Example
import java.io.Serializable;

public class PersonBean implements Serializable {


private String name;
private int age;

// No-argument constructor
public PersonBean() {}

// Getter for 'name' property


public String getName() {
return name;
}

// Setter for 'name' property


public void setName(String name) {
this.name = name;
}

// Getter for 'age' property


public int getAge() {
return age;
}

// Setter for 'age' property


public void setAge(int age) {
this.age = age;
}
}

Benefits of JavaBeans:

• Interoperability: JavaBeans can interact with various components in a


standardized manner.

• 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

JavaBeans provide several benefits in the development of enterprise-level


applications. Their structured design and reusability make them a powerful tool for
developers. Here are some of the key advantages:

1. Reusability:

o JavaBeans are modular components that can be reused across different


applications or systems. This promotes faster development by reducing
duplication of code and effort.

2. Platform Independence:

o JavaBeans are written in Java, which is platform-independent. As long as


the Java Runtime Environment (JRE) is available, JavaBeans can run on
any platform, making them highly portable.

3. Easy Property Management:

o JavaBeans use getter and setter methods to access and modify


properties. This provides encapsulation and ensures controlled access to
object properties, adhering to good object-oriented principles.

4. Component-Based Development:

o JavaBeans enable the development of applications using a component-


based architecture. Components can be developed, tested, and
maintained separately, contributing to more scalable and maintainable
systems.

5. Graphical Manipulation:

o JavaBeans can be manipulated in development tools (like IDEs) visually,


without needing to write code. This makes it easier for developers to
integrate and configure components within an application.

6. Event Handling:

o JavaBeans support event handling through a well-defined listener model,


making them ideal for developing interactive GUI applications.
Components can generate and listen for events such as button clicks, key
presses, etc.

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:

o JavaBeans follow a standard architecture (no-argument constructor,


property naming conventions, etc.), making it easier to integrate them
with other Java-based frameworks and tools.

9. Customization and Flexibility:

o JavaBeans are customizable and flexible. They can be extended or


modified to suit specific application needs without altering the core
functionality.

10. Loose Coupling:

o JavaBeans enable loose coupling between components. This means


individual beans can function independently and interact through well-
defined interfaces, leading to more modular and flexible system designs.

Common Use Cases of JavaBeans:

• Building reusable business logic components

• Creating user interface components for web and desktop applications

• Facilitating data exchange between different layers of an application (e.g.,


database access beans)

• Used in Java EE for Enterprise JavaBeans (EJB) for developing server-side


components

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.

Key Aspects of BDK Introspection:

1. Bean Development Kit (BDK):

o BDK is a toolkit provided by Sun Microsystems (now Oracle) to assist


developers in creating, testing, and configuring JavaBeans. It includes
tools that can introspect the beans to understand their structure and
behavior.

2. Introspection Mechanism:
o The introspection process in JavaBeans allows a development
environment or application to discover:

▪ Properties: Attributes of the bean that can be accessed and


modified via getter and setter methods.

▪ Methods: Functions that can be invoked on the bean.

▪ Events: Event-handling mechanisms, which can notify other


components when certain actions occur.

3. JavaBeans Introspector:

o Java provides the Introspector class (from java.beans.Introspector) that


facilitates introspection. This class can analyze the bean and provide
details such as available properties, methods, and events.

o It uses the naming conventions (get, set, is, etc.) to discover the
properties and methods of the bean.

4. PropertyDescriptor, MethodDescriptor, and EventSetDescriptor:

o Introspection uses descriptor classes to describe properties, methods,


and events:

▪ PropertyDescriptor: Describes a bean property and provides


methods to read/write values.

▪ MethodDescriptor: Describes a bean method and provides


information about method signatures.

▪ EventSetDescriptor: Describes events a bean can generate and


the listeners that can be registered.

How BDK Introspection Works:

1. Automatic Introspection:

o By default, JavaBeans follow naming conventions for properties and


events. Tools like BDK use these conventions to introspect the beans
automatically. For example:

▪ A method named getName suggests the presence of a property


called name.

▪ A method named addActionListener indicates the ability to handle


ActionEvents.

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:

Here's an example of how to use Java's introspection API to inspect a bean:

import java.beans.*;

public class IntrospectionExample {


public static void main(String[] args) {
try {
// Create an instance of the bean
Class<?> beanClass = Class.forName("PersonBean");

// Introspect the bean


BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);

// Retrieve property descriptors


PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
System.out.println("Properties:");
for (PropertyDescriptor pd : propertyDescriptors) {
System.out.println(" - " + pd.getName());
}

// Retrieve method descriptors


MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
System.out.println("\nMethods:");
for (MethodDescriptor md : methodDescriptors) {
System.out.println(" - " + md.getMethod().getName());
}

} catch (Exception e) {
e.printStackTrace();
}
}
}
This program introspects a hypothetical PersonBean class, listing its properties and
methods by using the Introspector class.

Benefits of BDK Introspection:


• Dynamic Analysis: Allows developers to inspect and manipulate JavaBeans
during runtime, even if the bean's source code is not available.

• Flexibility: Enables bean builders (e.g., graphical development environments) to


expose and manipulate properties and events visually.

• Customization: Developers can override the default introspection behavior by


implementing custom BeanInfo classes, providing fine control over which
properties, methods, and events are exposed.
Bound Properties in JavaBeans are properties that notify listeners when their value
changes. This is essential when developing applications where components need to
respond to changes in other components' properties, such as in a graphical user
interface (GUI) or enterprise application.

What are Bound Properties?

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.

Steps to Implement a Bound Property:

1. Property Change Event: When the value of a bound property changes, a


PropertyChangeEvent is fired.

2. Listeners: Interested components can register as PropertyChangeListeners to


receive notifications.

3. PropertyChangeSupport: Java provides the PropertyChangeSupport class to


simplify the management of property change listeners and the firing of property
change events.

Example: Creating a JavaBean with a Bound Property

Here’s how you can implement a JavaBean with a bound property:

import java.beans.PropertyChangeListener;

import java.beans.PropertyChangeSupport;

public class PersonBean {


private String name;
private int age;

// Support for property changes


private PropertyChangeSupport pcs = new PropertyChangeSupport(this);

public PersonBean() {}

// Getter for 'name'


public String getName() {
return name;
}
// Setter for 'name' with bound property support
public void setName(String name) {
String oldName = this.name;
this.name = name;
// Notify listeners about the property change
pcs.firePropertyChange("name", oldName, this.name);
}

// Getter for 'age'


public int getAge() {
return age;
}

// Setter for 'age' with bound property support


public void setAge(int age) {
int oldAge = this.age;
this.age = age;
// Notify listeners about the property change
pcs.firePropertyChange("age", oldAge, this.age);
}

// Method to add a property change listener


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

// Method to remove a property change listener


public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
}

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;

public class PropertyChangeExample {


public static void main(String[] args) {
// Create an instance of the PersonBean
PersonBean person = new PersonBean();

// Add a listener to monitor changes to the 'name' property


person.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("Property " + evt.getPropertyName() + " changed from "
+ evt.getOldValue() + " to " + evt.getNewValue());
}
});

// Change properties, triggering the listener


person.setName("Alice");
person.setAge(30);
}
}

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;

public class PersonBean implements Serializable {


private String name;
private int age;

// No-argument constructor
public PersonBean() {}

// Getter and Setter for name


public String getName() {
return name;
}

public void setName(String name) {


this.name = name;
}

// Getter and Setter for age


public int getAge() {
return age;
}

public void setAge(int age) {


this.age = age;
}
}

The Custom BeanInfo Class:


import java.beans.*;

public class PersonBeanBeanInfo implements BeanInfo {

@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);

// Return the array of property descriptors


return new PropertyDescriptor[] { nameDescriptor, ageDescriptor };
} catch (IntrospectionException e) {
e.printStackTrace();
return null;
}
}

@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
}

// Methods below are part of BeanInfo but not used here


@Override
public BeanInfo[] getAdditionalBeanInfo() {
return null;
}
}
Explanation:

• getPropertyDescriptors(): This method returns an array of PropertyDescriptor


objects, specifying the name and age properties. Each PropertyDescriptor links a
property to its getter and setter methods.

• getMethodDescriptors(): This method returns null in the example, meaning that


no custom method descriptors are provided. If we wanted to customize which
methods are visible, we would return an array of MethodDescriptor objects here.

• getEventSetDescriptors(): Similarly, this method returns null because no event


handling is being customized.

• getBeanDescriptor(): Provides a basic descriptor for the bean class, but we


could add more detailed information here if needed.

• 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).

Custom Property Editors:

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.

Advantages of Using BeanInfo:

1. Explicit Control: Developers have precise control over which properties,


methods, and events are exposed and how they are represented in development
environments.

2. Customization: Custom BeanInfo implementations allow the specification of


icons, default properties, and custom property editors, improving the developer
experience in GUI builders or IDEs.

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 A constrained property is a property that fires a PropertyChangeEvent


just like a bound property, but it also allows any registered
VetoableChangeListeners to reject the change.

o If any listener vetoes the change, the property’s value will not be updated.

2. VetoableChangeListener:

o A VetoableChangeListener is a listener that listens for changes in a


constrained property and has the ability to veto (reject) the change.

o It implements the vetoableChange() method, where the logic for


approving or rejecting changes is placed.

3. Persistence:

o Persistence refers to the ability to store the state of an object (including


its properties) in a form that can be restored later (e.g., saving to a file,
database, or transmitting over a network).

o For a JavaBean to be persistable, it must implement the Serializable


interface, and its properties (including constrained ones) must be
serializable.

Example: Creating a Constrained Property

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.

PersonBean with Constrained Property:


import java.beans.*;

import java.io.Serializable;

public class PersonBean implements Serializable {

private String name;

private int age;

// Support for vetoable changes

private VetoableChangeSupport vetoSupport = new VetoableChangeSupport(this);

public PersonBean() {}

// Getter for name

public String getName() {

return name;

// Setter for name

public void setName(String name) {

this.name = name;

// Getter for age

public int getAge() {

return age;

// Setter for age with constrained property support


public void setAge(int newAge) throws PropertyVetoException {

int oldAge = this.age;

// Fire vetoable change event

vetoSupport.fireVetoableChange("age", oldAge, newAge);

// If no listener vetoed, update the property

this.age = newAge;

// Method to add a vetoable change listener

public void addVetoableChangeListener(VetoableChangeListener listener) {

vetoSupport.addVetoableChangeListener(listener);

// Method to remove a vetoable change listener

public void removeVetoableChangeListener(VetoableChangeListener listener) {

vetoSupport.removeVetoableChangeListener(listener);

In this example:

• The age property is constrained. Before changing its value, the


fireVetoableChange() method is called, allowing listeners to reject the change.

• The VetoableChangeSupport class is used to manage listeners and handle firing


the PropertyChangeEvent that supports vetoing.

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 {

public static void main(String[] args) {

try {

// Create an instance of the PersonBean

PersonBean person = new PersonBean();

// Add a VetoableChangeListener to restrict age changes

person.addVetoableChangeListener(evt -> {

if ("age".equals(evt.getPropertyName())) {

int newAge = (int) evt.getNewValue();

if (newAge < 0 || newAge > 120) {

throw new PropertyVetoException("Invalid age: " + newAge, evt);

});

// Try setting a valid age

person.setAge(30); // This will succeed

// Try setting an invalid age (will be vetoed)

person.setAge(150); // This will throw a PropertyVetoException

} catch (PropertyVetoException e) {

System.out.println("Vetoed: " + e.getMessage());

Output:
Vetoed: Invalid age: 150

Persistence of Constrained Properties

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:

1. Serialization: If your bean is serializable, its properties (including constrained


properties) will be saved when the bean is persisted. This means the value of the
constrained property is stored as part of the object's state.

2. Listener Persistence: The listeners themselves (such as


VetoableChangeListeners) are generally not serialized as part of the bean's
state. If you want listeners to be restored after deserialization, you would need to
re-register them manually or handle this process as part of your application
logic.

3. Restoring State: When deserializing a JavaBean, the constrained properties will


be restored to their saved values. However, any veto logic will not apply during
the deserialization process, as the properties are being directly restored from the
persisted state.

Example: Serializing a Bean with Constrained Properties

Here’s how you can serialize a bean to a file:

import java.io.*;

public class SerializationExample {

public static void main(String[] args) {

try {

// Create an instance of the PersonBean

PersonBean person = new PersonBean();

person.setName("Alice");

person.setAge(25);
// Serialize the object to a file

FileOutputStream fos = new FileOutputStream("personbean.ser");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(person);

oos.close();

System.out.println("Bean serialized successfully!");

// Deserialize the object from the file

FileInputStream fis = new FileInputStream("personbean.ser");

ObjectInputStream ois = new ObjectInputStream(fis);

PersonBean deserializedPerson = (PersonBean) ois.readObject();

ois.close();

// Output the restored property values

System.out.println("Name: " + deserializedPerson.getName());

System.out.println("Age: " + deserializedPerson.getAge());

} catch (Exception e) {

e.printStackTrace();

Output:

Bean serialized successfully!

Name: Alice

Age: 25

You might also like