Tuesday, October 30, 2007

Odd JSP EL behaviour

I just discovered an oddity in JSP Expression Language. I'm a huge fan of EL and its many uses. This is hardly a problem, but is something to keep in mind because it is an unexpected behavior.

Take:

int a = 5;
int b = 2;

System.out.println(a / b);

The println statement will output 2. Thus in EL (and JSTL) in a JSP you would expect the same integer division behavior from the following:

<var="a" value="5" />
<var="b" value="2" />

${a / b}


In the above, ${a / b} yields 2.5, behaving like floating point division rather than integer division. I can see this having its uses, but it surprised me, especially since I've been working almost exclusively in Java web technologies for the past few years. For future purposes I created an EL function so I can just call the following when I want to force integer division (where f is whatever prefix is specified for the custom taglib):

${f:integerDivision(a,b)}

Monday, October 29, 2007

Why I'm not moving to Leopard

Although I've been looking forward to OS X Leopard for some time now, I just can't make the switch yet. As it turns out, there's one major hurdle to be overcome before Leopard is an option for developers of Java EE 5 applications to be deployed on Glassfish. Here's the problem:

Glassfish encounters an exception that prevents domain startup when connected to the internet via Wireless, not connected at all, or in any other way not connected by the ethernet port (Stack trace below). If, however, I'm connected via the ethernet port, everything is okay. I develop applications to deploy in Glassfish, but I can't limit my development to when I'm tied down by the ethernet cable. So until there's a solution, I'm sticking with Tiger.

Anyone with a solution, please let me know. I haven't seen anything like this since fixing PCs with strange APIPA problems...

Full Exception:

[#|2007-10-29T15:28:48.086-0400|SEVERE|sun-appserver9.1|
  javax.enterprise.system.core|
  _ThreadID=10;
  _ThreadName=main;com.sun.enterprise.admin.server.core.JmxConnectorLifecycle@328cbf;
    com.sun.appserv.server.ServerLifecycleException: Cannot bind to URL
    [rmi://169.254.161.207:8686/management/rmi-jmx-connector]:
      javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException:
      Connection refused to host: 169.254.161.207; nested exception is:
      java.net.ConnectException: Operation timed out
    ];
  _RequestID=69db80be-8146-46bb-a879-157fedee2f87;|
  Service com.sun.enterprise.admin.server.core.JmxConnectorLifecycle@328cbf cannot be started!:
  com.sun.appserv.server.ServerLifecycleException: Cannot bind to URL
  [rmi://169.254.161.207:8686/management/rmi-jmx-connector]:
    javax.naming.ServiceUnavailableException
    [Root exception is java.rmi.ConnectException:
      Connection refused to host: 169.254.161.207; nested exception is:
      java.net.ConnectException: Operation timed out
    ]|
#]

Thursday, October 25, 2007

Facebook Platform

Sometimes FB developers suck. Namely, when I have to add an application just to see what somebody else has done with it. It's the equivalent annoyance of having to login to comment, or to rate something on a site. I see the app on their profile, and there are options to interact with it. I try to do something, but they require me to add the app to do anything. So, of course, I decline the app and never see what I was trying to see.

It's just really frustrating that many developers force you to add the app to see anything about it, and it seems a bit backwards. I'm not going to add an app without seeing inside it first, but if I have to add it to see inside, I'll never add it. Now, this doesn't seem to be troubling many developers, as they are racking up users quite easily. Nevertheless, I'd appreciate it if developers would stop trying to build mini walled gardens inside the walled FB estate.

On a larger note, I'm still waiting for the FB app to beat all FB apps in terms of actual usefulness. Maybe I just haven't found it yet, but I really don't want gimmicky things on my profile and I think the FB platform has much better uses than trying to build up vampire points.

On a smaller note, the abundance of crappy looking FB apps being launched has reaffirmed my opinion originally derived from MySpace profiles that most people out there have absolutely zero sense of design.

Gmail IMAP woes

I was really excited yesterday when I found out that my Gmail for domains account had IMAP access. I've used Apple Mail and my Blackjack to access my Gmail accounts via POP for a while now. It's not that I have anything against the Gmail web interface, but I've just never particularly liked having to open a web browser to view my email.

POP access had its downfalls, of course, though by using "recent:username@gmail.com" as the username, I was at least able to make sure that all my various devices accessing the account were able to get new emails. When, I saw IMAP access had been added, I thought all my troubles with accessing Gmail accounts from multiple sources would be gone for good. Not quite so.

It's pretty close though, I only have one complaint: Accessing Gmail via IMAP from Apple Mail stores drafts of messages in Gmails Sent Mail folder, rather than the Drafts folder. I sent a couple emails last night, and when I woke up this morning I saw 8 copies of one of the emails in my Sent Messages folder. Before I fired off an apology to the recipient for accidentally spamming their inbox, I figured I'd do a little testing, during the course of which I confirmed that I did not actually send the email 8 times, but rather that drafts were being stored on Gmail as sent messages.

I don't know whose fault this is, Apple Mail or Gmail, but it's a little annoying. For now, I've solved the problem by unchecking the box to "Store draft messages on the server" in Apple Mail's preferences for the Gmail account. I suspect it may have something to do with folder mappings, but I don't know of a way in Apple Mail to change the folder on the server that is associated with a particular type of email, i.e. a draft.

Tuesday, October 9, 2007

SimpleCaptcha in Glassfish and Tomcat

I'm a big fan of SimpleCaptcha. It has ample configuration options and, after some tweaking, it looks good.

It's clean and easy for the user to read, but still accomplishes the purpose. I especially like that you can specify the characters to be used, thereby eliminating possibly confusing characters, such as 1 and l (that's the number one, and a lower case L).

I've used SimpleCaptcha in Fantasy Congress, running on Tomcat 5.5, and Glassfish v2. Although SimpleCaptcha is great, there were a couple quirks that I had to work around. By far the best thing about SimpleCaptcha is that the source is available, which I've needed both times to get it to work and which allows you to really change whatever you want.

1.) If you use SimpleCaptcha on a server running on some version of *nix without a GUI, you'll need to decapitate AWT. There are a lot of blogs describing how to set the system property java.awt.headless=true, but with limited success. I never got that to work and from the comments I've seen, I'm not alone. Another solution, as this blog describes, is to fake a GUI with the X window interface framebuffer server. I didn't see any reason to resort to that. My solution: I noticed that the problem was being caused in the renderWord(String word, int width, int height) method of nl.captcha.text.imp.DefaultWordRenderer at:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();

