Friday, June 18, 2004

Just started setting up Tomcat 5 today and wanted to leave some notes on a few things I had to do to get it to work.

I had to change the doctype of my web.xml. This page had an excellent example of what to do.

I added this to enable EL in JSPs

<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-enabled>true</el-enabled>
<scripting-enabled>true</scripting-enabled>
</jsp-property-group>
</jsp-config>

I had to replace my Jakarta Taglibs Standard 1.0 library with the 1.1 version. 1.0 is for Servlet 2.3, 1.1 is for 2.4. I discovered this when the JSP compiler complained about an EL expression in the value attribute of the <c:param> tag.

Tuesday, June 15, 2004

Just a quickie.

We ran into an issue with our app today that at its root had a problem with the default value for the "session" attribute of JSP pages. Lesson learned: session is set to true by default. In other words, unles you specify the following:

<%@ page session="false" %>

your JSPs will automatically request a session object.

Monday, June 07, 2004

This week I've been learning a great deal about the image handling that is built in the JDK 1.4. Specifically, the javax.imageio.* packages. I've been mainly interested in two things: validating that a file is an image and gathering its meta data, and resizing the image. If users upload an image that is larger than we want to allow, I want to be able to reduce the image to an allowed size so they have the choice of using the smaller image. That way the upload wasn't a complete waste of time.

I accomplished the first step with code like this:


ImageInfo info = new ImageInfo();

try
{
Iterator imageReaders = ImageIO.getImageReaders(ImageIO.createImageInputStream(formFile.getInputStream()));

while (imageReaders.hasNext())
{
ImageReader reader = (ImageReader) imageReaders.next();

info.type = ImageType.getImageType(reader.getFormatName());

if( info.type != null )
{
break;
}
}

if( info.type == null )
{
return null;
}


try
{
BufferedImage theImage = ImageIO
.read(formFile.getInputStream());

info.height = theImage.getHeight();
info.width = theImage.getWidth();
info.fileSize = formFile.getFileSize();

theImage = null;
}
catch (Exception e)
{
log.debug("Exception caught trying to read image", e);
return null;
}

log.debug("Parsed image info: " + info);


I could probably have been more efficient and used the ImageReader I found in the first part of the code to actually read in the image instead of relying on ImageIO.read(). I've only today just been able to figure out that that's an option. The ImageIO guide claims the API was developed with application developer ease-of-use as a top priority. I'm sure it was, but I still think people like myself would benefit from some clear recipes for common operations. Almost everyone posting forum questions about image resizing is doing so for the same reasons as me, so it's clearly a confusing issue. It doesn't help that there's another API, the Java Advanced Imaging API, to confuse the issue. And there appear to be multiple ways to accomplish the goal of resizing an image making the whole thing rather confusing. </rant>

Resizing the image was a bit more difficult with the issue complicated by a bug in the 1.4.1 JDK. Upgrading to 1.4.2_4 fixes the issue (handling of certain JPEGs), but it still took me a while to figure out. Here's how I resize:


File inFile = new File(...);

InputStream is = new FileInputStream( inFile );

BufferedImage bufIn = ImageIO.read(is);

is.close();

// scale is a float with 1 being no change in size, 2 doubling, 0.5 halving...
AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(scale, scale), null);

bufIn = op.filter( bufIn, null );

File outFile = new File(...);

ImageIO.write(bufIn, imageInfo.type.getFormatName(), outFile);




Unfortunately, I'm still not accomplishing my goal with 100% success. I can reduce the file size of an image by scaling it by 50%, but on my test file, 90% scaling actually makes the file considerably larger. And there's really no way to specify a scaling based on file size that I've found. Perhaps I'll have to break down and post questions to the java.sun.com forums...


Thursday, June 03, 2004

Since we're going to allow our users to upload/store images, we need to validate the files they send us. Doing some research on the web, it appears we need to check the following:

1) The actual image binary data. Is the file a valid image? Is it a web image type (E.g. jpeg, gif, png)

2) The image does not have extreme dimensions. No 1x20000 images should be allowed

3) The filename extensions should match the image data. We can correct this automatically if we can identify the image type.

4) The image size should also be capped. The Struts Upload is already capping file upload sizes for us. However, we might want to cap images even lower. Have to talk to marketing about that...

The javax.imageio package seems to have all the tools I need for this.

Tuesday, June 01, 2004

We've decided that our site needs to use URL-rewriting instead of cookies as a means of tracking sessions. (We're hoping it will defeat the nasty habit one of our customer's proxy caches has of showing some users the data for other users. The jsessionid in the URL will hopefully make all URLs unique to each user).

I've learned that to turn on URL-rewriting you have to turn off cookies for the <context> in the Tomcat server.xml file and restart Tomcat. It also appears you have to restart your browser (IE in my case). I tried setting cookies="false" in META-INF/context.xml, but it doesn't appear to have any effect in Tomcat 4. I've heard Tomcat 5 is more respectful of settings in context.xml.

Of course, to make URL rewriting work, you have to pass all your URLs through HttpServletResponse.encodeURL() or use the appropriate taglib tag (<html:rewrite>, <c:url>, etc...)