Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Understanding Java's Component Model


Features: September 1998: Understanding Java's Component Model

Understanding the JavaBeans architecture will help you maximize creative solutions with component-based development.

Software developers are constantly being asked to build applications in less time with less money. And, of course, those applications are expected to be better and faster than ever. Object-oriented techniques and component software environments are widely used in the hope they will help us build applications more quickly. During the past few years, some have seen Java as the next "silver-bullet." Although this is obviously not the case, Java does offer a potential increase in productivity over many other programming environments.

Components are self-contained elements of software that you can control dynamically and assemble to form applications. Simply put, they are the building blocks used to create applications. But that's not the entire story. They must also interoperate according to some rules and guidelines. It's like a society of software citizens. The citizens (components) bring functionality and add value, and the society (environment) brings structure and order.

JavaBeans is the component model for Java development. It lets users construct applications by piecing components together programmatically, visually, or both. The support of visual programming is paramount to the component model. It's one of the things that makes component-based software development truly powerful.

Component Models

Any component model is essentially made up of an architecture and an API. Together, these elements provide a structure whereby components are combined to create an application. This environment provides services and rules, letting components participate properly. This means components are provided with the tools necessary to live in the environment, and the component exhibits certain behaviors that identify it as such. You may have the perception that this arrangement is too confining, not leaving enough creative freedom to develop elegant software solutions. Well, that just isn't so. This architecture lends itself well to creative solutions, while ensuring individual pieces of a larger system can be built independent of the system as a whole.

The fact is, you don't need to design components with the big picture in mind. As long as some basic rules are followed, you can reuse them on projects with goals and requirements that were never envisioned when the component was first developed. A simple example is a button widget on a dialog box. Most button designs and implementation are not influenced by the kind of application in which they will be used.

As I mentioned previously, components are expected to exhibit certain behaviors and characteristics that let them participate in the component structure and interact with its environment and other components. In other words, a combination of elements actually define the component model.

Discovery

Class and interface discovery is the mechanism used to locate a component at run time and to determine its supported interfaces so others can use them. The model must provide a registration process for a component to make itself and its interfaces known, so they can be discovered at run time. This dynamic binding lets you develop components and applications independently of each other. The dependency is limited to the contract between the parties; in this case, the interfaces that the component supports. An application doesn't have to include a component during the development process for it to make use of it at run time. Dynamic binding also allows the updating of components without having to rebuild the applications that use them.

You can also use this discovery process in a design-time environment. In this case, a development tool may be able to locate a component and make it available for the designer to use. Many visual programming environments support discovery via toolbars of available software components.

Event Handling

An event is an occurrence, something of importance that happens at a specific point in time. An event might take place due to a user action such as a mouse click. Events can also be initiated by other means. Imagine the heating system in your house. It contains a thermostat that is used to set the desired comfort temperature, keep track of the current ambient temperature, and notify the heating unit when its services are required. If the thermostat is set to keep the room at 70 degrees Fahrenheit, it will notify the heater to start producing heat when the temperature dips below that threshold. When an event takes place, components send notifications to all other objects that have interest in the event.

Persistence

Generally, all components have state. The thermostat component's state represents the comfort temperature. If the thermostat was a software component of a computer-based heating control system, you would want the value of the comfort temperature stored on a non-volatile storage medium (such as a hard disk). This way, if you shut down the application and then brought it back up, the thermostat control would still be set to 70 degrees. The visual representation and position of the thermostat relative to other components in the application would also be restored.

Components must be able to participate in the persistence mechanism of their container so all components in the application can provide application-wide persistence uniformly. If every component implemented its own method of persistence, it would be impossible for an application container to use its components in a general way. This wouldn't be an issue if reuse weren't the goal. If you were building a monolithic temperature control system, you could create an application-specific mechanism for storing state. But, if you wanted the thermostat component to be used again in another application, you'd want to use a standard mechanism for persistence.

Visual Presentation

The component environment lets individual components control most of their visual presentation. For example, imagine your thermostat component displays the current ambient temperature. You might want to display the temperature in different fonts or colors depending on whether it's above or below the comfort temperature. The component is free to choose the characteristics of its own visual presentation. Many of these characteristics will be properties of the component, a topic I'll discuss later. Some of these visual properties will be persistent, meaning they will represent some state of the component that is saved to, and restored from, persistent storage.

Another important aspect of visual presentation is layout. It concerns the way components are arranged on screen, how they relate to one another, and their behavior when users interact with them. The container object used to hold an assembly of components will usually provide layout-related services to the component.

Consider the thermostat and heating control application again. This time, the user changes the size of the application window. The container interacts with the components in response to this action, possibly changing the size of some components. In turn, by changing the size of the thermostat component, it alters its font size. As you can see, the container and the component work together to provide an application that presents itself uniformly. The application appears to be working as one unit. And with the component development model, the container and the components will likely be created separately by different developers.

And Now, JavaBeans

JavaBeans is an architecture for using and building components in Java. It supports the features of software reuse, component models, and object orientation. One of the most important features of JavaBeans is that it doesn't alter the existing Java language. This means if you know how to write software in Java, you know how to use and create Beans. The strengths of Java are built upon and extended to create the JavaBeans component architecture.

Although Beans are intended to work in a visual application development tool, not all Beans have a visual representation at run time. What this does mean is that Beans must let you change their property values through some sort of visual interface. It also means that their methods and events should be exposed so the development tool can write code that will manipulate the component when the application is executed.

Creating a Bean

As you'll see, creating a Bean doesn't require any advanced concepts. But before I go any further in describing Beans, here's some code that shows you how to implement one:

public class MyBean implements
    java.io.Serializable
{
    protected int theValue;

    public MyBean()
    {
    }

    public void setMyValue(int newValue)
    {
        theValue = newValue;
    }

    public int getMyValue()
    {
        return theValue;
    }
}

