Archive for the ‘Java SE’ Category

Java2D Optimization (a.k.a “Java is NOT slow”)

Wednesday, August 13th, 2008

Playing around with Java2D, I created a little application that paints a lot of PNG images on screen (about 200). I use ImageIO to load them, but the first prototype was VERY slow (3fps maximum).

After reading about fullscreen exclusive mode API and some tips on graphics performance, I’ve created a BufferStrategy using the same snippet from its API. I got no improvement, but the code became a lot cleaner.

Then, I remembered my ancient days as a C programmer, where I always need to convert the image color format to the screen color format. Since I’m programming in Java, I created this snippet:

private static BufferedImage createCompatibleImage(BufferedImage img,
    boolean translucent) {
  GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
  GraphicsDevice d = e.getDefaultScreenDevice();
  GraphicsConfiguration c = d.getDefaultConfiguration();
  int t = translucent ? Transparency.TRANSLUCENT : Transparency.BITMASK;

  BufferedImage ret = c.createCompatibleImage(img.getWidth(),
    img.getHeight(), t);

  Graphics2D g = ret.createGraphics();
  g.drawImage(img, 0, 0, null);
  g.dispose();
  return ret;
}

Maybe there’s a better way to copy the image, but the important part is to create an image with GraphicsConfiguration.

After this little trick, I got an impressive speed boost: from the 2fps-slow-motion-turtle to ludicrous 170fps (yes, one hundred seventy). I feel like saying: “It’s over nine thousand!

Configuring proxy in Java applications

Tuesday, April 29th, 2008

If you have a Java application that needs to connect to Internet, and you are behind a proxy, you have two options:

  1. Add this to the application command line parameters:
    -Dhttp.proxyHost=<host.of.proxy> -Dhttp.proxyPort=<port.of.proxy>
  2. Or edit the net.properties file in the lib folder of your java home. It is self-explanatory, since you have to edit one or two lines and there’s about 70 lines of comments on that file.

The bad news is if your proxy requires authentication. This means you will have to do something like:

Authenticator.setDefault(new Authenticator() {
  @Override
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("username",
        new char[] { 49, 50, 51, 52, 53, 54 } );
  }
});

You can, of course, create a more complex Authenticator subclass, that will open a Popup asking for the proxy user and password.

Tooltip on JTable cells (take 2)

Monday, March 31st, 2008

In a previous post, I explain how to add tooltips to JTable cells. Armand Bendananff told, in a comment, that a better way is to override the table’s getToolTipText method as in:

public String getToolTipText(MouseEvent event) {
  Point p = event.getPoint();

  // Locate the renderer under the event location
  int colIndex = columnAtPoint(p);
  int rowIndex = rowAtPoint(p);

  String tooltip = "some value based on the row/col";
  return tooltip;
}

Long lines in Java Tooltips (or multiline tooltips)

Thursday, February 14th, 2008

Do you want to show a tooltip with more than one line? Are your tooltips too large to fit in one line? The solution is easier than you think. Tooltips, in Java, accept HTML code:

jcomponent.setToolTipText("HTML tooltip");

It isn’t a Firefox, but is very powerful. And, when I said HTML, I also think about CSS. So, you can set your tooltips using this evil cheat:

<html><body>
<div style=”width: 300px; text-justification: justify;”>
Blah Blah Blah (repeat “blah” 100 times)
</div>
</html></body>

Have you seen automatic line breaks and the justification? Oh, yeah!

BTW, do you remember old days, when you couldn’t believe WordPad didn’t have justified text? :)

Copying file in Java - NIO version

Thursday, February 14th, 2008

In old days, copying a file in Java wasn’t easy: you had to create a array buffer to read from source and write to destination. Now, with NIO from JDK, it’s a matter of creating the streams and let the API do the dirty job.

FileChannel src = new FileInputStream(srcFile).getChannel();
FileChannel dst = new FileOutputStream(dstFile).getChannel();
try {
  dst.transferFrom(src, 0, src.size());
} finally  {
  src.close();
  dst.close();
}

Tooltip on JTable cells

Thursday, February 14th, 2008

This is a easy one (but it is not obvious): how to define tooltips in JTable’s cells. Just create a class like this one:

public class ToolTipTable extends JTable {
  @Override
  public Component prepareRenderer(TableCellRenderer renderer,
        int row, int column) {
    Component c = super.prepareRenderer(renderer, row, column);
    if (c instanceof JComponent) {
      JComponent jc = (JComponent) c;
      jc.setToolTipText((String) getValueAt(row, column));
    }
    return c;
  }
}

This example will set cells’ tooltip to its own content. Very useful if you have large contents on small cells.

Blackmagic with NetBeans and OpenOffice

Tuesday, January 8th, 2008

This one is one of the weirdest (and useful) things I ever seen in 16 years of my life as a developer (I’m 26, BTW)… OpenOffice is a very powerful Office Automation solution… NetBeans Plaform is a very powerful application platform… Can you imagine what you get when you mix both together? Yup, this is possible. With NB and OOo installed, you just need to create a NB Module with following JARs from OOo:

  • juh.jar
  • jurt.jar
  • officebean.jar
  • ridl.jar
  • unoil.jar

I created another module with a single TopComponent, and add this snippet:

private OOoBean oo;

@Override
public void componentOpened() {
  add(oo = new OOoBean());
  oo.loadFromURL("private:factory/swriter", null);
  oo.aquireSystemWindow();
}

But, this will NOT work… If you try to run it, an exception will be thrown, because OOo libs (.DLL/.SO) will not be found. They only exists in OOo install folder, and are automagically found by OOo classes - only if they aren’t moved from the “classes” folder in OOo installation.

The workaround is a couple of classes in OOo SDK and The Ultimate Blackmagic(TM) - patent pending:

  1. Grab odk / source / com / sun / star / lib / loader from OOo’s CVS and add it to integration module.
  2. Add unowinreg.dll to Windows Path (if you are on Linux, skip this step).
  3. We need to add “officebean” to classpath. Here lies OOoBean, and is optional if you are only using UNO interfaces. Other JARs are correctly listed by UnoInfo. Alter Loader.java and add this after line 205 (after “UnoInfo” call):
    vec.add(new File(fClassesDir, "officebean.jar").toURL());
  4. Now, the ugliest part of the evil potion: create a Facade. Using OOoBean directly will lead to some ugly ClassLoader conflicts. I’ve no time to fix this, but the following works:
    public static Container buildOOoBean() {
      return (Container) Loader.getCustomLoader().
        loadClass("com.sun.star.comp.beans.OOoBean").
        newInstance();
    
    }
    public static void showOOoBean(Container oo) {
      Class c = oo.getClass().
        getClassLoader().
        loadClass("com.sun.star.beans.PropertyValue");
    
      Class ca = Array.newInstance(c, 0).getClass();
      Method m = oo.getClass().
       getMethod("loadFromURL", String.class, ca);
    
      m.invoke(oo, "private:factory/swriter", null);
      oo.getClass().
        getMethod("aquireSystemWindow").invoke(oo);
    }
  5. Back to the TC, I use “buildOOoBean” in ComponentOpened and “showOOoBean” AFTER the component is shown (does not work otherwise).

This level of indirection is mandatory, because client module’s ClassLoader is different than integration module’s. If I do “OOoBean oo = new OOoBean()”, the declaration and instantiation will try to use the JARs bundled. Since they don’t lie on OOo install folder, the libraries will not be found. If I use “oo = (OOoBean) Loader.getCustomLoader().getClass(”…”).newInstance()”, the “OOoBean” class from declaration will NOT be the same as the class instantiated. If you ever worked with JavaEE 4 and JSF/Struts/etc, you know that same classes from different ClassLoaders throws ClassCastException.

Yes, it is the purest evilness, but works (with some bugs):

Screenshot of OpenOffice and NetBeans

OOo works really well with Java, but NetBeans ClassLoader is “self-contained” (i.e. your bundled application must include EVERYTHING you use). This is a very nice architecture, but does not help if you if you need to interface with external applications.

HTTP POST download with Java’s URL class

Friday, January 4th, 2008

This is easy, but I always forget the recipe. I need to download and process a file using a POST request. The code is:

URL url = new URL(FORM_URL);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);

OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write("field=value&field=value&...");
out.flush();

InputStreamReader isr = new InputStreamReader(conn.getInputStream());
BufferedReader in = new BufferedReader(isr);
String line;

while ((line = in.readLine()) != null) {
    // do something
}

out.close();
in.close();

The only catch is to use URLEncoder.encode to translate keys and values to the x-form-url-encoded style.