Letters to the Editor (2/20/99)

Mark Johnson responds to questions about his "XML JavaBeans, Part 1," article; a reader expresses a positive opinion about the version-number feature of 1.2 compilers and VMs; Bill Day helps a reader use Java 3D to move a "camera" view; and Geoff Friesen explains how to write an application based on the Telugu language, used in parts of India.

Cover Story: "XML JavaBeans, Part 1" by Mark Johnson

Read

Reader has trouble compiling Mark Johnson's SMLBeanReader.java file

Mark,

I like your "XML JavaBeans, Part1," article. I wonder how I can run your source code. I tried to compile your XMLBeanReader.java, it didn't go through. The reason, I didn't have the package of TestBean1 that you imported in the code.

Yong

Yong, Try downloading the jar file in the Resources section of the article, then put it in your CLASSPATH and run the XMLBeanReader from the jar. You can also remove the "import TestBean1" line from the java file and compile that way. Remember that you need to download and install IBM's "xml4j" package in order for this example to work properly. Mark

IBM changes the APIs in xml4j; Javaworld's Mark Johnson responds

Mark,

First let me say that was an excellent article [XML JavaBeans, Part 1]. I put the parts together using the links specified at the bottom of the article. I went to the alphaWorks link to xml4j from IBM (dated 2/9/99). I then downloaded your source for the article. But when I try to compile, I get several errors:

  1. At the NodeList nl = e.getChildNodes(); the getChildNodes() returns NodeIterator instead of NodeList. The error: "incompatible types; found: org.w3c.dom.NodeIterator, required: org.w3c.dom.NodeList." This error occurs several times.

  2. I also get "method getNodeName() not found in interface org.w3c.dom.Element." This error also occurs several times.

I checked the xml4j.jar and saw the org.w3c.dom classes. I even downloaded java-binding.zip from W3C and used that for the references to org.w3c.dom.

Mike Hulse

Mike, IBM must have changed the APIs in xml4j -- you'll notice that your version of the xml4j jar file is newer than the publication date of the article. I'll get the new jar file and fix the code to work with the new interface. Part II of that article comes out next week, by the way. I'll have to make sure the code for Part II runs with the new xml4j, as well. Thanks for the heads-up! Mark

Java Toolbox: "Programming Java threads in the real world, Part 5" by Allen Holub

Read

Reader responds to Allen Holub's dislike of the new version-number feature of 1.2 compilers and VMs

Allen,

In your article "Programming Java threads in the real world, Part 5" you complain, with some passion, that the new version-number feature offered by 1.2 (Java 2 platform) compilers and VMs somehow destroys the run-anywhere concept.

I'm surprised you take this view. I can write code using 1.2 features, and I don't expect it to run under older distributions. If I did try to run it, the class probably would get half loaded and/or executed and then return an exception (class, or maybe method, not found). Surely having the option to mark a class as "unable to run without 1.2 VM support" is a benefit since I can, if I choose, avoid all the tedious failed load and/or execute attempts.

You say "Since you have absolutely no control over which version of the VM is on the client platform, using this switch effectively throws away any hope of platform independence." But surely that's the point. If (and it isn't always the case -- consider intranet environments) I genuinely have no control over the environment on the client, then I must not write 1.2-dependent code. In addition, I must avoid setting the "1.2 only" flag. But I've lost nothing.

I firmly believe that the Java applet writing community is fully aware of the issues of "new versions." Many, if not most, applets are still written to the 1.0.2 feature set for precisely this reason. Most developers, I believe, will recognize and appreciate a simple feature that allows us to make it clear if a piece of code is dependent on a particular revision level.

Simon Roberts

Simon, You have made several points here that need to be addressed. Your comments show me, however, that you don't really understand the Java architecture. You're not alone, here, I might add. Many of the letters I received brought up the same issues as yours. I intend to address this matter in my next column, but for the interim, here's my response to the points that you (and others) have brought up:

I can write code using 1.2 features, and I don't expect it to run under older distributions.