This is a real Bean named MyBean that has state (the variable theValue) that will automatically have persistence, and a property named MyValue that is usable by a visual programming environment. This Bean doesn't have any visual representation, but that isn't a requirement for being a JavaBean component.

Properties, Methods, and Events

Properties are attributes of a Bean that are referenced by name. These properties are usually read and written by calling methods on the Bean specifically created for that purpose. A property of the thermostat component might be the comfort temperature. A programmer could set or get the value of this property through method calls, while an application developer with a visual development tool could manipulate its value using a visual property editor.

The methods of a Bean are just the Java methods exposed by the class that implements the Bean. These methods represent the interface used to access and manipulate the component. Usually, the set of public methods defined by the class will map directly to the supported methods for the Bean, although the Bean developer can choose to expose only a subset of the public methods.

Events are the mechanism used by one component to send notifications to another. One component can register its interest in the events generated by another. Whenever the event occurs, the interested component will be notified by having one of its methods invoked. To register interest in an event, you call the appropriate method on the component that is the source of the event. In turn, when an event occurs, a method will be invoked on the component that registered its interest. In most cases, more than one component can register for event notifications from a single source. The component that is interested in event notifications is said to be listening for the event.

Introspection

Introspection is the process of exposing the properties, methods, and events that a JavaBean component supports. This process is used at run time as well as by a visual development tool at design time. Its default behavior allows for the introspection of any Bean automatically. First, a low-level reflection mechanism is used to analyze the Bean's class to determine its methods. Next, it applies some simple design patterns to determine the supported properties and events. For this to take place, the developer just needs to follow a coding style that matches the design pattern. This is an important feature of JavaBeans. It means you don't have to do anything more than code your methods using a simple convention. If you do this, your Beans will automatically support introspection without your having to write any extra code. I'll explain the use of design patterns in more detail a little later.

This technique may not be sufficient or suitable for every Bean. Instead, you can choose to implement a BeanInfo class that provides descriptive information about its associated Bean. This is obviously more work than using the default behavior, but it might be necessary to properly describe a complex Bean. It is important to note that the BeanInfo class is separate from the Bean it is describing. This is so the baggage of the BeanInfo isn't carried around within the Bean itself.

Customization

When you're using a visual development tool to assemble components into applications, a user interface for customizing the attributes of a Bean is presented to you. These attributes may affect the way the Bean operates or the way it looks on the screen. The application tool you use will be able to determine the properties supported by a Bean and dynamically build a property sheet. This property sheet will contain property editors for each of the properties supported by the Bean. You can use the individual editors on the property sheet to customize the Bean to your liking. The Bean's class library comes with property editors for common types such as float, boolean, and String. If you are using custom classes for properties, you will have to create custom property editors to associate with them.

In some cases, the default property sheet created by the development tool will not be good enough. You may be working with a Bean that is too complex to easily customize in this way. Beans developers have the option of creating a customizer that the user can run to help them customize an instance of their Bean. You might even create smart wizards that guide users through the customization process.

Customizers are kept separate from the Bean class to keep from adding unneeded functionality to the Bean when it's not being customized. This is a common theme in the architecture. The only thing a Bean class has to implement directly is the functionality for which it was designed. All other supporting features are implemented separately.

Persistence

Beans must support a large variety of storage mechanisms. This way, they can participate in the largest number of applications. The simplest way to support persistence is to take advantage of Java Object Serialization. This is an automatic mechanism for saving and restoring the state of an object. It is the best way to make sure your Beans are fully portable, because you are taking advantage of a standard feature supported by the core Java platform. But this is not always desirable. There may be cases where you want your Bean to use other file formats or mechanisms to save and restore state. JavaBeans supports this as well.

Visibility

Beans don't need to be visible at run time. It is perfectly reasonable for a Bean to provide functionality that does not require it to present an interface to the user. The Bean may be controlling access to a specific device or data feed. However, it is necessary for it to support the visual application builder. The Bean component can have properties, methods, events, a persistent state, and interact with other Beans in a larger application. This Bean may be shown visually in the application development tool, and may provide custom property editors and customizers.

Using Design Patterns

The JavaBeans architecture uses patterns that represent standard conventions for names and type signatures for collections of methods and interfaces. Using coding standards is always a good idea because it makes your code easier to understand and therefore easier to maintain. It also makes it easier for another developer to understand the purpose of the methods and interfaces used by your component. In the JavaBeans architecture, these patterns have more significance. A set of simple patterns are used by the default introspection mechanism to analyze your Bean and determine the properties, methods, and events that it supports. This lets the visual development tools analyze your Bean and use it in the application being created. The following code fragment is an example of such use of patterns:

public void setTemperatureColor(Color 
    newColor)
{
    . . .
}
public Color getTemperatureColor()
{
    . . .
}

These two methods together use a pattern that signifies the Bean contains a read/write property named Temperature Color of type Color. This is the simplest technique to which the Bean programmer can conform. No extra development is required to expose the property. As mentioned earlier, this convention is not a requirement. You can implement a specific BeanInfo class that fully describes the properties, methods, and events supported by your Bean. In this case, you can name your methods anything you please.

Just the Beginning

So now you have a better understanding of what the JavaBeans architecture is all about. This is just the beginning'the fun really starts when you begin to use this model to develop real applications. Of course, the architecture will not solve your problems, but it will provide a guiding approach and framework for developing interoperating components that, together, comprise a complete application.

Many IDEs support JavaBeans, and there are a number of good books and online articles to help you along the way. The architecture and supporting framework are there. It's up to the software development community to adopt the model and use it to fulfill the potential of component-based development.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.