Grinding Java - Beans Components
Written by Shai Almog
When I first started studying object oriented methodology I was very confused. It seemed to me as if I was missing something since the ideas were so simple yet they were all the rave of highly skilled programmer's. After a while I decided that OO is rather simple and started developing in C++. But pretty soon I found out that understanding the syntax and basic concepts was not good enough.
I experienced the same sort of confusion when approaching Java beans. When I read the explanations in Sun's pages it seemed a little to simple; it is. In essence we have already developed some Java beans.
What are beans?
Java Beans were created by Sun to follow the success of OCX's (now renamed ActiveX) and VBX's (mostly obsolete). Beans are pluggable components used by visual development tools to allow a programmer to add functionality in a simple and visual way.
All of Java's AWT 1.1 Components are beans! Since we derive from these components we have essentially created very crude and very basic beans.
What are the basic requirements of a bean?
- A bean must be a subclass of component.
- A bean must be Serializable - when a class is serializable it means it can turn its state into a stream thus allowing the saving and transfer of the bean's data.
- A bean must follow a naming convention - i.e. all properties of the bean are defined by functions that begin with get and set:
File getFile(); void setFile();
exposes a bean property titled file. If we remove the setFile method the file property will become read only.
- A bean must be packaged in a JAR file. JAR files are new to JDK 1.1. They allow the grouping of files and resources into one file which may be compressed and is 100% compatible with zip files.
- All beans should have a default constructor (a constructor with no parameters), so they will be easier to load.
I used the code from Sun's BDK (Bean Development Kit) to study this subject and I believe it will be useful for you too. Sun's BDK comes with a bean Container called the beanbox which has its full source code available. It is very educational.
I also used VisualAge for Java/2 which is the first Java development tool I found which was actually on par with today's compilers (and many times better). I highly recommend downloading VisualAge.
Every bean must be serializable: in order to be serializable a class must implement the Serializable interface which has no methods!
The serializable interface is in fact only a tag stating that the object was designed with serialization in mind. A serialized object must have a default constructor and must mark every field it does not wish to save with the word transient.
The ObjectInputStream class and ObjectOutputStream class do all the work of converting the objects to streams. If you wish to have control over the way your object converts to a stream check out the Externalizable interface.
The code in the experiments directory has the following output:
A string representing the start of the file. a = 5 b = 6 c = 0 a = 11 b = 12 c = 0
a is public and c is private, c is transient so it is never saved.
Object serialization is used by developers to save the state of the bean.
John Dvorak called Java applets Crapplets referring to the slow download time of Java applets. To download an applet you need to open several TCP connections and download small but uncompressed class files. JAR came to change all of that. The JAR file format groups both the class files and all the resources into a single file with optional ZIP compression. In order to read from a Jar file we must used the package java.util.zip which contains several classes of interest. In Java reading from a ZIP file is no more complex than from a disk file.
The naming convention
Java beans have a very simple yet powerful naming convention. In fact, one of the biggest changes in JDK's 1.1 AWT was in making the AWT Components consistent with the Java beans naming conventions.
The two most important conventions are:
- properties are created using set* and get* methods.
- events are distributed using the add*Listener and Interface *Listener, which is the standard Java event delegation model.
Java beans allow lots of other interesting tricks such as a changing the behavior of beans during design time, and conventions regarding property changes. These can all be found at the Java beans home page at Sun. Sun will soon release a new Java bean spec codenamed Glasgo which promises some interesting extensions.
The visual developer
As I promised the previous month I made some dramatic improvements and fixes to the visual developer and the FreeFormEdit class. Since I started working from the existing code it will be very hard to document all of my changes so instead I will try to describe the overall changes.
I used the JavaDoc utility to document my code for easier browsing. grinding.zip JavaDoc and source zip file.
- I changed the entire concept of placing objects on the FreeFormEdit. Whenever a Component gets placed on the FreeFormEdit, a ComponentWrapper wraps it with a Panel subclass thus allowing people to resize and move the component without touching it. This is essential for Components which catch mouse events.
- I built in the ability to resize components by programming the logic into the ComponentWrapper.
- I created a global data class which contains the information needed by all the other part of the visual editor.
- I added the ability to load an use Java beans from JAR files.
Things to notice with the new implementation:
- The ComponentWrapper class is a class containing a Component whose interface it wraps with its own. Notice the MARGIN is set to 4 pixels to allow easier grasp of the objects, also notice the events are delivered to both components as if they were one and the same. Transformations are made by the wrapper so classes won't usually need to know that a Component is wrapped.
- In the FreeFormEdit the layout defaults to null layout which will allow components to be placed anywhere and prevent a layout manager from changing the design. The FreeFormEdit is no longer responsible for painting the selection, and the entire responsibility for moving the objects was delegated to the ComponentWrapper, which allows a more dynamic design.
- MacroExtention can now receive a JAR file to search through as well as the usual class loader path. The JAR loading implementation is very basic and contains no caching of the JAR contents, and it searches through the default class loader before getting to the JAR. It could easily be extended to support caching and thus gain significant speed increase.
- The class loader also supports loading resources. Up until now, we used the class loader as a means to load classes in different ways, but the class loader is also responsible for loading the resources used by the classes. This can matter a great deal if the resources are located in a JAR.
- The mouse manager is now simplified and has lost most of its responsibilities to the ComponentWrapper.
Room for improvement
- Being able to save the FreeFormEdit to a Java source file - this can be "easily" accomplished using the Java reflection API which allows us to detect the properties of the class in real time.
- Being able to change properties of Components - this can be accomplished with the same reflection API and should not pose a significant problem for those who know this material. Java beans supports extended configuration which should be simple to implement.
- Attaching code to component events should be simple enough with the reflection API detecting the type of events the object supports.
- I intended to add keyboard support and even placed the keyListener interface but time was not on my side. It should be simple enough to add keyboard support.
This column has been shorter than usual since I did not have time to add some features I wanted to add. Next month I will delve into security and some of the inside guts of the virtual machine.