Archive for the ‘Development’ Category

New Dojo Tree Functionality

Thursday, December 18th, 2008

Dojo has just accepted code from Spider Strategies into the toolkit that allows dragging and dropping hierarchical data in a tree format “between” places in the structure!

Dojo drag and drop between

Like the folder tree we’re all familiar with, we get accustomed to dragging and dropping things from one place to another.  Many of these structures, like file folders, don’t care about the order of the contents. They can sort by things like size or name, but don’t store the order of data.

For more complex data structures, like those in CMS, the order of the data is an important part of the information. Thanks to the code we sent to Dojo, data in a tree can easily be moved from anywhere to anywhere. Previously, you could only drag and drop things into a location. Now it is possible to position things before or after other items, allowing users to intuitively manage their data.

IE6, HTTPS and MS Office

Monday, January 14th, 2008

In CMS we have a software feature that allows users to export any screen in the application as an MS Office file (Word, Excel or PowerPoint). Recently we found out this feature didn’t work very well for some Internet Explorer 6 users, so we had to tweak our implementation a bit.

The basic technique we use to create MS Office files is to take our existing HTML screens and instruct the user’s PC to open the files in MS Office. In the past, we told the PC to open the file in MS Office by setting the MIME type for the appropriate file type (e.g. application/ms-word for Microsoft Word). We found a technique that works better with IE6, HTTPS and MS Office is to set the Content-Type to application/x-download and set the Content-Disposition to attachment; filename=(filename here).

We learned of this technique by reading this article from ONJava. The article is written assuming a Java programming environment, but setting HTTP headers isn’t really specific to Java, so the basic technique should be applicable to any web environment. If you’ve been wrestling with IE6, HTTPS and MS Office, I hope this article is of some help to you.

Eliminating Session Timeouts

Monday, December 10th, 2007

This weekend, my mother told me about the trouble she had booking train tickets from Washington, DC to New York using Amtrak’s online reservation system. She had to make the reservation three times because the first two times she took too long and the website timed out. As I listened to my mother’s story, I felt proud because I knew she wouldn’t have had the same problem if Spider Strategies wrote Amtrak’s reservation system.

The problem my mother experienced is a common one for web applications. Most web applications operate using the notion of a session which is used to store information about the user that is logged on and the activities he or she is performing in the application. The trouble is that the session is periodically erased to save memory on the server. When the session is erased, the user’s work is lost. In my mother’s case, her reservation was erased.

In CMS, we avoid this problem by using dojo to fire off a request in the background every few minutes. These requests prevent a user’s session from expiring as long as that user keeps his or her browser open. If the user closes his or her browser, the session will still be cleaned up so that the server doesn’t fill up with old, unused sessions.

In addition to benefiting the usability of the application, this technique can also decrease the amount of memory devoted to sessions on the server. Typically a web application will have a session timeout of 30 to 60 minutes. With this technique the timeout can be decreased to a smaller number (e.g. every 5 minutes) as long as background request are fired faster than sessions are expired (e.g. every 2 minutes). Faster session timeouts means sessions are in memory for less time means less total memory will be needed for sessions.

If you’re a software developer, I hope you find this technique useful and apply it to your application. If you’re a user of CMS, you can rest easy knowing this technique is already in place so that you don’t need to worry about losing your work.

Set Textarea Maxlength with JavaScript Intrinsic Events

Wednesday, September 12th, 2007

With the wonderful implementations of AJAX, many people (myself included) tend to look first within libraries like Dojo when trying to implement a client-side solution. While this is generally a good approach, one thing that some developers tend to forget is the intrinsic events like onkeypress, onmouseout, etc.

A good example is the textarea tag. It doesn’t have any limit on the number of characters like the input tag, so it’s a great candidate for a simple JavaScript function to duplicate the maxlength functionality. The initial instinct when coding something to handle this is to check the length of the field and return a false if it’s reached the limit. This does indeed limit the size, but there’s one problem; backspace and delete trigger onkeypress. As a result, if you’re at the limit and try to delete characters, it returns false and nothing happens! Instead, I find the best solution is to truncate the field if the size is reached. For example, to limit a textarea to 255 characters:

