Thursday, August 16, 2007

i'm bringing olaf back (yeah)

chicken outside my place

Tuesday, August 14, 2007

Keeping Simple Things Simple

You can always tell an overengineered API when you try to do something really simplistic and it takes you about 30 lines of code and 8 different classes.

For example: I want to read an image, make it smaller, and write it out as a JPG with a given quality. This is a fairly common and simple task. Here's the code:

BufferedImage sourceImage
try {
sourceImage = ByteArrayInputStream(imageData));
} catch (IOException e) {
return new ServiceResult(ServiceResult.STATUS.FAIL_HARD,
"Unable to read image; image is unreadable or an unsupported type", e);

// figure out the target width and height

BufferedImage newImage = getScaledInstance(sourceImage, targetWidth, targetHeight, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);

ByteArrayOutputStream output = new ByteArrayOutputStream();

Iterator imageWritersByMIMEType = ImageIO.getImageWritersByMIMEType("image/jpeg");
if (imageWritersByMIMEType.hasNext()) {
ImageWriter writer =;
writer.setOutput(new MemoryCacheImageOutputStream(output));
ImageWriteParam iwp = writer.getDefaultWriteParam();

IIOImage tmpImage = new IIOImage(newImage, null, null);
try {
writer.write(null, tmpImage, iwp);
} catch (IOException e) {
return new ServiceResult(ServiceResult.STATUS.FAIL_HARD, "Exception while creating jpeg content", e);
} else {
return new ServiceResult(ServiceResult.STATUS.FAIL_HARD, "Couldn't find a jpeg encoder!");

return new ServiceResult(ServiceResult.STATUS.OK, "Created avatar successfully", output.toByteArray());

So we had to use: BufferedImage, ImageIO, ByteArrayInputStream, ByteArrayOutputStream, Graphics2D (inside the getScaledInstance method), ImageWriter, ImageWriteParam, MemoryCacheImageOutputStream and IIOImage. (Not counting any java.lang, java.util or exception stuff.)

Why can't ImageIO read a byte array? (I can almost forgive the design decision to work mainly with streams.) Why does an ImageWriter need to write to a MemoryCacheImageOutputStream (an ordinary OutputStream won't do)? What's with ImageWriter#setOutput taking an Object? Do we really expect to have multiple image writers for a given MIME type such that we need an iterator? Why can't an ImageWriter write a BufferedImage? Why is there a getDefaultWriteParam, if that's the only WriteParam there is to get?

javax.imageio has got to be the absolutely most retarded API I have seen to date, with the closest runner-up being jTidy.

Labels: , , , ,

Toplink Query Deficiencies

In any relational setting, it is wise to avoid this situation if you can:

object_id serial primary key not null
foo_id integer not null references TABLE_TWO(object_id)
bar_id integer not null references TABLE_TWO(object_id)

object_id serial primary key not null
some_field varchar(80) not null

There is no way to perform a single join from table_one to table_two to get a complete set of information, because of the references to multiple different rows in table_two. It's probably better to reorganize the relationship if you can.

The exception is if you don't necessarily need both fields. For example, if you can do without knowing anything about bar_id in most cases, you could always lazy load that field. That is, if lazy loading for 1:1 fields works in your JPA provider.

It still doesn't work with Toplink, and these bugs are STILL open:

The consequence is that I cannot static weave my model, so my only choice for now is to mark the fields as @Transient and ignore them for now. (I have a feature that tracks the changes made to every entry in a table with a changer that references an Account... for now, I just won't track the changer until I have time to come up with a better way of doing it or the glassfish folks fix their shit.)

Labels: , , ,

Thursday, August 09, 2007


maruko helping me work

Wednesday, August 01, 2007

Another Dumbshit Toplink Error Message

When Toplink says "Trying to get value for instance variable [foo] of type [bar] from the object The specified object is not an instance of the class or interface declaring the underlying field" what it means is you specified the wrong mappedBy class in your many:many relationship, either explicitly or by inference from your generic type.

But it's much, much clearer to give their error message, isn't it.

Labels: ,

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]