- Advanced JavaBeans
- 15 -
At this point in the book, you should be well on your way to being a proficient JavaBeans developer and user. You've learned all the conceptual basics and have even built some custom beans from scratch. However, there still are a few issues you haven't covered that are important as you move on to bigger and better JavaBeans things. This chapter addresses some of these advanced issues and gives you some perspective as to why they are important and what they mean in practical terms.
Unfortunately, this chapter isn't presented as a delicately flowing group of related information that ties together in a nice little package. Instead, it is a mixture of a wide range of issues; all they have in common is simply that you haven't learned much about them yet. In other words, this chapter takes a group of advanced JavaBeans issues and presents them to you in the most logical way possible. The goal of this chapter is mainly to tie up loose ends in regard to your knowledge of JavaBeans and address some important fringe issues.
You learn about the following topics in this chapter:
- Invisible beans
- Beans and multithreading
- Internationalized beans
- Beans in a windowing environment
- Inner classes
Security has played a prominent role in the development of the Java programming language and runtime environment. This is primarily because Java has evolved as the programming environment of choice for the Internet, where security risks related to the online transfer of information are of great importance. It only stands to reason that the security issues relating to Java should transfer to JavaBeans, and in fact they do. JavaBeans components are subject to the same security model imposed on Java, which is very consistent with the positioning of JavaBeans as a logical extension of Java. The concerns related to Java security in no way change when it comes to JavaBeans.
More specifically, as far as security goes, beans are treated just like the applets with which they reside. A bean used within the context of an untrusted applet is considered just as untrusted as the applet. In practical terms, this means the bean isn't allowed to read or write files on a client or connect to arbitrary network hosts. To the Java runtime system, a bean that executes within an untrusted applet is no different than any other support class used by the applet. When a bean is associated with a trusted, or signed, applet, however, the whole scenario changes. Trusted applets are given full access to file manipulation and network host connections, just like full-blown Java applications. A bean that resides in a trusted applet or application is therefore given the same freedoms.
A simple rule to remember in terms of beans and security is that beans inherit the same security model as the parent applet or application within which they reside. It's important to note here that although many applets will be digitally signed, and therefore trusted, you should still assume the worst case when you design and develop beans. You should design beans in such a way that they can successfully function in an untrusted environment. In doing so, you are allowing the widest range of use for your beans. Of course, if your bean simply must perform file I/O or some other function that imposes security concerns as part of its core function, this guideline is impossible to meet.
When you are designing a bean, there are some steps you can take to minimize security concerns and allow the bean to perform in the most stringent of security environments. Following is a list of some of the areas in which security plays a role in the design of beans:
- Data transfer
- Menu merging
NOTE: Keep in mind that none of these restrictions apply to beans running as parts of trusted applets or full-blown Java applications, because beans adhere to a relaxed security model in these scenarios.
Recall from Chapter 5, "Introspection: Getting to Know a Bean," that there are two levels of functionality provided in the JavaBeans introspection services: low-level services and high-level services. The high-level services enable access to the publicly exported portions of a bean, and the low-level services are meant to be used primarily by application builder tools to assess the internal workings of a bean using reflection. Because of the access they provide to the internals of a bean, the low-level services raise some serious security concerns. It should come as no big surprise to find out that the low-level services are accessible only in a trusted environment, such as beans being used in an application builder tool. The high-level services, on the other hand, impose no security restrictions and are completely accessible in both trusted and untrusted environments.
Because of the security situation surrounding the introspection services, you should make sure you aren't relying on the low-level services in a bean that you intend to be used in untrusted environments. Instead, you should try to stick with using the high-level services, which are fully accessible across the board. Fortunately, the high-level services provide plenty of bean access for most situations through the publicly exported properties, methods, and events for a bean.
Persistence doesn't seem like an area in which security would come into play in a big way. However, remember that beans are often serialized to and from files, which are extremely suspect when it comes to security. For bean developers, this doesn't mean you can't serialize a bean in an untrusted environment; it just means that you might not be able to have any direct control over the serialization stream itself. It is expected that the parent applet or application for a bean will provide the stream through which the bean is serialized. Depending on the security imposed by the parent applet or application, the bean might or might not be able to access the stream directly. As a bean developer, your safest bet is to peacefully read and write to streams through the standard serialization mechanism and not worry about directly modifying the stream from within your beans.
The Java 1.1 AWT provides support for data transfer operations through extended windowing features such as the cut, copy, and paste clipboard functions. You learn a little more about the functional aspects of these additions to the AWT in the "Beans and Multithreading" section later in this chapter, but for now I want to focus on the security issues surrounding them and JavaBeans. Because clipboard services are based on the transfer of data over execution boundaries, you can't help but worry about the security implications involved.
This affects beans because they are fully capable of participating in clipboard operations and are therefore subject to the same security implications surrounding the operations. In general, clipboard operations aren't restricted by the default Java security model regardless of whether a bean resides in a trusted environment. However, there can be instances in which you will want to control the transfer of information in a clipboard operation, so you always have the option of altering the security model to be more strict in regard to data transfers. When it comes to data transfer, it is ultimately up to you as a developer to impose security restrictions based on the specific needs of the bean or parent applet or application.
In Chapter 16, "The Future of JavaBeans," you will learn about future enhancements planned for the JavaBeans API. One of these enhancements involves the capability of beans to contain menu information that can be merged with the menu of a parent applet or application. Although menus themselves aren't typically considered at risk for security breaches, the capability of a bean to alter the parent applet in such a way is itself a risk to some degree. Understand that this risk exists only when an applet attempts to alter the menu of the containing Web browser. It's perfectly OK for a bean to alter the parent applet's menu, provided the applet doesn't propagate this change on to the containing browser menu. In other words, the browser menu is the one that is at risk in terms of security, so merging an applet menu with a browser menu is the real issue here.
This situation affects beans because they will eventually be able to alter their parent applet's menu in a future version of Java; these alterations can then be indirectly transferred to the browser menu. The simple solution imposed by the standard Java security model is to allow only trusted applets the capability to merge menus with a containing browser. Menu merging can occur between a bean and an applet in any security scenario, but the applet can merge menus with a browser only when it is trusted.
All the beans you built in Part III, "Creating Your Own Beans," are considered graphical beans because they have a graphical representation at runtime. This might seem like a prerequisite for all beans because the most practical application of beans is in user interface controls or as output displays, both of which are graphical in nature. However, it is perfectly acceptable for a bean to have no graphical representation at all. These invisible beans usually take the form of some support library that performs a function behind the scenes. A good example of an invisible bean is a timer bean, which sits in the background and fires timer events at regular intervals. This type of bean would be extremely useful for orchestrating animation frames or any other process that requires a periodic trigger.
NOTE: In Chapter 13, "An Audio Player Bean," you learned how you can modify the audio player bean to act as an invisible bean. Although the task of actually converting the bean to an invisible bean was left as an exercise, you still got an idea about how the bean could be implemented and used invisibly.
Even though invisible beans have no visual representation in an executing applet or application, they have full access to all the services available to other beans, which makes them ideal for performing background functions. These beans have no visual representation at runtime, but they must be visible in some form at design time so that users can edit the properties of them inside an application builder tool. The typical approach is for an invisible bean to display a simple icon in design mode and then become invisible at runtime.
Another motivation for a bean to be invisible is so it can be used to build server applications, which typically aren't graphical. Knowing this, it is possible to design beans that are capable of being conditionally invisible depending on their use. This type of bean would be visible when used in an applet and invisible when used in a nongraphical server application.
JavaBeans components are designed as self-contained units that are accessible only through carefully constructed interfaces, so it's tempting to think that they are above some of the concerns that exist in other Java classes, such as applets. However, you can't lose sight of the fact that beans are really just normal Java classes with the capability to do some extra things such as export properties and support application builders. Therefore, beans are subject to all the same design concerns as Java classes. One of these concerns involves multithreading, which as you probably already know is the capability to enable multiple paths of execution to be taking place at once, potentially through the same piece of code. Multithreading is a fundamental part of Java and must be taken into consideration even with JavaBeans, just as it is for Java applets and applications.
Fortunately, the multithreading concerns relating to JavaBeans are relatively straightforward. Basically, you just have to consider the potential weaknesses a bean might have in regard to synchronization. You must question whether your bean has any code that could be problematic when multiple paths of execution are running through it. Because much of your bean's core functionality will be inherited from existing AWT classes that are highly thread-safe, you might not have to worry too much about how multithreading affects your bean. On the other hand, how you design your bean might mean you need to carefully evaluate how it will perform when it is multithreaded.
As an example, you learned while developing the fancy button bean in Chapter 10 that the event firing mechanism must be synchronized to avoid multithreaded problems. The problem involves the risk of an event listener being removed from the list by another thread while you are still moving through the list. If this situation occurred, you could feasibly end up firing an event to a nonexistent listener, which is a bad thing. Fortunately, a simple synchronization block fixes things and eliminates the risk. Although an in-depth discussion of synchronization problems and solutions is well beyond the scope of this book, I want you to be aware that multithreading and its related complexities must be addressed in JavaBeans.
A new area in Java 1.1 that affects JavaBeans is internationalization, which enables Java applets and applications to be localized to a particular country or cultural region. International localization typically affects the representation of things such as dates, times, time zones, and text names. The internationalization APIs in Java 1.1 are based on Unicode 2.0 character encoding and include the capability to adapt text, numbers, dates, currency, and user-defined objects to any country's conventions.
Internationalization affects JavaBeans components just as it affects Java applets and applications. The burden of supporting localization is placed at the package level, meaning that each package is responsible for internally generating locale-dependent information. In this way, it is a bean developer's responsibility to provide localization information in the package that contains the bean. Before you get too discouraged, however, keep in mind that internationalization is only an issue for beans for which you expect to see a large amount of international use. Because many beans are being used on the Internet, supporting internationalization whenever possible certainly makes sense because the Internet is a worldwide medium. However, the Internet itself isn't very localized, so you must seriously evaluate the use of a bean before jumping into the work required to internationalize it.
Another area in which Java 1.1 has grown a great deal is the AWT, which includes a lot of enhancements and completely new additions. One of the new additions is support for advanced windowing features commonly found in graphical operating systems such as Windows and Macintosh. These windowing features involve data transfer services that are also new to Java 1.1. The data transfer services in Java 1.1 form a widely applicable underlying component of the AWT that opens the door for a lot of new functionality. The end goal of these additions is to bring the AWT up to par with other modern graphical programming environments.
The data transfer mechanism built into the Java 1.1 AWT provides the fundamental mechanism that enables the interchange of structured data among applets, applications, and beans. The significance of this mechanism to JavaBeans is that it provides a means of moving information among beans and other runtime objects in a highly structured fashion. The result is higher-level features such as drag-and-drop and clipboard functions, which support the cutting, copying, and pasting of information among beans, applets, and applications.
NOTE: The drag-and-drop API actually did not ship with Java 1.1 due to development time constraints, but it is expected to materialize in the near future.
As if Java 1.1 hasn't done enough for the cause of JavaBeans as it is, there is yet another topic I want to cover in regard to Java 1.1 and JavaBeans. I'm referring to inner classes, which is a surprising change to the Java language syntax that is largely responsible for making the Java 1.1 (and ultimately JavaBeans) event model possible. Inner classes basically refers to the capability to define a class in any scope. Previous versions of Java supported only top-level classes, which must be package members. Classes that weren't assigned a specific package were made members of a default global package.
New Term:Inner classes refers to a feature in the Java language that enables you to define classes at any scope.
In Java 1.1, this limitation has been lifted so that it is possible to define classes at any scope, including within other classes. You can even define classes within the scope of a block or expression. At first glance, this change might appear to be something done simply to appease the folks who have nothing better to do with their time but argue the fine points of language syntax. However, support for inner classes was added for a very practical reason: the Java 1.1 and JavaBeans event model would have gotten very messy without it because adapter classes, which form a major part of the event handling internals, are much easier to manage using inner classes.
The proof of the importance of inner classes is the simple fact that they required a change to the Java language syntax itself, which was frozen as of Java 1.0. However, because the Java architects were able to add inner classes without affecting any other parts of the language, they decided it was worth doing. Inner classes will go down as one of the least publicized but most critical changes made in Java 1.1, at least as far as JavaBeans is concerned.
NOTE: For more information about inner classes or any of the other enhancements to Java 1.1, refer to the documentation that ships with the JDK 1.1.
This chapter brings some less obvious issues about JavaBeans to the forefront. Although most of these are advanced issues, it's still important for you to have at least a cursory understanding of them because they affect JavaBeans in a variety of ways. The first of these issues is security and how it relates to JavaBeans. Invisible beans are next on the menu, followed by multithreading and how it should be handled by beans. You then finished the chapter by learning about internationalization, windowing environment issues, and inner classes, all of which are additions to Java 1.1 that benefit JavaBeans.
This chapter is admittedly a jumbled group of seemingly misfit information, but there is a common thread: the issues covered are all important to your deep understanding of JavaBeans. Think of this chapter as a smoothing of the edges in terms of your JavaBeans knowledge, because it covers a wide range of topics that relate to concepts you've learned throughout the book. The purpose of presenting these advanced topics near the end of the book is to give you time to become more comfortable with JavaBeans.
Believe it or not, you will come across some of the information you learned today in practical JavaBeans development simply because software development inevitably requires you to dig around under the hood from time to time. Having an idea about some of the advanced issues of JavaBeans will make this process a little less painful. I encourage you to investigate some of these topics on your own, because I really only scratched the surface in this chapter.