The interesting part is that these objects are created, but never referenced, so I just commented them out and it worked fine. I later discovered an article on Java Boutique explaining why this was.

2.) I didn't like the line across the text that SimpleCaptcha generated by default. I know that it increases the effectiveness of a captcha but it simply wasn't necessary for my purposes. So I cracked open the source again and removed the line by commenting out these lines in nl.captcha.obscurity.imp.WaterRiple:

//draw line over the iamge and/or text
NoiseProducer noise = (NoiseProducer)Helper.ThingFactory.loadImpl(
Helper.ThingFactory.NOICEIMP, props);
noise.makeNoise(imageDistorted, .1f, .1f, .25f, .25f);
noise.makeNoise(imageDistorted, .1f, .25f, .5f, .9f);

Note: I set cap.obscurificator to nl.captcha.obscurity.imp.WaterRiple in the servlet declaration. If you're using a different class for obscurity, you'll need to modify the relevant class.

3.) Dropping the SimpleCaptcha setup I used in Tomcat into Glassfish resulted in a dump of nonsensical text to the display. I remedied this by editing nl.captcha.servlet.CaptchaServlet and changing the doGet method from:

String capText = captchaProducer.createText();
req.getSession().setAttribute(Constants.SIMPLE_CAPCHA_SESSION_KEY, capText);

String simpleC =(String) req.getSession().getAttribute(Constants.SIMPLE_CAPCHA_SESSION_KEY);

captchaProducer.createImage(resp.getOutputStream(), capText);

to:

String capText = captchaProducer.createText();
req.getSession().setAttribute(Constants.SIMPLE_CAPCHA_SESSION_KEY, capText);

String simpleC =(String) req.getSession().getAttribute(Constants.SIMPLE_CAPCHA_SESSION_KEY);