<textarea id="maxdemo" rows="20" cols="80"
 onkeypress="maxlength(this, 255);"></textarea>
<script type="text/javascript">
<!--
/**
 * Determines if a field is exceeding the maximum size
 * and truncates the string if it is over the limit.
 */
function maxlength(field, size) {
    if (field.value.length > size) {
        field.value = field.value.substring(0, size);
    }
}
// -->
</script>

Using Chainsaw for Log Viewing

Wednesday, July 11th, 2007

If you’re a programmer, no doubt you’ve the occasional, if not constant, need to read the logging statements generated by your application. I know that I’m constantly reading log output, which is why I’m thankful for a tool like Chainsaw v2. Despite having a not-yet-complete feel to it, Chainsaw has become an invaluable tool in my programming environment. Recently I discovered a hint that I should have known a long time ago, which increases its usability tenfold.

Configuring log4j and Chainsaw is a breeze. Once you’ve downloaded it, configure your log4j to use a SocketAppender. Here’s a snippet from my own log4j.properties:

log4j.logger.com.spider=DEBUG, CHAIN
log4j.appender.CHAIN=org.apache.log4j.net.SocketAppender
log4j.appender.CHAIN.remoteHost=localhost
log4j.appender.CHAIN.port=4238
log4j.appender.CHAIN.locationInfo=false

Here I’ve set up an appender named ‘CHAIN’ on port 4238. Its running on the same machine as my application (hence ‘localhost’), but it could just as easily point to a Chainsaw instance on another computer.

Next, add a “SocketReciever” within Chainsaw. The important property is ‘port’, which must correspond the value in your log4j.properties:

Chainsaw receiver configuration

That’s it. Your log messages should go to chainsaw, where you can navigate and search with ease. Here are a couple tips for Chainsaw use, including my own recent discovery:

  • Create an XML receiver file and configure Chainsaw to use it upon startup. This way you won’t have to redefine the receiver each time. See “View example Receiver configuration” on Chainsaw’s welcome tab.
  • Use the ‘Refine Focus’ field when you need to get at specific log statement or logger. You can use the “=~” operand for partial matches. For example, if you want to display only log messages from the Logger named “ServiceClassWithLotsOfLogging”, you can type “Logger ~= LotsOf” in refine focus. This same technique can be used for messages as well: “msg ~= some logging text”. Wish I had known this a long time ago!

If you’ve multiple monitors (or computers), I think you’ll find that 2nd monitor makes a great home for Chainsaw.

Happy coding!

~ Keith

Easily convert and copy information using Morph

Monday, May 21st, 2007

Ever since I first got started programming and was exposed to different computer languages I’ve been annoyed at how difficult it is to convert information from one type to another. Not only does every language have its own way of doing this, often even within the same language there are multiple different methods that need to be learned to do conversions properly. I can’t offer a solution for every programming language, but I can offer a solution for Java: the Morph framework. The main goal of Morph is to make it really easy to take information in one format and make it available in another format. I am including some examples along with this article to show how easy it is to do all sorts of conversions with Morph. You can get a full list of the conversions that come out of the box here.

Morph.convert allows you to convert an object from one type to another. Here are some examples:


Integer three = new Integer(3);
// code without Morph
String string = new Integer(three);
// or (without using Morph)
string = "" + three;
// code using Morph
String string = Morph.convertToString(three);


String three = "3";
// code without Morph
Integer integer = new Integer(three);
// code using Morph
Integer integer = Morph.convertToIntegerObject(three);


String three = "3";
// code without Morph
int i= new Integer(three).intValue();
// or (without using Morph)
int i = Integer.parseInt(3);
// code using Morph
int i = Morph.convertToInt(three);

