To save content items to your account,
please confirm that you agree to abide by our usage policies.
If this is the first time you use this feature, you will be asked to authorise Cambridge Core to connect with your account.
Find out more about saving content to .
To save content items to your Kindle, first ensure no-reply@cambridge.org
is added to your Approved Personal Document E-mail List under your Personal Document Settings
on the Manage Your Content and Devices page of your Amazon account. Then enter the ‘name’ part
of your Kindle email address below.
Find out more about saving to your Kindle.
Note you can select to save to either the @free.kindle.com or @kindle.com variations.
‘@free.kindle.com’ emails are free but can only be saved to your device when it is connected to wi-fi.
‘@kindle.com’ emails can be delivered even when you are not connected to wi-fi, but note that service fees apply.
Multithreaded programming has been with us for many years and is considered to be a feature that many robust applications utilize. Exception handling is another feature of many languages considered to be necessary for proper and complete error handling. Each of these technologies stands very well on their own. In fact, you cannot pick up a book about Java programming without finding a chapter devoted to each of these topics. Many of these books do a good job defining and describing how to use them properly in your programs. What is missing is the information on how to use these two technologies together effectively. After all, how effective is writing a multithreaded Java program if it is incapable of properly handling exceptions occurring on secondary threads? We will present a solution for effectively dealing with this problem.
To solve this problem, we introduce two new classes and two new interfaces to be used when writing multithreaded Java programs. These classes are small, easy to use and understand, and effectively enable you to handle exceptions occurring on secondary threads.
Writing robust code implies many things. One of them is the proper and effective way in which your program deals with error situations. The approach you take can vary from doing nothing to handling any and all problems. The approach you choose is more than likely dictated by the type of application you are writing.
This is the second of a two-part series on thread separation. The first, published in Java Report's August 1998 issue, dealt with general issues and techniques for addressing them. This installment describes a simple framework to thread-separate servers from the clients that call them. This thread separation is useful if the request being served is a lengthy one, such as to retrieve an image from a large image database. The client may go on doing other things and be called back by the server when the requested task is complete. Thread separation of servers is also useful when (e.g., in a Web server), you have chosen a thread-pooling solution to limit the number of concurrent threads running in your server. All client requests are transferred to one or more controlled server threads for execution. Finally, thread separation is useful when you take advantage of the “liveness” rationale for threading, in effect, making tasks in a system “live,” because it allows them better to embody the behaviors of their real-world counterparts. Thread separation allows different components to each live and run within their own thread or threads, with control and notification between components being as brief and shallow as the designer desires.
PROBLEM DOMAIN
I recently worked on a heavyweight component model that simplified the creation of system servers. Most of the top-level components in our system were built on this model and most of these components had presentation objects that commanded them based on user actions.
Moving to a new language involves some paradigm shifts in how you think about structuring programs and solving problems. Often we think in terms of solutions instead of problems and so ask questions like, “How do I pass a method pointer Java?” instead of “How do I encapsulate a behavior reference in Java?” This is particularly important for C++ programmers migrating to Java, because the similarity in syntax between the languages can lead to the assumption that the language paradigm is identical.
I'll discuss two classes of problems faced by developers. The first is what I call “Conceptual Confusion,” where a user of one language carries their assumptions to another language and then gets confused when their assumptions are invalid. The second class is the desire for new features to be added to the language. This “Creeping Featurism” generally involves adding complexity to the language for the sake of mimicking another language's feature, often no more than syntactic sugar. That is, the proposed feature may reduce the typing without adding to the power of the language.
Let me warn you of my bias: I find that too many features in a language confuse me. I find that a simple language based on a single paradigm provides for less confusion, better maintainability, and quicker code development. You may understand that neat “constant reference” feature, but think of the person who may have to fix, reuse, or extend your code a year from now.
Permutations and combinations appear in problems that have more than one answer, where we want to know what all the possibilities are or just how many possibilities there are. For example, a basketball coach may need to select a team of 5 players from the 10 boys on his squad. How many possible teams is that? Is it more than we can reasonably put in a list? If the coach has statistics on the five starting players from a competing team, can he match up his players with them based on height, speed, and experience? You can address these questions with a handful of algorithms for permutations and combinations that are an important part of a Java developer's toolbox.
COUNTING PERMUTATIONS
A permutation is an ordering of items. For example, we might have three errands to do, with a choice about what order to do them in. If we have to buy groceries, mail a package, and get an oil change, one possible ordering or permutation is {groceries, mail, oil}. Altogether, there are six possible orderings:
groceries, mail, oil
groceries, oil, mail
mail, groceries, oil
mail, oil, groceries
oil, groceries, mail
oil, mail, groceries
We can count these choices algorithmically, without necessarily listing them. Notice that once the errand runner completes one of the three errands, there are always two left. After the errand runner completes two errands, there is always one left.
In our complex world, events are constantly occurring. Any one person is only interested in a very small subset of all these events, so humans have worked out ways of getting just the information of interest, which works to a degree. We may periodically check to see if the event has occurred, or we ask someone to notify us when the event occurs. Often there is more than one source of a particular type of event such as disaster-related events, but we do not typically care about who notifies us, just that the event has occurred. Ideally, we would subscribe to just those types of events in which we are interested and be notified of them when they occur.
Event notification is a useful communication paradigm in computing systems as in real life. This article documents general event notification in the form of a design pattern, which provides a useful way of exposing readers to the important concepts and issues involved in event notification, and provides a language-neutral pattern for implementing event notification in a variety of scenarios. Concurrently, we discuss design issues using examples as appropriate to demonstrate effective use of event notification. Diagrams use the Unified Modeling Notation (UML) (see Unified Modeling Language User Guide, Booch, G. et al., Addison-Wesley, 1997).
After my last article for Java Report (“Tapping the Power of JavaScript,” March 1997), I received a question from a reader asking if there was some way for a Java applet to call a JavaScript function. I knew that JavaScript could call Java funtions, but I wasn't sure if things would work the other way around. So, it was off to the Internet to investigate! I wound up at Netscape's official JavaScript documentation site and here's what I found.…
THE BASICS
First, let's answer the question that started all this: Yes—Java methods can call JavaScript code, and JavaScript code can call Java methods. However, as you might expect, there are some exceptions and restrictions, and those depend on which browser you are using (we'll discuss these a bit later on).
The second question you might have is: “Why on earth would you want to do this?” Well, contrary to popular belief, JavaScript isn't just “Java lite,” it's a powerful and useful language in its own right. However, because it's intended to execute inside a Web browser, it does have a few things missing from it. For example, in JavaScript, you have no way to play a sound or access a database. Java has both of these capabilities, and by making them available to JavaScript, we greatly enhance the types of tasks it can perform.
For those who are just joining us, welcome! We are exploring common and useful object-oriented analysis and design modeling activities that ultimately lead to the creation of a system implemented in Java.
By definition, because analysis focuses on investigation of the problem space, the analysis models do not directly relate to Java. However, as we move on to design, we will explore more Java-related issues that impact the design of the architecture and software classes. When diagrams are used, we illustrate them in the Unified Modeling Language (UML) notation. However, this is not a column about the UML (which is “simply” a useful, standard diagramming notation—no small feat), rather it is a column about skills and heuristics in analysis and design, which is a more critical concern than notation. My usual disclaimer applies: modeling and diagramming should practically aid the development of “better” software—better in meeting the desires of the client or in being easier to change and extend. If it doesn't, question its value.
In our last column on conceptual (or domain object) models (see “The Conceptual Model—What's the Object?,” Java Report, Vol. 3, No. 10) we focused on the fundamentals of this classic object-oriented analysis model: identifying concepts, attributes, and associations. It is not a picture of software components or classes; it is an analysis-oriented set of diagrams that depict abstractions of things of interest in the problem domain.
Text searching and sorting is one of the most well researched areas in computer science. It is covered in an introductory algorithms course in nearly every engineering school, and there are entire books devoted to the subject. Why then, you might ask, is it necessary to publish yet another article about searching?
The answer is that most of the well-known, efficient search algorithms don't work very well in Unicode, which includes the char type in Java. Algorithms such as Knuth–Morris–Pratt and Boyer–Moore utilize tables that tell them what to do when a particular character is seen in the text being searched. That's fine for a traditional character set such as ASCII or ISO Latin-1 where there are only 128 or 256 possible characters.
Java, however, uses Unicode as its character set. In Unicode, there are 65,535 distinct characters that cover all modern languages of the world, including ideographic languages such as Chinese. In general, this is good; it makes the task of developing global applications a great deal easier. However, algorithms like Boyer–Moore that rely on an array indexed by character codes are very wasteful of memory and take a long time to initialize in this environment.
And it gets worse. Sorting and searching non-English text presents a number of challenges that many English speakers are not even aware of. The primary source of difficulty is accents, which have very different meanings in different languages, and sometimes even within the same language:
Many accented letters, such as “é” in “cafe”, are treated as minor variants on the letter that is accented, in this case “e”.
Aprimary design goal of Java is to enable developers to write software that can be deployed easily across a variety of world markets—these markets use very different languages and writing systems. To be acceptable in these markets, you must be able to present text in a way that conforms to the rules of their writing systems.
Displaying English text correctly is relatively simple—though not quite as simple as you may think! Other writing systems, particularly Arabic and Hebrew, are much more complex than English, requiring reshaping and reordering of text for acceptable display. Moreover, in a Graphical User Interface (GUI) you need to measure text properly; and if you are editing text, you also have to hittest it to find out what the mouse is selecting, highlight the text to show the selection, break the text into pieces that fit onto a line, and so on.
Fortunately, in the Java Development Kit (JDK) version 1.2, the new TextLayout class and its supporting classes can perform these functions for you, even if the text has multiple styles and contains characters from a mixture of different writing systems (including Arabic and Hebrew). We discuss several problems posed by these writing systems, and then describe how you can use the new TextLayout classes to handle these problems easily and efficiently.
Even if you write English-only software, you will find that using TextLayout is more convenient than writing your own utility for displaying and measuring text.
The Internet has fostered rapid growth in the use of application servers. Previously inaccessible outside private Intranets, application servers are increasingly appearing as the middle layer of three-tiered network applications. A GUI executing on a desktop establishes a session with an application server that implements product features on top of a third tier of legacy systems or databases. Supported by growing customer access to the Internet, the application server allows a business to rapidly deploy information products, and services. Java catalyzes the process by speeding the development of both the GUI and server software as well as making the GUI platform-independent.
Application server development is a complex undertaking. Supporting simultaneous GUI connections, application servers must protect the integrity of system data from malicious clients and the privacy of clients from each other. Traditionally this has been accomplished by guarding sensitive data with access control checks. Associated with each protected object, an access control list (ACL) names authorized principals and permitted operations. The server checks the ACL before taking potentially damaging actions. Although this is called an access list approach, its essential characteristic is not the use of a list, but the checking of permissions after granting a reference to the protected object. In this approach, the reference does not imply a right to use the protected object.
Described here is an alternative way of protecting objects based on a capability approach.
There is A widespread myth that computers, being fast adding machines, do math well. We all know that this is not true but sometimes we believe anyway. Sometimes we forget that the numeric answers we get have high precision but perhaps no accuracy. I know that I should do the error analysis on each and every floating point operation but sometimes I don't.
I have always believed in “consumer arithmetic.” (i.e., I don't care how fast I get the wrong answer. I care how fast I get the right answer.) And I really believe that programming language libraries should support math at least as good as high school algebra. When I get a numeric problem, I want the computer to tell me it can get the answer, it can get close, or it can't solve the problem to the accuracy I want given the data I have. What I don't want is a string of digits, which may or may not have any meaning, with no indication if they have meaning or not.
I will explore one small corner of the universe and how math happens in the Java language. I use a specific example from a talk I heard on Interval Arithmetic—more on that later. I'll warn you now that I consider myself a user of numbers rather than a mathematician, but we'll definitely do some math along the way.
Last month, Tim Matthews described how JavaSoft is developing a Java Cryptography Architecture (JCA) and extensions (Java Cryptography Extensions, or JCE). He described their contents and structure in the java.security package, and outlined their uses. This month I will present some actual code using the base functionality in the JCA, and next month will program using the JCE and use multiple Providers.
After reading this article, you will, I trust, be able to write a program in Java (an application or applet) that can sign or verify data using DSA with the security package. Beyond the specific DSA example presented here, though, I hope you will understand the JCA model enough to be able to quickly write code for any operation in the package.
Before beginning, however, it is important to note that the java.security package is not part of the JDK 1.0.2, only JDK 1.1 and above. Furthermore, there are significant differences between the security packages in JDK 1.1 and 1.2. This article (and next month's) describes features in 1.2. If you have not yet left 1.0.2 behind, now would be a good time to do so. After all, with 1.2, you are not only getting the security package, you are also getting improved cloning, serialization and many other features.
Now let's look at what a Java program needs to do to use the JCA. Most everything in cryptography begins with the random number generator.
You have probably heard or read something about software agents; they have been a hot topic for some time now and agent-based commercial products are available. There are several schools of thought on what the term “agent” really means. For example, in the context of artificial intelligence, an agent is often described as an autonomous, intelligent entity: They can make decisions and perform actions based on perceived inputs in order to achieve some goal (Russell, S., and P. Norvig, Artificial Intelligence: A Modern Approach, 1995).
Mobility is a common characteristic of many agent definitions. A mobileagent is an active object that can move both data and functionality (code) to multiple places within a distributed system. It doesn't matter what the ultimate purpose of the agent is or whether or not it can be classified as “intelligent.”
A mobile agent should be able to execute on any machine within a network, regardless of the processor type or operating system. In addition, the agent code should not have to be installed on every machine that the agent could potentially visit; it should move with the agent's data automatically. Therefore, it is desirable to implement agents on top of a mobile code system, such as Java virtual machine (VM). The dynamic nature of Java classes and objects, combined with advanced networking capabilities, makes Java highly qualified for use as a mobile agent platform.