Why not? That's the way Java is supposed to work. What if you had to install a new VM every time you made a change to a package that you (rather than Sun) wrote? I suspect you have confused the language version with the VM version. The VM shipped with Java 2 supports class file versions 45.3 and 46.0; the VM for Java versions 1.0 and 1.1 supported 45.3 only. (This version number is really the version number associated with the class-file format -- it's not tied to a specific VM implementation.) Don't confuse the compiler version with the class-file version. All previous versions of the compiler generated output that complied with the same class-file version. A new version of Java doesn't mandate a VM change any more than a new version of your word processor would mandate an upgrade of your operating system. Also, do not confuse the Java packages with the JVM. Swing, for example, ran and runs just fine with a 1.1 JDK and the 45.3 VM. If you install the class files that comprise the new Java 2 packages (such as Swing) onto your CLASSPATH, you'll find that your "Java 2" application will run just fine using a 1.1 VM. That's the way it should be -- that's my point: A 1.2 application will run just fine with a 1.1 VM, but only if you don't use the new command-line switch. In fact, the compiler's default behavior generates a 1.1-compatible class file; this code will run just fine with every VM in the world (there were no changes to the class-file definition between versions 1.0 and 1.1 of Java, despite changes to the language). Inner classes, for example, are implemented in such a way that VM-level changes are not necessary. Moreover, there is absolutely no guarantee that javax packages such as Swing will be available, even if your user has installed the new 46.0 VM. That is, even if you use your switch to generate a non-compliant class file, you still have no guarantee that your program with 1.2 features will run because there's no requirement that the javax packages be installed.

If I did try to run it, the class probably would get half loaded and/or executed and then return an exception (class, or maybe method, not found). Surely having the option to mark a class as "unable to run without 1.2 VM support" is a benefit since I can, if I choose, avoid all the tedious failed load and/or execute attempts.

It seems to me that you may not actually have tried this. The existing VM spec mandates (and the VM implementation follows the spec) that the error message, "Class not found," generated by finding a version 1.2 class file is identical to that generated by not finding the class in the class path. Put simply, there is no way for either a user or the program itself to distinguish between an exception thrown because of a class-file incompatibility and an exception thrown because you did not install the 1.2 class files onto your class path. In other words, the behavior is identical to a "tedious failed load." (This behavior may change when the new VM spec is released, however.) By the way, you can get the class-file versions supported by the run-time environment by using an undocumented system property. However, this information does not guarantee that any of the packages are installed. Your implication that using the new flag will give you a more reasonable error message doesn't hold water either. Most programmers have lost track of the fact that to the average user, all of the exception-related error messages are equally incomprehensible. If programs written in Java can be used only by programmers, then we're really hosed. The only way to output a comprehensible error message is to catch the exception and print something that a non-programmer can understand. I shudder to think what UIs will be like if programs are allowed to print the messages generated by the VM itself when it throws exceptions.

I firmly believe that the Java applet writing community is fully aware of the issues of "new versions." Many, if not most, applets are still written to the 1.0.2 feature set for precisely this reason.

Yes indeed. Now we are moving exactly those problems into the realm of applications. That is precisely my point. We don't want to have the same VM-related incompatibility problems in the application world that now exist in the applet world. The versioning problem with applets is caused precisely because the VMs in the browsers do not conform to the 45.3 class-file spec. The fact that you couldn't run a Swing applet under Netscape is a bug in the Windows/Netscape VM, which doesn't search the CLASSPATH. If it did search the CLASSPATH, it would be able to run a Swing application just fine. (The Unix version of Netscape doesn't have this problem, by the way.)

Most developers, I believe, will recognize and appreciate a simple feature that allows us to make it clear if a piece of code is dependent on a particular revision level.

Again, the new version switch simply does not do this for the reasons that I've stated earlier. Allen Holub

"Start customizing Swing's editor pane -- patch the Swing HTMLEditorKit" by Marc Loy

Read

Possible solution to reader's unknown-extension problem

Marc,

Enjoyed your informative "Start customizing Swing's editor pane -- patch the Swing HTMLEditorKit," article.