Morph.copy allows information from one object to be copied to another object. The object to which information is copied may even be of a different type than the source object. A great example of when you need to do this type of thing is when you need the data in an HttpServletRequest to be available to lower tiers in your application but you don’t want to tie your entire application to the servlet API. For example, let’s say you are trying to get your data prepared for a method with a signature IServiceInterface.service(Map data):


// without Morph
Map data = new HashMap();
for (Enumeration e=request.getParameterNames(); e.hasNext(); ) {
String param = (String) e.next();
data.put(param, request.getParameter(param));
}
// with Morph
Map data = new HashMap();
Morph.copy(data, request);
// actually with this particular example could also do
Map data = (Map) Morph.convert(Map.class, request);

You Had Me at Softlinks

Wednesday, April 25th, 2007

Last week Ubuntu 7.04 was released. I thought I’d contribute to the hype by talking about why I love Linux. Before I do though, I just want to say I am not a zealot. I believe in the right tool for the right job — and I’m even forgiving of not-quite-so-right-but-comfortable tool for the right job. I use Windows all the time, but when it comes to development, I prefer Linux hands down.

I’m relatively new to the party. A couple years ago I had been hired at a Linux-only development shop. Fortunately, even two years ago, it was relatively easy to transition from Windows to Linux. Which isn’t to say there isn’t much to learn — but even with a shallow knowledge of Linux it was easy for me to get around. Like many programmers though, I need more than shallow knowledge, and began delving into the OS’s nuances.

Its through this exploration that I began to appreciate Linux. These short, terse commands I entered at the command-line — these aren’t just tools, they are the collective wisdom of the ancients. My handy bash-scripting reference talks about the evolution of the “echo” command for two pages! Clearly, most of the basic concepts of Linux have been honed and polished for two decades, and truly I feel as if I’m standing on the shoulder of giants with each “sed” or “cat” invocation.

Granted, you don’t need to know how a car works to drive it, and Linux was the same for me. Indeed, I had been piping commands to each other for years before appreciating the holy trifecta of stdout, stdin, and stderr.

For those who want to get their feet wet, you can run Ubuntu entirely from CD. There are even instructions for running Ubuntu as a virtual machine using VMWare. But doing a full-on, dual-boot installation isn’t difficult (though disk partitioning is always harrowing for me), and I’d encourage anyone to give it a shot.

Here are some reasons, in no particular order, why I prefer to do development work on Linux:

  • Command-line Console. Slowly I’m becoming a command-line ninja, and find it much easier to navigate my filesystem, and perform other operations, by typing.
  • Warm fuzzies when using open source software.
  • Softlinks. Besides being a very handy way to organize my filesystem, it never fails to make me giggle when I compare it to window’s *.lnk (“Shortcut to…”) equivalent.
  • Appropriate Verbosity. Most unix commands (cp, mv, chmod) don’t provide any output upon completion. Type “man cp” though, and you have a couple pages of describing the simple command’s functionality.
  • Easy Package installation. How do I install MySQL? “sudo apt-get install mysql”
  • Multiple Desktops. One for my mail reader, one for log-viewing (via Chainsaw), and one for my IDE.

Undoubtedly there are dozens of other reasons, and I look forward to finding even more.

Networking with Virtual PC 2007

Sunday, April 15th, 2007

I wrote a post last month about how impressed I was with Virtual PC 2007 and how it has changed the way I work. This is a follow-up about a networking problem that I didn’t discover until it was almost too late, as well as how to fix it.

I decided to install Vista Business on my laptop a few months ago, and aside from a few application compatibility issues, I’ve been pretty happy with it so far. One of the main problems is that Oracle 9i doesn’t work with Vista, and that’s a database we need to develop against. So, I fired up my Windows XP virtual machine, installed Oracle, and then connected to Oracle on the virtual machine just like I would if it were installed on another server. Everything was working smoothly… or so I thought.

A little background: The default networking option for your virtual PC is “Shared Networking.” This allows the virtual PC to share your host PC’s internet connection, but doesn’t allow the host PC to talk to the virtual PC. So, instead of using shared networking, I set the virtual machine to directly use my wireless network. Both the host PC and the virtual PC got separate IP addresses from the router, and could therefore talk to each other. The only thing I didn’t think about was that the second my laptop lost its connection to my router, I couldn’t communicate with the virtual PC.

