★ wanayoo — archive 1999 http://developer.java.sun.com/developer/community/chat/CodeClinic/1997/cc0911.htmlNouvelle recherche | Portail wanayoo
Java Technology Home Page
A-Z Index

Java Developer Connection(SM)
Chat

Downloads, APIs, Documentation
Java Developer Connection
Tutorials, Tech Articles, Training
Online Support
Community Discussion
News & Events from Everywhere
Products from Everywhere
How Java Technology is Used Worldwide
Print Button
 

Code Clinic
includes questions on servlets, HTML components in HotJavaTM, JDBCTM drivers, and lightweight components
September 11, 1997

Guest-Speaker (SPK): SPK-jaz and SPK-rohaly

SPK-jaz: Hello, and welcome to the Code Clinic for Thursday, September 11. I'm John Zukowski with MageLang Institute, and rohaly is Tim Rohaly, also from MageLang. We're here to try to answer questions you have about anything Java-related.

SarahThompson: Thanks for having a code clinic! My question is about Images in JavaTM servlets. I have written a servlet that creates an Image object and paints it. Note: there is no file associated with the image, I make the picture on the fly. I would like the servlet to return the Image object to the browser for display. I plan to write a Java 1.0 version applet that will send the URL that triggers my servlet, since the potential customer is running ancient PCs that do not support Java 1.1. How can the servlet turn an Image object into something returnable by the servlet?

SPK-jaz: The easiest thing to do doesn't involve compression or converting the image to GIF/JPEG. Of course, if the image is large, you may want to compress in some way. Basically, use java.awt.image.PixelGrabber to get a byte/int array from the java.awt.Image. Then send the array over the connection to the applet. You might need to pass the width/height off as the first two things out over the connection, so the receiving end knows the size (unless it will always be the same size, then that isn't necessary). Once you have the array in the applet, have the applet use java.awt.image.MemoryImageSource to convert the array back into an Image.

If you would like to create an image file, that you would need to delete at some point, look at www.acme.com for classes to support this. Then, you would only need to send the URL of the file to the applet, and read it through normal getImage() means.

bruce76: Hi, I am creating an applet using two ListBoxes. I want to transfer a selection from the first one to the second one without duplicates. How do I do this using the ListBox?

SPK-jaz: Welcome bruce. Let me get this straight, you want to have two List components, and you want to remove one from the first and add to the second based on some event?

bruce76: Yes, but I also would like to delete or disable the selected List item from the list it originally came from.

SPK-jaz: You can delete (remove) items from a List with the
public synchronized void remove(String item) method in Java 1.1 or public synchronized void delItem(int position) in Java 1.0.

bruce76: I used the Java 1.0 delete command before, with errors.

SPK-jaz: Do you mean delItem?

bruce76: Yes. I would like to know if I can delete and replace items from both Lists. I have another question: Is there any way to disable single items in a single List?

SPK-jaz: The 1.0 List component is rather limited in what you can do. That is why there are so many more things you can do in 1.1. Neither permits one to disable items, although you should be able to do that with the Swing ListBox).

bruce76: Oh, I can do that with Swing? Thanks!

SPK-jaz: The ListBox has rather nice capabilities.

bruce76: Does the version 0.4 Swing ListBox work OK? I heard about some bugs in Swing.

SPK-jaz: I haven't had a chance to download 0.41 yet. I was able to do quite a bit with the 0.3 version of ListBox, like display images with text, load the ListBox from an array of String elements, and display different text when selected. Do take a look at it.

analogue: Please go into gory detail about the addNotify() method. I have yet to find a good explanation of exactly what is going on behind the scenes when this method is called. Why should I care, and in what scenarios is it important?

SPK-rohaly: addNotify() is used to create a peer for an AWT component. In general, you should not have to call this method. But sometimes, it is needed to force a peer to be created before it normally would.

The reason you would want to force creation of a peer is because sometimes you want to invoke a method that is handled by the peer, and you want to invoke this method before the peer would normally be created.

