Skip to content
accelerando

Category Archives: Java

Enabling tooltips on a JTree

12-Aug-08

Thinks i keep forgetting. Today: Enabling a JTree in J2SE to show different tooltips on his nodes:

1. Create a custom tree renderer like so:

import java.awt.Component;
 
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
 
public class TooltipTreeRenderer  extends DefaultTreeCellRenderer  {	
  @Override
  public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
    final Component rc = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);		
    String tooltip = "Compute some arbitrary text depending on the node (which is hidden behind 'value')";
    this.setToolTipText(tooltip);
    return rc;
  }
}

2. Set this renderer

aTree.setCellRenderer(new TooltipTreeRenderer());

3. Keep wondering, why the tooltip doesn’t show…

4. Register the tree with the ToolTipManager (which isn’t necessary for nearly all other Swing Components…)

javax.swing.ToolTipManager.ToolTipManager.sharedInstance().registerComponent(aTree);

5. Enjoy :)

regex: URL thingy with username, password, host and port

07-Jul-08

Just in case i do keep forgetting that stuff, here’s a regex for decoding urls like

ftp://user:somepass@somehost:someport

in Java:

final Hashtable<String, Integer> portMap = new Hashtable<String, Integer>();
portMap.put("ftp", 21);
portMap.put("sftp", 22);
 
final Pattern urlPattern = Pattern.compile("(ftp|sftp)://(\\S+):(\\S+)@([\\S&&[^:]]+)(:(\\d+))?");
 
final Matcher m = urlPattern.matcher(url);
if(!m.matches()) 
	throw new RuntimeException("Invalid ftp url!");			
 
final String protocol = m.group(1).toLowerCase();
final String user     = m.group(2);
final String password = m.group(3);
final String host     = m.group(4);
final int port = m.group(6) != null ? Integer.parseInt(m.group(6)) : portMap.get(protocol);

Just in case anybody is interessted, i’m writing a wrapper around j2ssh and Commons::Net to support both ftp and sftp in a J2SE program.

Hibernate and Inheritance Mapping

27-May-08

Hibernate supports multiple types of inheritance mapping, some of them (Table per class, Table per subclass) using a discriminator column to decide the class.

The type of the discriminator can be one of

string, character, integer, byte, short, boolean, yes_no, true_false

In case you need to use any other than string or character, i.e. integer, you have to give the base class a default discriminator-value like 0 or -1 or whatever fits, otherwise you’ll end up with a an exception like:

org.hibernate.MappingException: Could not format discriminator value to SQL string

as Hibernate uses the class name of the base class to derive a default value.

Division by zero

26-May-08

Just a quick reminder for myself:

int a = 0/0; // Throws ArithmeticException
double d1 = 0/0.0; // d1 is NaN
double d2 = 1/0.0; // d2 is Infinity
double d3 = -1/0.0; // d3 is -Infinity

Can cause some headache if things fall apart in the JDBC driver and not before. Grmpf.

SCJP, finally!

06-May-08

More than a year ago i decided to do the Sun Certified Java Programmer. Shortly after i bought this book, the projects at work and at home were somewhat overwhelming and after all, i realized that a big part of the SCJP is about some weird, crazy and sometimes wrong design decisions of the Java language. Some of them i mentioned under this tag.

Last month i realized i had some spare time, signed up at Prometric and had a 2nd look at the book and on my good Java experience from the last 6 years.

First thing: The “Java 5 Study Guide” isn’t a bad book but the “MasterExam” software on the enclosed cd is a master piece of crap. Not only the gui is as shitty as it gets but some of the answers are just plain wrong.

Second thing: I bought the preparation kit from Whizlabs for 50€. This thing isn’t bad at all and helps you get prepared for the craziness thrown at you.

Third: Being good at something is always great :D It rocks, really. Like single trail riding or music with electric guitars while driving open. It’s like drugs but not that unhealthy.

After about 2 weeks of preparing, I arrived 30 minutes early at “New Horizons” in Cologne, took the test certainly in english as i prepared with english material and finished somewhat 50 minutes later (you have officially around 3 hours to take the test). The nice proctor asked me if i wanted to use the toilet as she saw my report being printed: 90%, pass! Wooot!

I thought about this post at Jans. I really like the guy who wins a million dollars at Who wants to be a Millionaire and has the guts to call his dad but not ask for help and instead tells him he is going to win a million dollars. I can totally relate to that as i always had fun taking test and scoring at the upper limit :D

So today i’m gonna eat an extra portion of Cookies & Cream and leave you with the following piece of Java madness:

More…

Tired of all the powerpoint presentations…

23-Apr-08

Right now i’m in Wiesbaden, attending the JAX 2008 conference.

The mood is somewhat different compared to the DOAG i used to visit the last years. The people are more open minded, partially much younger and generally try to be much cooler. And for the sake of it, some are even more interesting and after all, there isn’t that ongoing whining about Oracle not engaging in Forms 6i Client Server any more (although, i must admit, i somewhat like Oracle Forms 6i, maybe it’s a love/hate relationship, trust me, i know both worlds, Java and Forms).

The sessions suffer from one big problem: Many of them just seem to play powerpoint karaoke: Throw in a bunch of crappy slides with a handfull code snippets and sing-a-long to that stuff which means basically: Hind behind the slides.

Let me tell you: This is so boring and pointless. In the past i tried to be polite and always stayed to the end of a session but the last 2 or 3 conferences i can’t stand it any more. I can read myself, thanks. If you haven’t got anything additionally to say, just pass me the slide and i’m fine.