So, there I was, minutes before a demo with an important client, and my application server couldn’t talk to my database, even though they were both on the same laptop.

The solution was relatively simple, but for some reason the information was really hard to find. First install Microsoft’s Loopback Adapter on the host PC, and then tell the virtual PC to use it for its network access. The process is explained very well here.

Version Labeling and Continuous Frustration

Wednesday, April 11th, 2007

I approach continuous integration (CI) servers in the same way I do my IDE — as a tool of convenience for performing tasks I could choose to perform manually. I would no more have a build system reliant upon a specific CI server than I would write code that was only recognized by a specific IDE. Thankfully the CI servers with which I’ve worked conform to my philosophy. They do not seek to replace your build system as much as provide much needed automation. There is one area, though, where I feel CI servers violate this ideal, and that’s creating a unique build/version label.

Out-of-the-box, most CI servers provide a simple numbering scheme in order to produce a unique label for each build. Generating a build/version label is a task I prefer to happen within the build itself, so that the build is truly self-contained. Take our builds, for example. I’ve made use of the ant task buildnumber, so, upon a build, ant reads and increments a build-number property file and appends it to the project’s “base version,” the result being a label like “1.9.0.6″, where “6″ would be the build number. I imagine this is a common scenerio — indeed its why the <buildnumber> ant task exists. Once I launch an official build via command-line, label generation happens automatically, and the repository is tagged “Build 1.9.0.6″.

Introduce the CI server, though, and suddenly I’m having to jump through hoops to accommodate this setup. At the crux of the problem is this: from the CI server’s perspective, a build starts upon checkout or update of a project, and therefore wants to know the build label prior to actually running the build. That’s putting the cart before the horse, in my opinion, although I do understand the reasoning. Should access to the repository fail, for example, the CI server is able to report “1.9.0.6 Build failed due to VCS unavailability”.

What I’ve done is create a small script whose sole duty is to fetch the next build label for the CI server — fortunately the CI servers with which I’ve worked allow for pre-build script execution in some manner or another. With CruiseControl, I use an “antbootstrapper” to invoke a small ant build named “get-next-version.xml”. CruiseControl passes the value generated from that to the official build, so ant is invoked like so: “ant package -Dbuild.label=1.9.0.6″.

However, my work isn’t done. I still must ensure that my build-number property file is accurate, even if the build.label is being provided instead of being generated. So, in addition to configuring CruiseControl in the manner described, I also must have my build.xml extract the build number from the passed label (in this case, “6″), and update the build-number file appropriately.

Granted, I imagine most folks don’t rely on ant to generate build numbers, and therefore the CI server provided functionality is a convenient mechanism. The minority of us who do, though, ought to be able to supply build labels to the server in an easier fashion.

Not upgraing to Internet Explorer 7? Why not?!?!

Tuesday, March 27th, 2007

Whenever I hear about a government agency indefinitely postponing their upgrade to IE7, I cringe. We web developers plan on supporting IE6 for at least the foreseeable future, but any setback that delays the natural browser upgrade progress always stings a little. Yes, under the hood IE6 can do most of the stuff that IE7 can, but it does it badly and incompletely.

I listened to Chris Wilson’s talk (he’s IE’s program manager) at the Ajax Experience conference in Boston and he brought up a really good point. IE6 was a great browser when it was released in 2001. Since then the web has changed dramatically. Things are being done with DOM and JavaScript now that just weren’t on our radars six years ago.

Because of that, IE6 is seriously crippled for modern web apps. Aside from its incomplete support for CSS, IE6’s main problem is the execution time and garbage collection in its JavaScript engine. Recent tests show just how dismal the performance is.

I guess this will just be another challenge that we’ll have to work around, but it sure would be nice to hear that larger companies and government organizations are actively planning a browser upgrade.