However, one thing I noticed: like all HTML viewer examples I've seen, a link to a file with an unknown extension causes a null pointer exception. It seems that there should be a way to force a default text editor for such cases.

John McCoy

John, Glad you enjoyed the article. And yes, I agree that the handling of unknown extension types is less than useful. While I have not tried this specifically (yet!), you should be able to register a DefaultEditorKit (with a PlainDocument) for the mime type "*/*". In theory, that would pop up the text editor for the incoming file. As I said, I have not had a chance to try that out yet. I'll be playing with some of this stuff in the very near future (I'm writing the HTMLEditorKit chapter for O'Reilly), so I'd be happy to keep you informed. By the same token, if you find yourself trying this out, I would definitely like to hear about your successes or difficulties. Marc

News: "Update on Java development on and for the Mac" by Daniel Steinberg

Read

Reader asks about the Apple MRJ kit

Daniel,

I'm surprised that you didn't mention my favorite Mac Java IDE. Okay, I haven't used it much, but the Apple MRJ kit, used with an appropriate editor (there's one around that parses Java code nicely), is a cheap and convenient IDE.

Michael Bayme

Michael, You can use the Apple MRJ kit with an appropriate editor. Many people do and it works quite well. However, it is not an IDE. An IDE is an integrated development environment. What you are describing is a "DE" but not an IDE. In fact, in past articles I have mentioned that the Apple team provides their tools as a service, but they recommend CodeWarrior or Visual Café. Daniel

Media Programming: "3D graphics programming in Java: Part 2, Advanced Java 3D" by Bill Day

Read

Java 3D problems; solutions

Bill,

I try to use the examples in your Java 3D archive, but I am unable to run them. I always get the message: "Exception in thread "main" java.lang.NoClassDefFoungError javax/media/j3d/."

The applet codes in Sun's demos run without any problems, but not the applications.

Have you any idea what could be wrong?

Juergen Pankrath

Juergen, You must explicitly include the archive jar file in your classpath. For instance, to run Example01 from the Java 3D columns, you would use the following command line: java -classpath media.jar com.javaworld.media.j3d.Example01. (Assuming you were in the directory that contains media.jar when you execute this command.) If this still does not work, then I will need more information. To help me diagnose your problem, could you verify:

  1. From where do you get the code (JavaWorld, Gamasutra, my Web site)?
  2. What your OS (Win32 or Solaris), Java runtime/JDK, Java 3D, and OpenGL are? Instructions for discovering your Java version are included at: http://www.billday.com/Work/mediafaq.txt. (Search for "Please begin by verifying your version.")
  3. If you have CLASSPATH set, what is it set to? On Win32, open a shell (DOS is fine) and type: printenv

Assuming you have Java 2 (final release), Java 3D 1.1 (final release), and OpenGL 1.1 all installed correctly, you should not have to set CLASSPATH. However, I wonder if you have it set and this causes your problems. Bill Day

Use the ViewPlatform to move the "camera" in Java 3D

Bill,

I am a student from Singapore in need of sample code on how to use Java 3D to make camera animation possible. My task: rotate my camera so I can view an object, such as a cube, from its front, side, and back views. Presently, I can rotate my camera but can see only the front view of the object.

I do not have the slightest idea how can I move my camera to the back of the cube.

Linhua

Linhua, Java 3D does not have a "camera" per se, but you can move the ViewPlatform, which moves your view into the world (and thus, appears to move the camera). More information on this distinction is available from: http://java.sun.com/products/java-media/mail-archive/3D/0530.html This Java 3d-interest mailing list also contains information on how you can move the ViewPlatform in your code. An in-depth discussion is available from my columns (search for "ViewPlatform" and "View" for more). Updated versions of both columns are available at: http://www.gamasutra.com/features/programming/19990115/java3d_01.htm and http://www.gamasutra.com/features/programming/19990122/java3d_02.htm Bill Day

"Internationalize your software, Part 3" by Geoff Friesen

Read

Read

Read

Work around unsupported local languages in Java 2

Geoff,

I want to write a Word for Windows-type application/applet for the TELUGU language (Unicode language code TE), one of the languages used in India (Unicode country code IN). But the list of LOCALES supported by Java 2 does not contain te_IN.

