|
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
General Java Persistent User Interface for Multiuser Applications
Persistent User Interface for Multiuser Applications
By: Andrei Cioroianu
Aug. 1, 1998 12:00 AM
I'm starting my computer. I'm waiting for the operating system to be loaded. Now I can see the icons of my favorite applications. They're aligned on my desktop and in the same positions I left them. I'm launching a development tool. It's creating its own windows and loading the toolbars I need. I select a project I want to work on from the list of those I used most recently. Everything is the same as it was when I closed this project. What is hiding behind this mechanism? Lots of code that saves the coordinates of the windows, the position of the cursor in each window, the position of the visible text, the position of the selected text and many other parameters that determine the current state of the application's user interface. Each project has several files in which it keeps all this data. The application has its own config files. The programmers who made the tool worked very hard, and the persistence of the interface between two consecutive sessions is timesaving for users. Now I'm launching one of my applications written in Java. Its window is placed somewhere on-screen at random coordinates or in the upper-left corner. This phenomenon doesn't appear at the Java applications that use property files, in which they keep the coordinates and dimensions of the windows. If the user interface is complex, however, then the property files become inadequate. You might be willing to spend money and time to write the code for reading and writing files in an application-specific format, but maintaining that code will be a real pain. Each change of the file format will require modifications in the source code in at least two places (the read and write routine). Is there a simpler solution? Yes. You can use object serialization.Suppose you need an application that allows each user to connect to a network, depending on his/her position(s) in the company: manager, designer or developer (Figure 1). The users won't want to redefine their profile each time they run the application, so the profile should be serialized. So as not to grow the line count of the source code more than necessary, I won't introduce options for colors or fonts. For a real-world application, these options might be compulsory. A user who has a few complex profiles might want to identify them rapidly according to the background color of the application (which becomes the parameter of the profile). Using the simple application described in this article, the user will be able to differentiate the profiles, depending on the on-screen position of the application's window. For a heterogeneous network you will choose Java. But the cross-platform support isn't the only advantage Java provides. Even if all users have the same operating system, they will still have displays with different resolutions, so fonts and controls will have different sizes. Few frameworks offer the flexibility of the Layout Managers from AWT. Sometimes you'll hear criticism that the AWT-based interfaces should be tested on all target platforms. It's impossible to write applications whose interfaces fit, on the first try, in all user preferences. However, an AWT dialog box can be resized, and all the UI components will be automatically reshaped. Users can resize the windows so the fonts and controls of their platform are correctly shown, instead of using font sizes that are established when the application is written. It remains only to serialize the dimensions of the windows so they don't have to start all over again each time they launch the application. It's unfair to criticize AWT, which has, in addition, a multithreading architecture. Since most native applications use dialog boxes that are modals with fixed dimensions, the code of these applications either isn't reentrant or is running in a single thread. If you're still undecided about using Java, I'll give you one more reason. The Object Serialization API provided by Java is easy to use, flexible and scalable. You won't find something like this in other popular programming languages, such as C++, which produces native code, because the Serialization API is based on Reflection API. The latter provides information at runtime, which in the case of C++ native applications is available only at compile-time. I must say that MFC of Visual C++ provides some support for serialization, but the developers have to replace lots of TODOs with their own code. Unlike MFC, Java handles many issues automatically with the help of the reflection API. Sometimes, being interpreted means being superior.
The SmartLogin Application
public static final String OK = "OK"; The constructor of the SmartLogin class (Listing 1) receives as parameter a string taken from the command line, which represents the name of the user's profile. A reference to this string will be stored in the profile member variable. The constructor sets the title, size and the LayoutManager of the window. The last one is GridLayout(6,1). In the first two lines it inserts a label -- "Name:"- and a TextField -- tName - in which the users will type their name. In the third line are the three Checkboxes that define the user's profile, cMan, cDes and cDev. The next two lines contain a label -"Password:"- and a TextField -- tPassw -- in which users will type the password. The last line groups two buttons -- bOk, and bCancel. The events which are fired when the buttons are pushed or the window is closed when intercepted by a SmartAdapter instance. The SmartAdapter class (Listing 2) extends java.awt.event.WindowAdapter and implements java.awt.event.ActionListener, java.io.Serializable. The SmartLogin() constructor receives as parameter an instance, sd, of the SmartLogin class. The actionPerformed() method implements the method with the same name of the ActionListener interface. This method is called when one of the buttons is pushed. For the Ok button it calls the login() and serialize() methods of the SmartLogin instance. The windowClosing() method overrides the method with the same name of the WindowAdapter class. This method is called when the user closes the application's window. The Serializable interface has no methods. However, the SmartAdapter must "implement" it for it to be serializable. The SmartLogin class needn't implement Serializable, because one of its ancestors (java.awt.Component) implements it. The login() method of the SmartLogin class simulates a login. It shows a message like the following one:
Hello Andrei The serialize() method first calls clearPassw() and then tries to serialize the user interface of the application. The clearPassw() method clears the password stored in a private variable of a TextField instance.
public void clearPassw() { After it calls clearPassw(), the serialize() method uses writeObject() of the java.io.ObjectOutputStream class to serialize the SmartLogin object, which represents the application's window. The writeObject() method is applied recursively on the member variables of the object passed as parameter and takes care not to serialize the same object twice. The OK and profile variables aren't serialized because one of them is static and the other one is transient.
FileOutputStream out = new FileOutputStream(profile The main() method of the SmartLogin class first tries to deserialize the user interface. For this purpose the readObject() method of the java.io.ObjectInputStream class is used. If the deserialization succeeds, then the setProfile() method of the SmartLogin class is called to initialize the profile member variable, which wasn't serialized because it's transient. The show() method, which SmartLogin inherits from Frame, will show the window of the application.
FileInputStream in = new FileInputStream(profile If the deserialization fails, then an exception is thrown. This is caught and shown at console only if its type isn't FileNotFoundException (the profile files may not exist if they haven't been created or have been deleted). A new instance of the SmartLogin class is created and the application's window is shown.
sl = new SmartLogin(profile); See Reference 2 for more information about object serialization.
Control What Is Serialized You probably noticed that I used the transient keyword when I declared the profile member variable. Hence, this variable is ignored by the serialization mechanism because the name of the profile can't be part of the file without generating worry about whether an inconsistency will be determined. Nevertheless, this operation shouldn't be made when the SmartLogin application is running. When the user interface is deserialized, the profile variable is initialized with a default value. It's the programmer's responsibility to give it a correct value. This is the reason I called the setProfile() method. Storing constants in the serialization stream is futile. Therefore, I declared the OK variable with the static keyword. As usual, the constants of a class and other variables that need large amounts of memory (as precomputed tables) are declared static, to be shared between the instances of the class. Note that the static variables are ignored at serialization and mustn't be initialized in constructors because these aren't called at deserialization. There is one more source of information, the password. For security reasons it must not be serialized. SmartLogin uses a TextField component to obtain the password. However, this component must be serialized because it's part of the user interface. The solution is to call the setText() method of the tPassw object to replace the password with an empty string. This operation is made by clearPassw(), which is called whether or not the user interface is serialized. The garbage collector is invoked as a supplementary cautious measure. This should be enough, but you can never be sure. If you don't want a variable to be serialized, then you declare it static or transient. You might wonder how additional information could be stored in serialization streams. You can add write/readObject() methods to your serializable classes. These methods will be called by the write/readObject() methods of the ObjectOutput/InputStream classes, instead of the default serialization mechanism, which is still available via defaultWrite/ReadObject(). If this solution isn't sufficient, then you can implement the java.io.Externalizable interface instead of java.io.Serializable. The externalizable classes have total control of what is serialized. They also control the format of the serialized data. See "Object Serialization Specification" (Reference 2) for details. Sometimes, you need to serialize information to which only authorized persons should have access. The easiest solution is to put filters between FileOutput/InputStream and ObjectOutput/InputStream. These filters should encrypt/decrypt the information, which you can store on disk or send over the network after encryption. However, the encryption algorithm should be chosen carefully because the format of the serialization stream is public. A safer solution is to combine encryption with the use of externalizable interface.
Be Sure Your Application Is Closing
What Are the Advantages? From the programmer's point of view, object serialization is easy to use. You don't need to read "Object Serialization Specification" or have work experience with files in Java (this might be a common case because many Java programmers develop only applets, in which the use of streams is restricted for security reasons). But more importantly there is no supplementary cost for code maintenance.
Possible Inconveniences The SmartLogin application isn't perfect. A few users might try to log on with the same profile at the same time. If they modify the profile, the changes will be overridden on disk. This problem should be solved by the login() method, which should be able to detect the possible conflicts. The problem isn't relevant for this article.
Back to My Computer...
References: Reader Feedback: Page 1 of 1
Latest Cloud Developer Stories
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week
Breaking Cloud Computing News
|
|||||||||||||||||||||||||||||||||||||||||||||||||