analogue: Why would I, as a developer, even want to know when the peer is created?

SPK-rohaly: You shouldn't have to know, you shouldn't need to know, you should never have to deal with addNotify()--but that is in a perfect world. One of the times I have used addNotify() is if I am going to use the createImage()
method (which is defined on Component). Sometimes I want to use this from within the constructor of a subclass of Component, where the peer hasn't been created yet.

uomini: I just downloaded HotJavaTM 1.1 Beta 2, and I think I died and went to heaven: the HotJava HTML component is finally available. The question is: How exactly do I add it to my Java application? Is there documentation anywhere that details how to use the HTML Bean?

uomini: If there is no documentation on the HTML Bean yet, can you tell me how to use it?

SPK-jaz: I don't have any examples sitting around. Let me try to get one for you and add it to the transcript. [John Zukowski has since provided the following example.]

A note about the following code: The following code requires the HotJava 1.1 beta2 class libraries. Be sure to read the HotJava licensing agreement regarding their distribution. Basically, they are not freely distributable, and outside of the HotJava browser they are only usable for noncommercial purposes.

Now that the HotJava Bean Component is packaged as a product, there is a little more documentation. Be sure to read the readme.html file that is bundled with the product. Besides the BeanBox example that is provided, you can just use the Bean yourself in source code with something like the following example:

import java.awt.*;
import sunw.hotjava.bean.HotJavaBrowserBean;

public class Foo extends Frame {
  Foo (String urlString) {
    HotJavaBrowserBean hj = new HotJavaBrowserBean();
    add (hj, BorderLayout.CENTER);
    hj.setDocumentString (urlString);
    setSize (400, 400);
    setVisible (true);
  }
  public static void main (String args[]) {
    String site = "http://www.magelang.com";
    if (args.length != 0)
      site = args[0];
    Frame f = new Foo(site);
  }
}

muraliM: We can't print anything from the Netscape browser/IE, if we are using an applet. Is there any way we can do this?

SPK-rohaly: Current versions of Netscape and IE don't support the new JDKTM 1.1 printing scheme. Printing was impossible to do (other than with a screen dump) in JDK 1.0.x. With JDK 1.1, it should be possible and easy, but no one supports this yet. (Not even Netscape with the JDK 1.1 patch :-( But support should be coming soon, if you can wait a few more months.

rowehrli: I've been trying to get local cookie data from the browser to a running applet. Do you have any idea if this can be done?

SPK-jaz: Normally, cookie data is not available to Java programs. However, through communications with JavaScriptTM, you can access it in a platform/browser-specific way.

TMRTMR: I need help in the code involved in PropertyChangeEvents. I have a class that extends TextField and contains the appropriate(?) code:

public class newText extends TextField 
    implements Serializable
{
   ...
   
   public void addPropertyChangeListener(
      PropertyChangeListener l) 
   { changes.addPropertyChangeListener(l); }
   		
   public void removePropertyChangeListener(
      PropertyChangeListener l) 
   { changes.removePropertyChangeListener(l);}
   
   ...
    
   public void focusLost(FocusEvent e) 
   {			
      Contents = getText().trim();
      changes.firePropertyChange("Contents","dummy",
         Contents);		
      ...
   }
This class and the invoking program work just fine in all other respects. What I want to do in the invoking program is trap a particular property when it changes, and I haven't figured out the code for that. The approach I'm taking looks like this:
   ...
   
   tt1 = new newText("Default value");
   tt1.addPropertyChangeListener(reportChange(
      PropertyChangeListener l));

   ...

   public void reportChange(PropertyChangeEvent pce)
   {
      System.out.println("reportChange() fired");
   }  

   ...
It's the "tt1.add..." line that gets me in trouble (if not the whole approach). What's the proper syntax here? I haven't been able to find a good example anywhere.

SPK-rohaly: I suppose you know how to make your class generate PropertyChangeEvents by defining the addPropertyChangeListener and removePropertyChangeListener methods, then delegating the implementation to the PropertyChangeSupport class.

Your listener class must implement PropertyChangeListener, and override propertyChange() method to deal with the PropertyChangeEvent.

To wire components together, you simply use addPropertyChangeListener to connect the listener to the component that generates the PropertyChangeEvent.

So it is the same as any other event source/event listener.

TMRTMR: I understand the principle (I think). It's the code in the program which instantiates the class that is baffling me.

SPK-rohaly: The line that is giving you problems should be something like: tt1.addPropertyChangeListener(myListener); where myListener is an instance of a class that implements PropertyChangeListener and has a public void propertyChange(PropertyChangeEvent e) method.

This propertyChange() method gets invoked when the event source generates the PropertyChangeEvent.

SPK-jaz: TMRTMR, here is a code snippet that might help:

box1.addPropertyChangeListener(new 
   TriBoxer_box1_propertyChangeAdapter(this));

void box1_propertyChange(PropertyChangeEvent e) {
   if (e.getPropertyName().equals ("color")) {
      Color newColor = (Color)e.getNewValue();
      box1.setColor (newColor);
      box2.setColor (newColor);
      box3.setColor (newColor);
}

analogue: How can I print using 1.1 PrintJob API without having to make what I want to print visible on the screen? I get blank pages unless I show() the component on the screen first.

SPK-jaz: To print without showing something in your paint() routine, do something like:

paint (Graphics g) {
if (g instanceof PrintGraphics)
   do something
else
   do something else
}
The other way to think of printing is that it gives you `total control' of the displayed page. It's kind of like when you want to print the total contents of a TextArea, instead of only what is drawn to screen.

analogue: Let me show you a little code that might help explain better.

f is a frame. If I take the call to setVisible() out, I will get blank pages. You're saying I should change to f.paintAll(pg)?

public void printCurrentPage()
{
   Graphics pg = pjob.getGraphics();

   if (pg != null)
   {
      f.setLocation(100,100);
      f.setVisible(true);
      f.printAll(pg);
      pg.dispose();
   }
}

SPK-jaz: It seems like JoeSam would like to offer an opinion about this. Let's see what he has to say before I answer that.

JoeSam: Well, not an opinion.

analogue: Solutions are better than opinions :)

JoeSam: I just wanted to say that I have posted a fairly complete print example on the DukeDollars page at newbie question 59. It generates its own data, but to get something from a TextArea or other component, use getText(), parse the data into intelligible print lines, and print. The example works as an applet or application. (To get to DukeDollars newbie question #59, go to http://developer.java.sun.com/developer/toolbar.shtml and select the GroupReaderApplet from the JDC Applet Toolbar. Be sure to search for "all questions.")

analogue: The problem is not getting what I want to print on the PrintGraphics context. The problem is getting the contents of a frame to print without having to render it to the screen first.

SPK-jaz: analogue, let me add, in your example, if you want to dump the screen contents of a frame, you must show the frame first. Because Java 1.0/1.1 uses peers, the only way to know what a component looks like is to show the frame.

I haven't tried printing Swing components yet, but I suspect what you want to do may be possible with them, without showing the frame.

analogue: That's all I wanted to know--no printing without rendering to the screen. Is this still the case with JFC?

SPK-jaz: You can print without rendering. You just keep doing screen dumps without rendering.

analogue: Why is it a screen dump? A frame is a component. What is different? Oops...maybe not. Container, I mean.

SPK-jaz: Because Java relies on the platform's peer to know how to display a component, the only way to print Component objects is to show them. I don't necessarily mean a complete screen dump. Think of it as a component dump.

rowehrli: Is there anyway to get HTTP server response headers to a running applet?

SPK-rohaly: Sure, with the URLConnection class. The caveat is that the applet can only connect back to the HTTP server from which it was loaded.

rowehrli asked for an example using URLConnection. Let me post it for everyone to see. Here is the URLConnection example, it uses the JDK 1.0.2 API and reads text data from a URL, printing out a few of the header fields:

import java.io.*;
import java.net.*;

public class GetURL {
   public static void main(String[] args) {
   
      URL url = null;
      DataInputStream in = null;
      
      try {
         if (args.length == 1) {
            try {
               url = new URL(args[0]);
            }
            catch (MalformedURLException e) {
               System.err.println("Exception " + e);
            }
         }
         else {
            usage();
            System.exit(1);
         }
         
         URLConnection urlc = url.openConnection();
         System.err.println("Content-Type: " + 
            urlc.getContentType());
         System.err.println("Content-Encoding: " + 
            urlc.getContentEncoding());
         System.err.println("Content-Length: " + 
            urlc.getContentLength());
         
         in = new DataInputStream(urlc.getInputStream());
         String line;
         while ( (line = in.readLine()) != null ) {
            System.out.println(line);
         }
      }
      catch (Exception e) {
         System.err.println("Exception " + e);
      }
      finally {
         try { in.close(); }
         catch (IOException e) {}   
         // close and free up system resource.
      }
   }
   
   private static void usage() {
      System.err.println("Usage:  java GetURL url");
   }
}

egagnon: What's wrong with this program? It doesn't exit.

import java.awt.*;
class Main
{
   public static void main(String[] arguments)
   {
      FileDialog dlg = new FileDialog(
         new Frame(), "Load File", FileDialog.LOAD);
      dlg.show();
      System.out.println("File Name: " + 
         dlg.getFile());
      dlg.dispose(); // Just to make sure
      dlg = null;  // Let's be really sure
      System.gc(); // Why not?
   } // NO!! It doesn't exit!!!!
}

SPK-jaz: Once an AWT component is created, a new system thread is created. Because this thread continues to run, the program still runs. To come up with an even simpler test case, just do new Frame().show(). Do you really want Java to exit after displaying a Frame?

egagnon: dlg.show is a modal dialog. So my answer would be, yes, in that case.

SPK-jaz: Submit a suggestion to the Java team with reasonable justification. Beyond that, there is nothing I can do. Why not just add a System.exit(0) call at the end though?

egagnon: I would say that a justification would be that the system shouldn't create a nondeamon thread. Does this make sense?

SPK-jaz: Not a sufficient reason.

egagnon: Calling System.exit(0) does not comply with the 100% Pure JavaTM guidelines. Is this a sufficient reason?

SPK-jaz: Why doesn't it comply?

egagnon: It is written explicitly in the Cookbook. You could be aborting important threads. So you should rely on the VM behavior of exiting when all nondeamon threads are dead.

SPK-jaz: Then write up the suggestion with that justification. There is nothing we can change here though. I would suggest attending the Pure Java discussion forum on the 16th and see what Ray Gans and Roger Hayes have to say about your reasoning.

analogue: Could you please explain why lightweight components are better than peer-based components? I don't understand why they are considered more efficient and faster. If anything, I would think peer-based components have the upper hand because they are implemented in the native windowing system.

SPK-rohaly: Well, I can list a couple of reasons.

First, lightweight components can be made transparent. Imagine if you want to create a round button. Without lightweight components, you would have to subclass Canvas and draw your button on the Canvas. But Canvas is opaque, so you would have to worry about setting the background color of your Canvas to match the background of the application, and you would have a real problem if your application background was an image.

Second, peers utilize operating-system window handles, which are a limited resource. A lot of times you only use a component as a container or a spacer, and in those cases there is no need to create a native OS peer--it just consumes resources and adds an extra layer of object to your application.

Third, sometimes you might want to intercept events before the native peer does. For example, you might want to capture a mouse event, but the native peer normally consumes them before you even see them.

Fourth, you can ensure a common look and feel across all platforms. Without lightweight components, you get the platform-specific look and feel, whether you like it or not. The JFC components, by the way, are all lightweight--which is how they manage the pluggable look and feel.

Fifth, you can subclass lightweight components to provide improved functionality that is not available to the peer class. For example, if you wanted to subclass Button to create an ImageButton, you couldn't do it. This is because the native Button doesn't support an icon--only text. But if your button is lightweight (like the JFC JButton), then you can subclass it to add any visual or behavioral enhancement you want.

I could probably go on, but that's enough for now :-)

analogue: So you're saying lightweight components are really just constructed from OS-specific primitives, but not full-blown widgets.

SPK-rohaly: No, lightweight components don't have any OS-specific stuff in them--they are pure Java. The exact definition is that they are a subclass of Component (or Container), so they don't have an associated peer.

muraliM: Say, for example, if I'm using some database to retrieve information and generate some graphics--is it possible to do that using JavaBeansTM?

SPK-jaz: Yes, it is possible, assuming you can find a Bean to generate the graphics. I like the charting Bean from NetCharts (http://www.netcharts.com). There are others available from companies like KL Group and RogueWave.

JoeSam: Any comments/enlightenment on calling/invoking other Java applets or applications? I guess I'm thinking of a menu-type system that calls other programs.

SPK-jaz: Personally, I haven't seen anyone do this. But there is nothing that stops you from calling the main() method directly in any class that has one. I have seen people wrap applets within a frame, and start them up with init(), start() calls. It's not too common though. Of course, you can always exec something to start, but then it isn't "pure."

rowehrli: How do I find more information on writing my own JDBCTM driver for a database that doesn't currently have one?

SPK-jaz: Before I answer, what is the database?

rowehrli: I'm currently exploring three different ones, JustLogic technology's, Solid's, and one of my own ISAM <-> SQL interface design.

SPK-jaz: Wiley has a book that discusses creating JDBC database drivers: Java Database Programming from Brian Jepson. If you weren't trying to create a driver, I wouldn't recommend it though.

Also, Addison-Wesley has a new book out in the "official" series from JavaSoft. (JDBC Database Access with Java) I haven't looked at it much, besides flipping through it. It might have something for you. You might also want to post an email to the JDBC email list. Someone might already have a driver.

SPK-rohaly: I agree with Jaz's evaluation, the book is of limited use, unless you are specifically interested in creating a driver.

pliew: Does anybody know how can I request more security permissions in an applet?

SPK-rohaly: Are you asking how to get Netscape or IE to let your Applet do something that is normally forbidden? You can't.

pliew: How can I request for more security priviledge in an applet?

SPK-jaz: Actually, Netscape 4.0 lets you do more with Object Signing.

SPK-rohaly: In the next versions of the browsers, hopefully, they will support signed applets along with a configurable security model. Right now, only HotJava will let you do this. The Netscape 4.0 object signing is Netscape-specific, and not the same as the general Java class signing.

SPK-jaz: If you have Netscape Commmunicator 4.02, go to http://www.net7.co.uk/dataTRAK/Trakker.htm to see a `signed' applet that communicates with the hosts it came from. And the Cab signing from Microsoft is specific to them. Unfortunately, they aren't the same.

sbesel: Hi, I am looking for way to find Java++. Can you help me?

SPK-jaz: Besides a tool used to create applets, is there anything else you know about the product? With a name like that, it is very difficult to find. Are you sure you don't mean Visual J++ (didn't come from Microsoft)?

For a list of tools that support JavaBeans, you can look at: http://java.sun.com/beans/tools.html.

JoeSam: JDBC question: I'm fuzzy about selecting a driver myself. I understand the JDBC mechanism `looks' for one that can provide the service. Is that correct or not? I'm thinking in terms of connecting myself without user intervention/selection, for a batch or background-file processing run, for example.

SPK-rohaly: When you say DriverManager.getConnection(url, name, password), the DriverManager class is responsible for looking at the URL subprotocol and selecting a registered driver to use to make the connection.

JoeSam: Right, the terminology is selecting `a' driver that the manager decides can do it. What if I want to be sure of a specific one?

SPK-rohaly: The individual drivers register themselves by using static code blocks. So a driver would have something like:

static {
   DriverManager.registerDriver(this());
}
That is why you just have to say:
Class.forName("drivername");
By loading the class, the static block gets executed, and the driver registers itself with the DriverManager.

You only have to worry about that if you have multiple drivers registered that deal with the same protocol. In which case, by default, the first one registered will be used (I'm not sure if that is guaranteed, but that's the way it now works.)

JoeSam: So to be sure, I should have only one driver that can do the specified task, or can I influence the registration order?

SPK-rohaly: You can use DriverManager.getDrivers() to find a list of the currently registered drivers. If you want a specific driver out of many that are registered with the same protocol, one thing you can do is to use the deregisterDriver() method of DriverManager to deselect the one(s) you don't want. (You can always reregister them later).

As a good practice, you should only have one registered driver for each subprotocol--that way you will be sure of what is going on.

JoeSam: If I have a product that goes out to a lot of users, I may not have control over how many drivers are installed. JavaSoft engineers need to think of commercial/enterprise needs, as well to have an effective tool.

SPK-rohaly: Hmm, think about what you mean by "installed"...The drivers can't get registered except through something like Class.forName() or by setting the jdbc.drivers property upon invocation of the VM. These are things that are controlled by the programmer, not the user. It would probably be dangerous to let the user have complete control over what driver is loaded and used.

lassej: Can anyone tell me, how can I get my hands on the Java WorkShop, and is it better than IBM Visual Age?

SPK-jaz: WorkShop is available at http://www.sun.com/workshop/java/ I would also recommend http://rampages.onramp.net/~ranger/java_workshop.html as an available resource. I haven't used it personally. It is something that runs on a Unix platform--your choices are limited there. If you are on a PC, JBuilder is now shipping too.

lassej: Where can I get JBuilder?

SPK-jaz: JBuilder is available from Borland (http://www.borland.com/jbuilder) It is not downloadable though. You have to order it, or try to find it at Egghead or some other store. I've heard it has sold out of most of the first shipments.

For cookie access from Java, you need to use the MAYSCRIPT <APPLET> tag and import the netscape.javascript package. The solution is specific to Netscape.

rowehrli: Yeah...I'm trying to find platform-independence in a world dominated by MS, ho hum. :)

SPK-jaz: By the way, as JoeSam reminded me, WorkShop is available for Win95/NT, besides Solaris. There isn't direct cookie support from Java. I'm not sure what would happen if you made the Netscape JavaScript packages available from a web server and the browser was IE. Worth a try... ;-) Java World also has an article on using RMI for cookie-type functionality.

rowehrli: That sounds "worth a try" :@)

SPK-jaz: I might also recommend going to DejaNews and looking through the archives for hints. They were the only place I could find anything remotely related.

JoeSam: www.digitalfocus.com/faq is a good source, although I don't know if they have anything on cookies.

SPK-jaz: They don't, I checked.

JoeSam: Of course, JDC is the best place.

SPK-jaz: That looks like its it for this week's code clinic. Thanks for coming, maybe we'll see you back next week.

SPK-rohaly: Thanks for coming. See you next week.



Print Button
[ This page was updated: 30-Mar-2000 ]
Products & APIs | Developer Connection | Docs & Training | Online Support
Community Discussion | Industry News | Solutions Marketplace | Case Studies
Glossary - Applets - Tutorial - Employment - Business & Licensing - Java Store - Java in the Real World
FAQ | Feedback | Map | A-Z Index
For more information on Java technology
and other software from Sun Microsystems, call:
(800) 786-7638
Outside the U.S. and Canada, dial your country's AT&T Direct Access Number first.
Sun Microsystems, Inc.
Copyright © 1995-2000 Sun Microsystems, Inc.
All Rights Reserved. Terms of Use. Privacy Policy.