resp.setContentType("image/jpeg");
captchaProducer.createImage(resp.getOutputStream(), capText);

It seemed logical that because the servlet is outputting an image (and in my case is mapped to /Captcha.jpg) that the content type should be an image, specifically "image/jpeg". Because adding the line resp.setContentType("image/jpeg"); solved the problem, I'm led to believe that the contentType was not being set before (though I haven't checked). However, that presents the interesting question of why SimpleCaptcha works in Tomcat without setting the contentType. I think this might have something to with the default mime types declared in the server-wide deployment descriptor in Tomcat. I'm not familiar enough with Glassfish yet to say whether it has an equivalent. I'd appreciate some insight if you have an explanation. For now, it works, and I don't have time to troubleshoot what works : )

EIP meet DWR, DWR meet EIP

My favorite AJAX framework out there is DWR as I've found it tremendously useful, developer friendly, and a breeze to implement. I originally used AJAX by writing my own non-abstractable-pseudo-framework and for the longest time I avoided AJAX frameworks because they were not extensible enough, didn't provide the functionality I needed, or just seemed to stick their grubby little paws into my code in ways I didn't desire. I finally adopted a framework when I discovered DWR, and it was my most wonderful day with AJAX. Thus, I've become quite attached to DWR.

I've toyed around with edit-in-place functionality in a few projects, but only on a small scale, and without using any 3rd party scripts. (I generally approach technologies in that manner, I like to know how it works before I start using it.) I wanted to thoroughly integrate an in-place editing system in a project I'm currently developing, and since by now I had experimented enough to know how the edit-in-place wheel rolls, I started looking around for a suitable wheel that somebody else had already built. The best I stumbled across is EIP, written by Joseph Scott (check out his blog at http://joseph.randomnetworks.com/).

EIP seemed to be a nice system, but it had one obstacle that needed to be overcome for it to be a viable option for me: it uses Prototype for AJAX, and I wanted DWR integration. Fortunately, this was relatively straight forward and there were no huge barriers to making DWR and EIP play well together. The only stumbling block was how to enable EIP to call methods opened up by DWR with variable numbers of arguments. A cool thing about javascript is that essentially every method accepts a variable number of arguments, despite what the method header (which is basically just a way to assign names to arguments) may declare. The tricky part was that somehow, EIP needed to be able to take:


dwr_params: {
p0: 0,
p1: 1
}

...

dwr_params: {
p0: 0,
p1: 1,
p2: 2
}


and then call:

DwrExposedClass.dwrExposedMethod(p0,p1,dwrCallback);
DwrExposedClass.dwrExposedMethod(p0,p1,p2,dwrCallback);

respectively. But there is no way to construct an argument list in a loop, except for to create the entire method call as a String and then use eval() to make it happen. I'm not a big fan of eval() (for reasons that may show up in a different post), and although I occasionally see it as necessary, I only resort to it after exhausting the possibility of other options.

The first thing that came to mind was currying, which (for the unfamiliar) lets you turn a method that takes multiple arguments into a method that takes one argument. This seemed like a good starting point because if I could call any DWR exposed method with only one argument, then it didn't matter how many additional arguments needed to be included. At that point I figured I could either curry an array of arguments down to one, or recursively curry until I arrived at a single argument method.

When playing around with how to implement such a solution, I discovered a much simpler way in rediscovering the apply() method of the javascript Function object. Essentially, arguments are passed as an array in javascript, evidenced by the fact that any number of arguments can be passed to any method, even one with zero declared parameters, and then referenced within the method by treating the local variable arguments as an array. Thus, at a basic level, the apply() method of a function can be used to apply an array of arguments to the function.

var args = [0,1,2,3];
DwrExposedClass.dwrExposedMethod.apply({},args);

Problem solved, I can now make any item editable and use DWR for AJAX with:

EditInPlace.makeEditable({
id: 'editableItemId',
... any other EIP params...
use_dwr: true,
dwr_method: DwrExposedClass.dwrExposedMethod,
dwr_params: { // any other data you want to pass
p0: 0,
p1: 'foo'
}
});

Feel free to use the script. You'll need DWR and Prototype.

Download the script here.