Java Tip 50: "On the Parameter Constants pattern" by Jon Steelman
Gosling sets the record straight
To James Gosling,
I have a very earnest question about the Java specification that I believe only you can answer. When you were developing the initial specification for Java, what prompted you to decide not to include enumerated primitive data types? Several recent articles (I notice they're popping up everywhere) describe how to accomplish the same sort of compile-time range-checking, most notably JavaWorld's Java Tip 50.
I've begun a correspondence with Jon Steelman, author of this article, and we agree that all these interesting designs for accomplishing this task could be avoided if enumerated types were available. This isn't necessarily a criticism, but I was wondering if there's a specific reason for this omission. I've been unable to find the answer elsewhere, which is why I came straight to the source.
Thank you for your time and consideration (and for the Java language, of course).
Kyle, Enumerations were left out of the Java spec not because I think they're a bad idea, but because I couldn't converge on a design that made sense. Enumerations means different things to different people. One version of enums is that found in early versions of C, where they were essentially just integers. Very simple, but no type checking. Later versions of C made enums proper types, but the type algebra was pretty simplistic, and the only way to use them involved lots of casting, which breaks type safety (to use enums as array subscripts you have to cast them to
(int)). Pascal has a somewhat more complete type algebra (they're at least type safe), but many of the useful things folks do with C enums are impossible here (having defined mappings to integers for SCSI function codes). Another contingent wanted enums to be abstract qualities from a dynamically extensible set (the enum patterns that use instances of content-free object instances as values). There was more than enough grayness in the area that I decided to put the issue aside for the time being. James Gosling
The hidden power of inner classes
Great article! I've been using the type-safe enums since Java was in beta (a friend and I came up with the idea to get around the fact that Java didn't have enums and found that we actually liked this scheme -- with its compile-time type safety and bounds checking -- better than the traditional enum). So I didn't find the first tip regarding using this method very useful; but I have to admit I didn't think of combining the new inner-class abilities with this method to get an easier-to-reference version.
Scott, I'm glad you found a new application of the power of inner classes. I personally think that inner classes are underutilized, that people unfortunately avoid them or at most use them for event adapters. I appreciate the positive feedback. Check out Java Tip 27 by Philip Bishop for its relevance to your enums. Even better, see the article, "Create enumerated constants in Java" by Eric Armstrong. Was your enum design similar to the one Eric describes here? Jon Steelman
The mysteries of accessibility
I have a question regarding your tip on parameter constants.
The last block of code includes a private constructor with the comment "private constructor for type safety but accessible in both containers: Parameters & Calendar."
How is that private constructor accessible?
If it were a private method in the interface, I understand how it would be accessible in any class that itself implemented the interface. It's not in the interface, however, but in another class; I would think that it wouldn't be accessible from outside that class.
What's the special aspect of nested classes (or interfaces) that renders the constructor accessible from classes that implement the containing interface?
Daniel, The specification for inner classes makes even private members of inner classes accessible to outer classes. Conversely, private members of containers are likewise accessible from the inner classes. The accessibility, therefore, has nothing to do with implementing the interface and everything to do with the containment relationship. Some of the bugs in JDK 1.1.x relate to this issue. In one particular case, the private member is not accessible, but again this is a bug that deviates from the specification. See bug #4051281 on the Java Developer Connection. Generally, these bugs are being fixed for 1.2. I've not found that the code in my sample runs into any of these bugs. Jon Steelman
JavaBeans: "Doing it the Nescafé way with freeze-dried JavaBeans" by Mark Johnson
I loved your article "Do it the 'Nescafé' way -- with freeze-dried JavaBeans," but it should be titled Do it the Taster's Choice way... Taster's Choice is the freeze-dried Nestle coffee, not Nescafé. (Just for your information!)
Our factory in Freehold, NJ, is the only North American producer of Taster's Choice instant coffee, and darn proud of it!
Gregory, I knew the instant I saw this letter that I'd have to come up with some dry comments about it. Though at first I thought it would drive me to drink, I found a solution (though I really had to concentrate). I've been in more hot water about the freeze-dried Java issue than any other, but I haven't been losing any sleep over the roasting I've received. Because testability is one of the benefits of software component technology, perhaps I should have entitled the column Tester's Choice. Mark Johnson
Design Techniques: "What's a method to do?" by Bill Venners
Flexible Java, coming soon to a bookstore near you...
Your Design Techniques articles are great. I'm a student at Ocean County College, and we're using Java as the core language for our classes. Your articles have helped me shrink Java down to a more understandable level. Is your column part of a book that I can purchase?
William, I'm glad you get a lot out of my articles. There is no book as yet, but I am working on one called Flexible Java, in which much of the material from my Design Techniques column in JavaWorld will appear. Bill Venners
Mind those XYZs
I enjoyed your article, but I'm not sure it answers my question. Assume I have an object X contained in object Y contained in object Z. I want to invoke a method on X, but I only have access to Z. I currently have to pull Y out of Z, then pull X out of Y, then make the method call once I have X in hand.
I vaguely remember reading about a post-office pattern that would allow me to send a message for X through Z. I can think of a way to do this via strings and the Reflection package, but it seems kind of crude. Any ideas?
Stephen, Well, it all kind of depends on what X, Y, and Z represent, but in general, I'd say that it would be nice if Z offered a method that does the job you need done (with X), if possible in a way that doesn't really require you to know so much about X or even Y. Let's say the method is
z.getZJobDone(). What would likely happen when you invoke
getZJobDone() is that it would invoke a method on Y (which is part of Z's internal implementation, referenced by an instance variable in Z), say
getYJobDone(). And what
getYJobDone() would do is invoke
getXJobDone() on the reference to an X that Y has in its instance variables. This way, the X, Y, and Z methods offer services, rather than simply offering access to internal data. In addition, this way yields the message passing scheme you were talking about. When you invoke
getZJobDone(), you are passing a message to Z, which then passes its own message to Y by invoking
getYJobDone(), which in turn passes a message to X by invoking
getXJobDone(). But the client of Z just invokes
getZJobDone() and doesn't have to think about Xs and Ys and the details of how
getZJobDone() gets the job done. On the other hand, there will likely be times when you feel clients of an object need access to internal data, and the accepted way to do that in Java is with
set/get methods. Z could have a
getY() method and Y could have a
getX() method. It sounds like this is what you're currently doing. So the answer is that
set/get methods are OK, but first you should try to think about designing X, Y, and Z as bundles of services (their accessible methods are the services), not just as wrappers of data. Bill Venners
Breaking the mold
Nice job! I like your column and it seems clear to me, from the presentation that you used, that you have a design patterns background . That is, you discussed a problem in a context, along with the constraints that drive decision making. The summary was a good way for me to park the information (pattern) in my brain. Thanks again and I look forward to more of your best practices.
Russ, I've found that some things are best described as patterns and others are best described as guidelines. I'm thinking of packaging this material into a book of guidelines along the lines of Effective C++, but with a few "best practice" patterns sprinkled in. I don't know if you've ever seen Kent Beck's Smalltalk Best Practice Patterns, which covers the same type of material for SmallTalk, but in a patterns (not guidelines) mold. It's a great book, but I think it sometimes strains to get guideline pegs to fit into pattern holes. Bill Venners
In your article, you note that coupling doesn't have an analog in the writing domain -- sure it does!
How about a document that's littered with see X, and refer to Y references or links? That document doesn't stand on its own -- it requires the reader, in order to understand one document, to access input from other documents.
Jay, Oops! You're right. In my attempt to be uncohesive, I was also inaccurate. (I think this reply is "coupled" to your comment, because it would make no sense in the absence of your comment. All kinds of coupling in writing.) Bill Venners
Java Tips Q&A with John D. Mitchell
I enjoyed your article on system properties.
One question, though. Your article implied that you can get the environment variables defined in DOS/Windows. Running your program doesn't return any of the environment variables that I have defined, however, in either Windows NT or Windows 95. Do you know of a "pure" way to get these environment variables?
Mike, Glad to be of service! I don't think there was any such implication. The article certainly does compare properties to environment variables, but I don't recall anything that stated that OS environment variables do or do not make it into the system properties list. Perhaps I should have made that clear in the article. Sorry for the confusion. The only way to get the OS system variables is to have them passed in on the command line which starts the Java runtime. This is problematic for applets, but for applications, just wrap the invocation of the Java runtime in a batch/shell script. There are tons of portability problems trying to rely on OS-level environment variables; as a result the system properties have been developed to allow you to get more or less the same information everywhere. John D. Mitchell
Servlet permissions quandary
I am a CIS student at Kansas State University working on a Web site project. I have a question about Java Tip 41.
I need my servlet to write to a file -- the same operation your example code (
PosterServlet) performs. I am getting the error:
unable to open output file. I've had trouble getting permissions set correctly. What exactly do I need to set the permissions to? Also which permissions are these (just permissions for the directory, or is there something in the server configuration)? I have set up my own Apache 1.2.5 server with the servlet patch.
Julie, Different servlet runners have you do things somewhat differently (due to the unspecified nature of some things). The default directory that a servlet opens files in seems to be one of those things. I haven't used Apache, so your best bet is to check out the java.apache.org documentation. For the example
PosterServlet, running under Sun's Java Web Server on a Linux box, the default directory is the root server directory (so the /posters directory is directly under the top), and I've specified 775 (that is,
rwxr-xr-x) permissions -- although that's not particularly tight (or secure!). Other servlet runners may default to the directory from which the servlet's class file was found. Please let me know what you find out. John D. Mitchell
Multiple callbacks in the same class?
Thanks for Java Tip 10, which discusses callbacks in Java. I am struggling with the following problem. How do you set up multiple callbacks in the same class? I'd like to avoid a
switch(...) in the "main" callback (the one defined in the interface, and, at the same time, I'd like to avoid declaring a callback vector in the interface. Any hints?
Andrea, You have the basic idea of how to do callbacks. After that you can pretty much do whatever you like to build more complicated systems. A vector is a good solution, or you can use multiple, anonymous inner classes. Depending on your needs, you could have a single demultiplexer object, which knows how, who, and what to call when the event happens, installed as the callback. You might also want to look at how the various events and listeners are implemented by the AWT. John D. Mitchell
Out of the sandbox?
How can I get an applet to write/read to/from the disk where it is running?
Armin, A standard applet cannot do that. Signed applets can potentially do that, but the state of signed applet support in the various browsers is questionable. You can learn more about applet signing by reading the Applet Signing FAQ, which is floating around in the comp.lang.java.programmer newsgroup. You can also read the various security and signing documentation that is available on Sun's Java Web site. Netscape has it's own "Capability" API for allowing applets to do various levels of things on a local machine. Check out the documentation on Netscape's Developer Web site. John D Mitchell
Java optimization resources
Thanks for compiling the very useful Java Tips in JavaWorld magazine. I especially found Java Tip 26 quite useful. I'm looking for general guidelines on performance tuning/optimization of Java code. Could you please let me know of any resources (or books) where I can find this kind of information?
Nagendra G. Nirnakar
Nagendra, I'm a firm adherent to the notion that premature optimization is the root of all evil. The first (and best) step to make with respect to performance is to learn/find good algorithms and designs for whatever problems you're solving. After that, take the time to learn the way things are done in the language/system that you're using -- in the case of Java, a myriad of books, magazines (like JavaWorld), references, and the like are readily available. Additionally, writing the code for correctness and then profiling your code will help you to see what areas are worth improving. For a more bottom-up point of view, learn about the design and implementation of the Java virtual machine and the bytecode language for it. Dump your class files out and look at the generated bytecode. For something in between the two extremes, check out the various FAQs, and use the search engines on the Net and on the various specific Web sites (like the JavaWorld search engine). There's a fair bit of stuff floating around out there. John D. Mitchell
Passing parameters between applets
We are trying to pass parameters from one applet to an applet located on different Web page (not within different frames, they are totally different Web pages). How can we do this?
Letters to the editor
Java believer says it's time to bury the hatchet with MS
To the editor:
I've been a Microsoft basher for many years -- long before Java arrived on the scene. In the mid '80s I lamented over the OS wars and now I lament over the browser wars.
But recently I find myself burying the hatchet. Why? Certainly not because Microsoft has changed its unethical ways but because for the first time it's about to help advance the state of the art rather than hinder it. I'm talking about Windows 98, DOM, XML, scriptlets, and active desktop. At long last we'll be able to advance GUIs to the next step of true programmability. This is an area that has not seen true innovation since the early '80s.
Our culture is about to embark on the extranet and virtual corporate adventure. The fastest way to make that happen is XML and scripting. Scriptlets (with COM under the covers) does away with the need for CORBA or Java in such applications.
I bet the farm on Java a year and a half ago. I quit my job and became a contributing author to two titles for Java. I've written much freeware for Java including a generic server toolkit including a proxy and Web server. I've worked several contracts with Java and turned off many an IT manager with my zealous advocation of Java.
All I have to say to my fellow Java believers is to conduct this simple exercise: Build an extranet application with strictly Java. Then try it with XML or MS DHTML with data binding. Which is easiest, fastest, cheapest? By the end of this year the power of XML and MS DHTML with scriptlets will be apparent.
The Java community fell in love with Java because it's truly a wonderful, easy, and fun language. The cross-platform dream simply made it all the more wonderful. But consider the fact that Internet Explorer is rapidly becoming the cross-platform browser. Also consider the greater ease of building content-intensive apps with a content language like XML, versus a computative-intensive language like Java, and you may well find yourself falling in love all over again.
Java is here to stay, in embedded systems and dedicated distributed apps, middleware, etc. But Microsoft's vision of Java as a component building language is correct. VJ++ is an attempt to optimize Java for that role, and by so doing Microsoft is taking Java where JavaSoft will never take it -- to the extranet content delivery world. Seen in that light, the 100% Pure Java initiative while being cross-platform-computing inclined misses the most vital concepts of our era: connectedness and the flow of content.
Microsoft can afford to lose the Java zealots because by next year XML's power in the extranet will be starting to be felt in a very strong way. At that point you'll see XML and remote-scriptlet envy.
The world is changing constantly. For once Microsoft is advancing the cause of computer science rather than exploiting the inventions of others. I think it's ironic that the DOJ may negatively affect this advancement, instead of stopping Microsoft years ago when it was destroying Dr. DOS, WordPerfect, Lattice C, Paradox, Lotus, etc.
Riled up over JavaWorld ads and parameters
To the editor:
First, is it really necessary to apply a parameter like ?051198txt to all of your URLs? This is really bad, because many proxy caches do not cache URLs, which include parameters, and I don't like to add the rule/burden of parsing such URLs.
It always takes a long time to download these articles. From my point of view there isn't any need to apply parameters to such URLs, as each article is pretty static. Of course, maybe your intention is to track the access to these articles, but you should take into account that there are other ways to get around this problem.
Second, I don't like all these ads on your pages. It wouldn't be a problem if the ad servers were fast and the download of these images didn't take so long, but they are often very slow. As a result, our university has redirected all ad image downloads to a transparent GIF, located at our site, which speeds up the presentation of your pages.
My suggestion is to organize your Web service to be more cache friendly and remove the ads or put them on your server with a static URL (that is, no parameters).
Jens, First, I assume you are referring to the trackable links in our e-mail alerts. I'm not certain about caching problems they create, but I'm guessing your concern is that they don't match up with the pages you've cached in advance (having stripped out our ads). When you strip out the ads for your readers, you are ensuring that our revenues are dampened, which makes it harder for us to prosper. JavaWorld is supported almost exclusively through advertising; this is our livelihood. In other words, no ads, no magazine. Second, caching everything means we can't track pages, which means we don't know what's going on, which means we are running blind. Not the best way to understand how our readers are responding to our efforts. Third, caching ads means we can't report on ad traffic, which means we don't get paid, which means we go out of business -- not our preferred outcome. Ideally, we'd be able to serve ads and pages without disturbing caching, which would be best for everyone -- we'd be able to track things, readers would get pages served faster. It's a less than ideal world, however. We are switching to a new ad serving service in the summer; they claim they are able to track ads served without clearing cache. If it works in practice, it will be a big help to all concerned. In the end, Jens, I can only work with what I've got; this business is in a technically early and primitive stage. Michael McCarthy
Web Publishing Inc.