The 3 most interesting sessions where the sessions spoken freely with the slides just illustrating the speech. I especially liked Brian Chans presentation of Liferay Portal, Rod Johnsons keynote on the future of J2EE and the most witty one, Ted Newards talk about the renaissance of languages. It was funny, included the audience, was well prepared and freely hold, not to forget the topic: It wasn’t about the nth framework around the corner but about the nearly philosophy topic about the “perfect programming language”.

I really wish that i’d be creative and intelligent enough to design a language that is not predestined to die an early death, but i ain’t. But i can distinguish a sharp tool from a spoon if i see one and i can adopt to it very easily. And in that sense i share Teds opinion that a discussion about abstracting things and about the tool itself is of much more value than implementing some arbitrary pattern (i.e. one be the GOF) in just another framework. For example, many implementations of some patterns in frameworks have been rendered obsolete by more powerful and more expressive languages and i’d like to see this trend go on.

Beyond all evil: Javas definition of an object

09-Apr-08

Some days i ago, i decided to revamp my ambitions to get the scjp thingy done. What exactly for, i don’t know. But working to the self tests, i found the following:

class Ring {
  final static int x2 = 7;
  final static Integer x4 = 8;
  public static void main(String[] args) {
    Integer x1 = 5;
    String s = "a";
    if(x1 < 9) s += "b";
    switch(x1) {
      case 5: s += "c";
      case x2: s += "d";
      case x4: s += "e";
    }
    System.out.println(s);
  }
}

Questions is: Some arbitrary output or a compilation error and if, on which line.

Answer: Compilation fails due an error on line 11. What the frag? The obviously totally retarded switch statement can only handle constant values in its branches. So what? x4 is declared final static, as constant as it can be in Java. But no… Because its a big difference between int and Integer and due to the auto boxing and unboxing in Java 5 and up, the object Integer isn’t constant opposed to the scalar int.

Summary: A big deal with the SCJP is to teach the contestants how to work around some brain dead things in Java. Don’t get me wrong, i actually like Java, but the more i do in Ruby and the likes, the more some concepts in Java seem and are just wrong, like the for example not being all things equally objects.

JDBC: Autogenerated keys revisited.

02-Apr-08

Some months ago i wrote about retrieving auto generated values with JDBC from an Oracle Database: JDBC: Get autogenerated keys on a Oracle DB.

The solution i presented in the previous article doesn’t run in a Oracle Java Stored Procedure.

To accomplish this, use a callable statement like this:

final String sql = "BEGIN INSERT INTO foobar(id, b) VALUES (id.nextval, ?) RETURNING id INTO ?; END;";
CallableStatement cs = connection.prepareCall(sql);
stmt.setString(1, "bar");
stmt.registerOutParameter(2, Types.INTEGER);
stmt.executeUpdate();		
rv = rs.getInt(2);

This way you get the id generated by the sequence id without first selecting and then using it.

Feeling dizzy…

26-Mar-08

After staring at this

dummy

for about a day in various rotations and flips just to get Oracle GeoRaster work together with a homebrew GIS like application made me feel somewhat dizzy. To be cartesian or not cartesian, that is the question ;)

Otherwise, Oracle GeoRaster works quite well, at least for that bunch of german TK25 maps in GK3 coordinates that used to float around in the filesystem and are now being stored in the database.

A fistfull of readers

23-Oct-07

After presenting a working InputStream on a ByteBuffer, i have to more readers for you out there.

First, the StringBufferReader to efficient read data from a StringBuffer. One can use new java.io.StringReader(sb.toString()) but that would convert the whole StringBuffer (sb) to a string, loosing a whole lotta memory if the string is just big enough. If you can assure that the StringBuffer don’t need to be modified, use the following code:

import java.io.IOException;
import java.io.Reader;
 
public class StringBufferReader extends Reader {
	private int pos;
	private final StringBuffer sb;	
	private boolean closed;
 
	public StringBufferReader(final StringBuffer sb) {
		this.sb = sb;
		this.pos = 0;
		this.closed = false;
	}
 
	@Override
	public void close() throws IOException {
		this.closed = true;
	}
 
	@Override
	public int read(char[] cbuf, int off, int len) throws IOException {
		if(closed)
			throw new IOException("Reader is closed");
		int _len = Math.min(len, sb.length() - pos);		
		sb.getChars(pos, pos + _len, cbuf, off);
		pos += _len;
		return _len == 0 ? -1 : _len;
	}
}

It uses no intermediate buffer.

In the same context i stumbled upon the Byte Order Mark (BOM) in some UTF8 files (especially ones that were created with tools under Microsoft Windows).

The InputReaders and Streams in the JRE don’t skip the BOM, neither does the org.dom4j.io.SAXReader so parsing of such XML files or strings fails with something like “Content not allowed in prolog”. Enter my simple BOMSkippingReader:

import java.io.IOException;
import java.io.Reader;
 
/**
 * This reader skips a possible Byte Order Marker at the 
 * start of UTF8 files which java doesn't.
 * @author michael
 *
 */
public class BOMSkippingReader extends Reader {
	private final Reader decorated;	
	private final boolean rewrite;
	private final int firstchar;
	private int pos = 0;
 
	public BOMSkippingReader(final Reader decorated) throws IOException {
		this.decorated = decorated;
 
		this.firstchar = decorated.read();						
		this.rewrite = firstchar != 65279;			
	}
 
	@Override
	public void close() throws IOException {
		decorated.close();
	}
 
	@Override
	public int read(char[] cbuf, int off, int len) throws IOException {					
		int redone = 0;					
		while(rewrite && pos < 1) {
			cbuf[off + pos++] = (char) firstchar;
			++redone;
		}
		return redone + decorated.read(cbuf, off + redone, len - redone);				
	}
}

If there’s a BOM in the underlying reader, it’s skipped, otherwise written back to the reader. Works well for me and the small while loop doesn’t have much impact on the performance in my app.

Close
E-mail It