My question: Can I use Java to do my project? If so, how?

Srinivas Nimmagadda

Srinivas, Thanks for writing. It certainly is a problem when Java 2 does not support a particular locale. However, you can still write an application from this locale's perspective. You'll just have to do a lot more work. If you read my "

Internationalize your software, Part 2

," article you might recall my discussion about umbrella classes. I had this to say:

An umbrella class is an abstract base class that describes either a common entity (such as a calendar) or a common operation (such as sorting). This class shields code from the many concrete (as opposed to abstract) subclass implementation differences by providing a common interface to these implementations. Umbrella classes contain static factory methods, giving code the ability to instantiate objects from concrete subclasses without needing to know any details about those subclasses.

You typically pass a locale object, for your desired locale, to the factory method. But you can't do this if a locale is not supported. So what do you do? You work directly with the concrete subclasses. For example, suppose you needed a currency formatter for an unsupported locale. You wouldn't be able to work with

NumberFormat

by calling its

getCurrencyInstance

methods. Instead, you would need to work directly with the

DecimalFormat

and

DecimalFormatSymbols

classes. I didn't bother to include an example that uses these classes in the third part of my series because it would have increased the size of an already long article. However, I did point out that there is a good example at Sun's Java Tutorial site. You can visit the Java Tutorial by going to the following address:

http://java.sun.com/docs/books/tutorial/index.html

Geoff Friesen

Solutions to jar file problems in an internationalization applet

Geoff,

I've been trying to use an internationalization applet. I use a jar file with the classes and properties files.

I've read your articles about internationalization, particularly the comment about using jar files with properties files.

However, my applet doesn't run. Netscape always shows the message: "java.util.MissingResourceException: Can't find resource."

My applet is:

 
<HTML>
<HEAD>
<TITLE> A simple program </TITLE>
</HEAD>
<BODY>
<APPLET CODE=internationalDynamic.class
archive=i.jar
WIDTH=800 HEIGHT=600>
</APPLET>
</BODY>
</HTML>

And a jar file includes all classes and properties files.

What can I do to read properties files into a jar file?

Javier Sanz Alamillo

Javier, Thanks for writing. I'm going to answer your question by first providing the following excerpt from my

"Internationalize your software, Part 2,"

article:

Remember last month's Example3 applet -- the applet that works with property resource bundles? I mentioned that this applet would not run under Netscape because it tries to access the user's machine to read the underlying property file, and this activity results in a security violation. This security violation causes the Java runtime code to throw a MissingResourceException object. So how can we get past this problem? The solution is to place Example3's class and property files in a jar file, and to include a reference to this jar file in the <APPLET> tag. The following code fragment uses the jar command (under Windows 95) to create a jar file called example3.jar. This command places example3.class and all files that end with a .properties extension into this jar file:
jar -cvf example3.jar example3.class *.properties
The following code fragment shows the <APPLET> tag with the new ARCHIVE attribute. This attribute is used to identify the jar file.
<APPLET ARCHIVE="example3.jar" 
    CODEBASE="/javaworld/jw-01-1999/internationalize" 
    CODE="example3.class" 
    WIDTH=200 
    HEIGHT=220>
</APPLET>
And now for the grand finale! The following PropertyResourceBundle example shows the same Example3 applet we were introduced to in last month's installment. The source code and class files are the same. The only differences are that the Example3 class and properties files have been placed into a jar file, and that the <APPLET> tag has an ARCHIVE attribute.

This leads me to ask you the following questions:

  1. Have you placed all of your properties files in the jar file? You need to place the properties file for each supported locale in the jar file. You should also include the class file in the jar file. The CODE attribute in the <APPLET> tag simply identifies the class file within the jar file.
  2. Is your jar file in the same directory as your class file? In other words, do i.jar and internationalDynamic.class reside in the same directory on the server? If they don't, you will need to include the CODEBASE attribute in your <APPLET> tag. You will set the value of CODEBASE to the directory containing the jar file.

Geoff Friesen