<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5334737</id><updated>2011-04-21T13:53:28.068-07:00</updated><title type='text'>The recalcitrant engineer</title><subtitle type='html'>Main Entry: reï¿½?ï¿½calï¿½?ï¿½ciï¿½?ï¿½trant&lt;br&gt;
Pronunciation: -tr&amp;nt&lt;br&gt;
Function: adjective&lt;br&gt;
Etymology: Late Latin recalcitrant-, recalcitrans, present participle of recalcitrare to be stubbornly disobedient, from Latin, to kick back, from re- + calcitrare to kick, from calc-, calx heel&lt;br&gt;
Date: 1843&lt;br&gt;
1 : obstinately defiant of authority or restraint</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://burnthacker.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>52</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5334737.post-106808437004441386</id><published>2003-11-05T18:06:00.000-08:00</published><updated>2003-11-05T18:07:11.206-08:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;301: This blog has moved permanantly&lt;/h3&gt;
Please see &lt;a href="http://www.burnthacker.com/"&gt;http://www.burnthacker.com/&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106808437004441386?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106808437004441386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106808437004441386'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_11_01_archive.html#106808437004441386' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106799256190621889</id><published>2003-11-04T16:36:00.000-08:00</published><updated>2003-11-04T16:36:56.960-08:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;The "too complex" rule: if you can't figure it out in a day or two, it shouldn't be done&lt;/h3&gt;
There are a few things that have been bouncing around in my head the last few days with regard to software.  The first is an old adage, from I think Brian Kernighan, that says (roughly) "you must be twice as smart to debug code than you need to be to write it". If you use all your cleverness to write the code, then by definition you aren't smart enough to debug it.  The other thing is a quote from Albert Einstein that (paraphrased) is "If you really understand something, you should be able to explain it to your mother."
&lt;p&gt;
I've been thinking about this a lot, both due to the inherent conceptual complexity of a web framework I've been working with and the difficulty trying to explain it. The other thing that's been bouncing around is trying to figure out a really complex web UI if you're a backend java person.
&lt;p&gt;
Real world problems are hard. Really really hard. A commercial webapp that needs to &lt;i&gt;actually&lt;/i&gt; scale to thousands of users and cluster, that has hundreds of pages and probably 50-100 tables is a beast. Super complex. Not necessarily in any part, but as a whole, it's a freakin' monster.  When you try and build a framework that can be a platform for such a thing, you're up against a very big, very tall cliff.  There's almost this tradeoff: by the time you get your framework complete enough to actually work for the app, it's going to be so complex in its details and behavior that it won't be understandable without a huge amount of ramp up time. There's a lot to be said for good theoretical backing, orthogonality, good general design, etc, but that won't make things necessarily crystal clear. I know that ultimately, if its a good design, it will have that clarity, but I am wondering if anyone is smart enough to do it, or if its just going to take a lot more time and a lot more baby steps before we can get there.
&lt;p&gt;
The other half of this is complex user interfaces. I'm currently working with a UI where developers have implemented extremely clever JavaScript, which, when it explodes, blows the minds of everyone expect perhaps 1 or 2 people.  Such a thing is really not workable, as the long term maintenance is not going to be either cheap or possible, depending on your perspective.  
&lt;p&gt;
I'm starting to wonder if the only thing that actually works is really, really dumb code. Not necessarily bad, but forgoing a lot of things like complex user interfaces, skinnability (micrositing), massive performance throughput, etc, in order to just get something that a normal human can understand and maintain. It's depressing that microsoft access is looking like a good answer for business applications.

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106799256190621889?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106799256190621889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106799256190621889'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_11_01_archive.html#106799256190621889' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106727685016327663</id><published>2003-10-27T09:47:00.000-08:00</published><updated>2003-10-27T09:47:29.216-08:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Naming Conventions: Language versus Technology Holy Wars&lt;/h3&gt;
One thing I've been thinking about a lot is poor design decisions, and how they cripple software.  I'm probably going to write a good bit about this over the coming week or so as I serialize out my musings and try and extract something worthwhile to read. There's a lot of angles on this, and I'll try and write down all the things that have been floating around in my head on them.
&lt;p&gt;
Today, we see a lot of API and framework designs on top of existing languages, rather than a lot of new language designs.  The main driver here is install base on the lanaguage side, but as &lt;a href="http://st-www.cs.uiuc.edu/users/johnson/"&gt;Ralph Johnson&lt;/a&gt; told me several years back, APIs and frameworks themselves constitute a meta language, and are every bit as hard to design as the language itself. Sometimes it seems like this point is lost on the people that are doing the actual design.
&lt;p&gt;
Anyway, what I was thinking about is people that are doing APIs for a specific technology that exists in multiple languages.  The classic (old) example of this is CORBA: When you build your IDL (interface description), it defines your object API in every language (with a single naming convention). The notable exception to this is in Smalltalk, where the language binding for CORBA actually fixes the naming conventions from "foo_bar" to "fooBar" at IDL compile time so the code you write still LOOKS like Smalltalk.  In my opinion, this is another case where the Smalltalkers made the absolute correct decision.
&lt;p&gt;
A modern example of this is the APIs for acessing all the various X* technologies (DOM, XSLT, XPath, ...) and their language bindings.  If you use the W3C standard APIs for Java (TRAX, JAXB, etc), you end up using these weird &lt;tt&gt;NodeList&lt;/tt&gt; objects and other things that make your Java code awkward, ugly and difficult to maintain. However, if you use something designed for Java, like &lt;a href="http://www.dom4j.org"&gt;dom4j&lt;/a&gt;, you end up with code that looks, reads and feels like Java. And, as such, is amazingly cleaner and easier to maintain.
&lt;p&gt;
The disconnect here, as I see it, is the hubris of the people driving the technology, and their focus on a single language (usually C++). The assumption is that the technology will be far bigger than any single language, so the goal is to have code in the various languages look basically similar. This makes it so developers can move between languages and immediately be able to work on code that is driven by technology X.
&lt;p&gt;
I think this highly misguided, and misses the point of how real programmers work. In the real world, Java programmers write Java code. It has a set of conventions that are well defined, and the more Java looks like Java, the easier it is for people to come in and work on it. I will probably never work on DOM trees in C++, and if I did, I would have to go back and read the documentation anyway to find out all the language specific nuances of the APIs, so this convoluated API isn't buying me anything. 
&lt;p&gt;
Having missed this point, many standards boards (such as the W3C) end up burdening other languages with these funky APIs, forcing bifurcation and duplication of effort as people work to reinvent what the API should have been in the first place, after the standard implementation is complete.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106727685016327663?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106727685016327663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106727685016327663'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106727685016327663' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106703145842723071</id><published>2003-10-24T14:37:00.000-07:00</published><updated>2003-10-24T14:39:53.780-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;How can is it possible that BEA's JMS is so slow?&lt;/h3&gt;
A while back, I wrote a large amount of code that used the JMS implementation in Weblogic 6.1 for internal messaging. The system was a user interactive system, where timely deliveries of messages were critical for user display. Ideally, you wanted the user input to trigger a message, have the system act upon it, and have the user interface update with the result in milliseconds. What I expected when I began was that things would run at or near method invocation speeds, as long as I was in the same JVM.
&lt;p&gt;
The result I found was that things would stay magically "in the queue" for 3-5 seconds (that's seconds, not milliseconds) before the response was heard, each time a write was done. If you had to do a JMS write, then a JMS read to service a single page request, the result was an additional 6-10 seconds PER PAGE, on top of your normal computation and page rendering time.
&lt;p&gt;
You can say that a lot of things, such as removing the filters (I was using filters of moderate complexity) might have helped. You can say "Gee, everybody knows Weblogic JMS is slow."  I, honestly, don't really care. The Weblogic JMS server is basically unusable for user interactive applications. I had to turn around and write my own internal messaging system, developing my own filter mechanism, etc. But once I was done, it ran at the speeds that I expected, and is in heavy production use today.
&lt;p&gt;
The honest truth behind it is that JMS has a lot of guarantees on the message delivery. In fact, it makes TCP seem like a total weakling in comparison. And yes, doing a lot of these things probably requires a lot of effort on the server's part. What I think BEA is honestly missing is the ability to relax what the server guarantees you in terms of reliability in order to recover the speed you need.  Most people and most applications honestly don't require all the fancy pants stuff that JMS offers, at least most of the time. But for Weblogic to really make good on some fraction of JMS's potential is going to require it to become much more flexible and lightweight. It's a great mechanism for scaling computations, if it was fast enough to deploy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106703145842723071?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106703145842723071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106703145842723071'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106703145842723071' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106702041902936677</id><published>2003-10-24T11:33:00.000-07:00</published><updated>2003-10-24T11:34:13.810-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;TimeZones: It's not just a java problem&lt;/h3&gt;
I was sent &lt;a href="http://blogs.gotdotnet.com/raymondc/PermaLink.aspx/0e41ef9c-fa0b-4d09-a942-06e3d1a86961"&gt;this link&lt;/a&gt; this morning about one man's pain with daylight savings handling under Win32. If you read this, it's basically a dump on how the internals of the time zone computation mechanisms in windows are as weird and flaky as Java when it comes to DST handling.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106702041902936677?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106702041902936677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106702041902936677'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106702041902936677' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106686735912986259</id><published>2003-10-22T17:02:00.000-07:00</published><updated>2003-10-22T17:02:39.226-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Who thought of the J2EE configuration mechanisms?&lt;/h3&gt;
I think I'm something of a rare bird, in a way: I've worked as a system administrator for large, enterprise systems, and I've worked as the architect developing those systems. Sometimes it seems like the distance between the two is a chasm. The disconnect between the people that write software and the people that install and maintain it is amazing.
&lt;p&gt;
Case in point: Configuration files. What a system administrator wants is a flat file that lives somewhere (preferrably in /etc or /var somewhere) that clearly and concisely allows them to tune all the knobs of the system. This thing should be reloadable either via a SIGHUP, or, at worst, via a JVM restart. Either way, the file is readily accessible and easily changed.
&lt;p&gt;
J2EE actually puts the config files (deployment descriptors) INSIDE the application BINARY. I don't care that war and ear files are "just zip files". I, as a system administrator, do not want to disassemble the application to find the configuration file.  Honestly, as a developer, I won't even manually attempt to take a war apart and then put it back together, because I almost always break it.
&lt;p&gt;
When I get in the config file,  I want it to make logical sense to someone that doesn't have the source code in front of them. Don't mix the config options in with the nuts &amp; bolts of what makes the application run (such as the servlet mappings).
&lt;p&gt;
This frustration has actually led me to abandon the j2ee config mechanisms entirely and implement my own system that is actually accessible to system administrators, doesn't require a GUI, and automatically detects and reloads itself.  The response from the people using the applications that I've developed have been amazingly more positive now that they can see config options without trying to disassemble and decipher the deployment descriptor.
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106686735912986259?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106686735912986259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106686735912986259'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106686735912986259' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106635736181984229</id><published>2003-10-16T19:22:00.000-07:00</published><updated>2003-10-16T19:23:37.720-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Taglibs and internal state&lt;/h3&gt;
So I just discovered the hard way that you can't safely store internal state in a taglib.
&lt;p&gt;
My current application sports a fairly large taglib set that lets you do many powerful things, such as iteration, value display, automatic form element rendering and lots more. The thing I found is that if you have tags that do things like looping, when they nest, many appservers reuse instances of the &lt;tt&gt;Tag&lt;/tt&gt; class for the nested calls to the tag. The problem here is when the tag saves instance variables: each nested invocation clobbers the state of the parent. If you're doing something like looping tags, when the innermost loop completes, the whole nested iteration completes because the state about being "at the end" of the loop just got clobbered by the inner most tag.
&lt;p&gt;
Instead, you have to push the state that you stored in the taglib member variables as attributes in the &lt;tt&gt;pageContext&lt;/tt&gt;, which are scoped by the "depth" of the nesting of the tags.  The depth of the nesting has to be computed by incrementing on &lt;tt&gt;doStartTag&lt;/tt&gt; and decrementing right before you return &lt;tt&gt;SKIP_BODY&lt;/tt&gt;. This "stack depth" gives each nesting a namespace in which it can declare its context variables and save its state.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106635736181984229?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106635736181984229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106635736181984229'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106635736181984229' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106617047747778383</id><published>2003-10-14T15:27:00.000-07:00</published><updated>2003-10-14T16:22:33.530-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Time Zone Representations &amp; Software&lt;/h3&gt;
I've built a few systems in java that required doing lots of TimeZone conversions for end user date display.  It's a pretty standard problem for any software that has to work outside of a single site, and generally falls into the i18n/l10n bucket of problems that have to be solved when you're building the app. Which, in my experience, means it rarely gets solved well.
&lt;p&gt;
I'm not going to start down the standard path of complaining about the implementation of &lt;tt&gt;java.util.Date&lt;/tt&gt;; it's safe to say that horse is dead. What I did find fascinating, though, is just how complex time zones actually are.  The first thing to realize is the timezone list that the JVM ships with is totally inadequate. It changes depending on the platform, and is fairly incomplete. You can't rely on it to build a real application. This generally means you have to make your own subclass of &lt;tt&gt;java.util.TimeZone&lt;/tt&gt; which you then populate from a database (or something) that you ship with the product.
&lt;p&gt;
When you go to implement your own subclass of &lt;tt&gt;java.util.TimeZone&lt;/tt&gt;, you'll find you need to provide a lot of values to the constructor of &lt;tt&gt;SimpleTimeZone&lt;/tt&gt; to create the time zone, such as the day of the week that daylight savings time starts, the day of the week in the month it ends, etc. I still find these confusing to some extent, but thankfully I was provided with a list of the data so I just had to implement it.
&lt;p&gt;
The tricky part is: how do you actually refer to a time zone? The typical thing I've seen is "GMT-6" or something like that. What you find out when you delve into the details is, "GMT-6" is highly imprecise. All it says is "-6 hours from GMT", which maps to an actual SET of time zones.  For -6 hours offset, you could have a set of different timezones with different DST rules. 
&lt;p&gt;
The next natural question is: What is this set and where can I get the canonical list? The short answer is: It doesn't really exist. The crux of the problem is, time zones are a political creation.  If you look, there is no ISO standard for timezone names (at least that I could find). These things are highly fluid; they change at the whim of legislatures and are not well defined to start with. Quite honestly, it's a complete mess. 
&lt;p&gt;
If you look in &lt;tt&gt;/usr/share/zoneinfo&lt;/tt&gt; on a UNIX machine, you'll see the "state of the art." One of the things that poking around at this data showed me is that timezones have a "historical" dimension, which is 100 times worse. This adds the problem of "from 1971-1979, daylight savings time started on the last Thursday of the month." If you're curious about what doing it "right" entails, read the manpage for &lt;tt&gt;tic&lt;/tt&gt;, which is the &lt;tt&gt;timezone info compiler&lt;/tt&gt;
&lt;p&gt;
The best answer I found to all of this is to flatten it into a namespace you define and pick the timezones you need to support from your userbase. Also, discard the historical dimension; not only is it confusing, Java doesn't support it. 
&lt;p&gt;
The naming convention that I found most useful for naming timezones is "Country/City" like "America/Los_Angeles" because it actually maps to the political entity that created the timezone, and then show that string to the user to let them chose their time zone.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106617047747778383?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106617047747778383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106617047747778383'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106617047747778383' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106606838372287189</id><published>2003-10-13T11:06:00.000-07:00</published><updated>2003-10-13T11:06:40.263-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Key Conversion Step Through: The Mechanics&lt;/h3&gt;
I had to actually finish the job of getting the PVK file (mentioned below) into a JKS keystore today, and it was non trivial. I did not mean to mislead my loyal readers by portraying the PVK to PEM conversion as the last step in the process, as it most certainly is not.
&lt;p&gt;
The whole story is: The PVK format is known as "Microsoft Authenticode" format for a key, and is commonly used by COM (read: VB) developers for signing controls. For actually doing the signing, there's actually two parts that you need: The PVK file, containing the private key, and the SPC file, which is the actual certificate. Both of these must be used together and imported into Windows in order to export to a neutral format so they can be used. The SPC file is downloaded from Thawte after they complete the signing process.
&lt;p&gt;
The tool you need for the import is &lt;a href="http://msdn.microsoft.com/vba/technical/pvk.asp"&gt;here&lt;/a&gt;, and it's called &lt;tt&gt;pvkimprt&lt;/tt&gt;. Once you get that, you follow the directions, do the import and then (interestingly enough) the key shows up in Internet Explorer. In IE, choose &lt;tt&gt;Tools -&gt; Internet Options -&gt; Content -&gt; Certificates...&lt;/tt&gt; and you'll see your key under the &lt;tt&gt;Personal&lt;/tt&gt; tab. 
&lt;p&gt;
The thing to know about this next step in the process is you need to export the certificate with the private key, and the only way you can do that here is in the &lt;tt&gt;PKCS12&lt;/tt&gt; format (a well supported standard) , which the JVM (&gt;= 1.3.1) can read correctly. Select &lt;tt&gt;Export...&lt;/tt&gt;. Make sure you export the private key, accept the defaults and safe the cert to a &lt;tt&gt;PFX&lt;/tt&gt; file somewhere.
&lt;p&gt;
Once you have a &lt;tt&gt;PKX&lt;/tt&gt; file, you simply need to convert that to &lt;tt&gt;JKS&lt;/tt&gt; format for maximum ease of use with &lt;tt&gt;jarsign&lt;/tt&gt;. As usual, Sun displayed plenty of foresight and doesn't provide a tool to do this. &lt;a href="http://home.istar.ca/~neutron/Thawte/"&gt;Thankfully, someone has done the legwork for us&lt;/a&gt;. They go into much more detail about how to use the key in other environments, but for our purposes, all you need is &lt;a href="http://mail.further.com/~kris/KeystoreMove.java"&gt;KeystoreMove&lt;/a&gt; (which I have mirrored, but is available from the original page above as well). Compile this, and then run:&lt;br&gt;
&lt;font size="-1"&gt;
&lt;tt&gt;java -cp . KeystoreMove pkcs12 yourkey.pfx yourpass jks yourkey.jks yourjkspass&lt;/tt&gt;
&lt;/font&gt;
Which then leaves you with yourkey.jks that you can use with jarsign.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106606838372287189?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106606838372287189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106606838372287189'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106606838372287189' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106572765717314339</id><published>2003-10-09T12:27:00.000-07:00</published><updated>2003-10-09T12:27:36.903-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;PVK, PEM and JKS: Code signing key conversions&lt;/h3&gt;
Ok: So if you go to thawte and buy a universal code signing key, you've just spent a very small amount of money to be able to run trusted code on pretty much everything everywhere. It's a great deal, but I won't comment on the security implications. It scares me silly. Suffice it to say, you can sign microsoft code (COM controls), java jars and anything else you need.
&lt;p&gt;
Anyway, the key you get is in "PVK" format, which is msft proprietary. Don't despair, this CAN be used for Java. What you are trying to do is get it into JKS format for ease of use with the JVM. What you need to do is first convert the "PVK" format to "PEM" (which is a standard) and then convert the "PEM" file to "JKS" using &lt;tt&gt;keytool&lt;/tt&gt;.
&lt;p&gt;
I'm not going to explain how to use &lt;tt&gt;keytool&lt;/tt&gt; here, as that's a lot of work. What I will say is the missing link is how to get the damn "PVK" file into "PEM". Thankfully &lt;a href="http://www.drh-consultancy.demon.co.uk/pvk.html"&gt;this kind person&lt;/a&gt; reverse engineered the key store format and provides a downloadable utility to get the PVK file into PEM. From there, you can use BouncyCastle JCE (see below) to convert the PEM file into JKS with keytool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106572765717314339?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106572765717314339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106572765717314339'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106572765717314339' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106572626360428335</id><published>2003-10-09T12:04:00.000-07:00</published><updated>2003-10-09T12:06:00.060-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Keystores, keytool, JCE and the state of Java encryption&lt;/h3&gt;
Not everyone has had to do this, but when you deal with signing jars and lots of crypto in java, things can very quickly get very complex. And you also quickly discover that most of the crypto stuff that's out there is actually broken and flaky. Most important is that the default JCE that Sun ships with the VM is anemic and buggy.  In particular, before 1.4, the &lt;tt&gt;keytool&lt;/tt&gt; that you use to manipulate keystores that comes with the JVM could only manipulate a custom proprietary keystore format (jks) unless you swapped the JCE provider. The problem is, none of the key signing agencies actually deal with anything but standards like PEM encoded keystores.
&lt;p&gt;
But what is one to do? RSA charges a truckload for their BSAFE libraries, and having them in your app doesn't do much for you except to be able to say "Yep, there's BSAFE in the classpath." OpenSSL (the de facto C standard) can be used for some things like doing command line operations and key generation, but it doesn't do you any good from Java. 
&lt;p&gt;
The best thing I've managed to find is &lt;a href="http://www.bouncycastle.org"&gt;The Legion of the Bouncy Castle&lt;/a&gt;. They make a great JCE provider that actually reads and writes standard formats, along with a lot of other great crypto tools, like OpenPGP compliant encryption, etc. And it's all BSD license, it works and it's a full cleanroom implementation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106572626360428335?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106572626360428335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106572626360428335'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106572626360428335' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106572121764367193</id><published>2003-10-09T10:48:00.000-07:00</published><updated>2003-10-09T10:48:22.870-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Self Documenting Builds &amp; Ant&lt;/h3&gt;
As I've been thinking more and more about ant, I've rememberd a lot more tricks that I've found useful. I didn't intend to trickle all this out over a week or so, but I suppose having several articles about ant is more interesting than one gigantic huge article.
&lt;p&gt;
There are really two ways to approach telling your users about how to run the build: send them a big document that describes the build, or just have the build itself guide them. In my experience, nobody reads documentation anyway, and it gets rapidly out of date.  So it's better to just use what ant provides. In this case, your biggest boost is setting the &lt;tt&gt;description&lt;/tt&gt; on each &lt;tt&gt;task&lt;/tt&gt;.  This is done like:&lt;br&gt;
&lt;tt&gt;
&amp;lt;task name="webapp" description="Build the main deployment ready web application. This makes the war file."&amp;gt;&lt;br&gt;
....
&amp;lt;/task&amp;gt;&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
Once you do this, everyone can see what the build targets do with a simple call of:
&lt;br&gt;
&lt;tt&gt;ant -projecthelp&lt;/tt&gt;
&lt;br&gt;
Which shows you all the targets defined, and their descriptions. 
&lt;p&gt;
Also, It is frequent that builds need things like Weblogic to be on the host to be able to actually build the project. Usually, this is done by requiring a user to have a local properties file that defines paths for their machine so that the build can get running.  The powerful thing here is ant's &lt;tt&gt;unless&lt;/tt&gt; and &lt;tt&gt;if&lt;/tt&gt; attributes on tasks. 
&lt;p&gt;
The easiest way to do this is to do something make a task like:
&lt;br&gt;
&lt;tt&gt;
&amp;lt;task name="weblogic.config.check" unless="weblogic.home"&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;fail message="Please define weblogic.home in your local.properties file to point to your weblogic server home"/&amp;gt;&lt;br&gt;
&amp;lt;/task&amp;gt;&lt;br&gt;
&lt;br&gt;
&amp;lt;task name="compile" depends="weblogic.config.check"&amp;gt;&lt;br&gt;
....&lt;br&gt;
&amp;lt;/task&amp;gt;&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
This way, you know that unless the user defines thier &lt;tt&gt;weblogic.home&lt;/tt&gt;, the build will fail, and the build will tell them exactly what they need to do to make the build run. This tends to reduce ramp-up time a lot for new hires.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106572121764367193?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106572121764367193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106572121764367193'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106572121764367193' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106562972942667384</id><published>2003-10-08T09:15:00.000-07:00</published><updated>2003-10-08T09:17:21.713-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;One more ant tip: paths and multiple build scripts&lt;/h3&gt;
The reason I wrote the chunk of ant advice below originally was I was trying to remember all the stuff I had learned about advanced usage of ant that was seriously difficult to figure out to pass it on to someone. The problem was, I forgot the thing that I found the weirdest and that actually inspired me to start writing the blog entry.
&lt;p&gt;
Anyway, when you're splitting a large build up into multiple files, you really want all those files to have a single global classpath that they share for varius parts of the build. The problem is, normal &lt;tt&gt;path&lt;/tt&gt; blocks are actually local to the xml file that declares them. They are not inerhited across &lt;tt&gt;&amp;lt;ant&amp;gt;&lt;/tt&gt; invocations, even if you set &lt;tt&gt;inheritAll=true&lt;/tt&gt;. What you instead have to do is flatten the path into a property that is colon separated and use that as a &lt;tt&gt;classpath&lt;/tt&gt; rather than a &lt;tt&gt;classpathRef&lt;/tt&gt;. 
&lt;p&gt;
If you flatten the &lt;tt&gt;path&lt;/tt&gt; in the global build script into a property, then all the invoked scripts can see it correctly and all is bueno. The magic to do this is:
&lt;font size="-1"&gt;
&lt;pre&gt;
&amp;lt;path id="base.path"&amp;gt;
....
&amp;lt;/path&amp;gt;

&amp;lt;property name="base.path" refid="base.path"/&amp;gt;
&lt;/pre&gt;
&lt;/font&gt;

Note that the property and the path exist in separate namespaces, so there's no collision here having them both named &lt;tt&gt;base.path&lt;/tt&gt;. For clarity, it might be better to name the property version &lt;tt&gt;base.path.property&lt;/tt&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106562972942667384?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106562972942667384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106562972942667384'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106562972942667384' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106554840412894906</id><published>2003-10-07T10:40:00.000-07:00</published><updated>2003-10-07T10:40:03.850-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Binary XML &amp; Bandwidth&lt;/h3&gt;
I've been looking for a long time for a basic compression scheme that was standardized that I could use for XML. Today I found &lt;a href="http://www.w3.org/TR/wbxml/"&gt;this&lt;/a&gt;, which describes a simple huffman-like encoding for XML. I had personally come up with something very similar a while back, but ran out of time to implement it. I'm glad to see such things are out there and standardized, so theoretically parsers should support them without me writing my own compressor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106554840412894906?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106554840412894906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106554840412894906'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106554840412894906' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106553976922287509</id><published>2003-10-07T08:36:00.000-07:00</published><updated>2003-10-07T08:42:42.813-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Scaling your ant build, and making it maintainable: Kris's tips for ant&lt;/h3&gt;
I think most complex apps that get built these days, especially when you've got an appserver and (god forbid) ejbs in the mix, have, by necessity, a pretty complex build. I've often heard of places having dedicated build engineers (I've even worked at some), but almost always even when you have a person dedicated to it, the programmers are going to end up working on the build. 
&lt;p&gt;
Almost all of the things that I'm writing here are obvious if you're an ant guru, but  the one thing I've noticed about ant is the way the documentation is written, you constantly find more and more ways to make your build script that much better. The tricks I've found for making your ant builds scale:
&lt;ol&gt;
&lt;li&gt;Multi-file builds are absolutely necessary. If you keep your huge multi-target build in one file, you're going to end up with a mess. A java class with 10,000 lines is impossible to understand, and so is an ant script.
&lt;li&gt;Dealing with multi file builds is easiest done with a build script per deployment scenario. That is, if you have a target for websphere, a target for weblogic, etc, and each of these builds its own ear, its best to keep them in separate files.
&lt;li&gt;Ant is not a programming language. Complex "logic" (as best as it can be called) is always brittle, and difficult to debug if it causes subtle things to go wrong. (yes, ant is duct tape).
&lt;li&gt;Code sharing between ant scripts (such as a common set of build scripts shared by multiple apps in the same product suite) are problematic at best and a disaster at worse. This mostly comes into being because of subtle differences between the needs of each product.
&lt;li&gt;A product should never require a user to drop jars in their ant/lib directory. This was necessary in earlier versions of ant, but can now be accomplished by passing a classpath to the custom task declaration  and keeping the jars in the source tree. Having your product work with a vanilla ant install is a huge boost to getting people up and running.
&lt;li&gt;Use custom tasks with extreme caution. Not many people understand how ant works all that well, and custom tasks even less so.  You can quickly make your build impossible to understand if you have lots of custom tasks with sparse documentation. However, the boost to your system by bringing things together in a single build with custom tasks is also huge, so it is a double edged sword.
&lt;li&gt;Use "-" as a prefix to all internal task names. Internal tasks are those that are intermediate build steps, and should not be called from the command line. The "-" prefix actually makes it impossible to call them from the command line at all.
&lt;li&gt;Use property files instead of individual property statements. That would look like:
&lt;tt&gt;
&amp;lt;property file="build.properties"/&amp;gt;
&lt;/tt&gt;
rather than:
&lt;pre&gt;
&amp;lt;property name="foo" value="bar"/&amp;gt;
&amp;lt;property name="baz" value="quux"/&amp;gt;
&amp;lt;property name="blah" value="blahblah"/&amp;gt;
....
&lt;/pre&gt;
repeated a million times. Also, name your properties file &lt;tt&gt;build.properties&lt;/tt&gt;. This is becoming standard and I'm starting to see editors (like eclipse) that actually know about the build properties.
&lt;li&gt;Filesets are a powerful tool for setting up your classpath. In particular, doing something like:&lt;br&gt;
&lt;pre&gt;
&amp;lt;path id="app.class.path"&amp;gt;
    &amp;lt;fileset dir="${lib}"&amp;gt;
        &amp;lt;include name="**/*.jar"/&amp;gt;
    &amp;lt;/fileset&amp;gt;
&amp;lt;/path&amp;gt;
&lt;/pre&gt;
lets your programmers just drop jar files in the lib directory and they automatically become part of the app.  This can lead to headaches later when you have to construct things like ejb jar manifest &lt;tt&gt;Class-Path&lt;/tt&gt; entries that need to explicitly list jar names, but that can also be handled with the right set of ant incantations. The alternative to this (which I've also done) is explicitly listing the jars in the classpath in the build, which creates a maintainance nightmare as jars are added and upgraded and you try to recall which files contain the jar names.
&lt;li&gt;Put the version numbers of your jar in the jar name. I can't emphacize enough how critiical I think this is, and I'm also floored that other people don't do it. Having a file named &lt;tt&gt;classes12.zip&lt;/tt&gt; versus having a file named &lt;tt&gt;oracle-jdbc-8.1.7-1.2.jar&lt;/tt&gt; is just no contest to me. At some point, some day, you're going to need to swap out those jars and upgrade them, and when you do, knowing what jar versions you're using is going to be absolutely imperitive.
&lt;li&gt;When you're doing you're build, adding a datestamp, build host and time, etc, to some file that is in the output (such as html comments in your login screen) quickly helps with customer diagnosis of what version of the code the person is running. Ant can do this for you automatically with the &lt;tt&gt;copy&lt;/tt&gt; task and &lt;tt&gt;filterset&lt;/tt&gt;. What this looks like is:
&lt;font size="-2"&gt;
&lt;pre&gt;
&amp;lt;copy todir="${output}"&amp;gt;
  &amp;lt;fileset dir="${jsp}"&amp;gt;
    &amp;lt;include name="version.jsp"/&amp;gt;
  &amp;lt;/fileset&amp;gt;
  &amp;lt;filterset&amp;gt;
    &amp;lt;filter token="BUILDDATE" value="${builddate}"/&amp;gt;
    &amp;lt;filter token="BUILDCOMPILER" value="${build.compiler}"/&amp;gt;
    &amp;lt;filter token="BUILDUSER" value="${user.name}"/&amp;gt;
    &amp;lt;filter token="BUILDSCRIPT" value="${ant.file}"/&amp;gt;
    &amp;lt;filter token="BUILDOS" value="${os.name}"/&amp;gt;
    &amp;lt;filter token="BUILDOSVERSION" value="${os.version}"/&amp;gt;
    &amp;lt;filter token="BUILDARCH" value="${os.arch}"/&amp;gt;
  &amp;lt;/filterset&amp;gt;
&amp;lt;/copy&amp;gt;
&lt;/pre&gt;
&lt;/font&gt;
and then adding a block like this to &lt;tt&gt;version.jsp&lt;/tt&gt;:
&lt;font size="-2"&gt;
&lt;pre&gt;
&amp;lt;!-- Built By: @BUILDUSER@ --&amp;gt;
&amp;lt;!-- Build Script: @BUILDSCRIPT@ --&amp;gt;
&amp;lt;!-- Build Compiler: @BUILDCOMPILER@ --&amp;gt;
&amp;lt;!-- Build OS: @BUILDOS@ @BUILDOSVERSION@ @BUILDARCH@ --&amp;gt;
&lt;/pre&gt;
&lt;/font&gt;
&lt;li&gt;The productivity boost for your programmers for having both an exploded build target and a packaged build target is well worth the effort of maintaining them. This is J2EE specific, but I think highly useful. There is a large difference in the deployment times for the various appservers if they are deploying a zipped &lt;tt&gt;ear&lt;/tt&gt; file versus an exploded file on disk that just has to have the classes reloaded. Often this can save minutes per build, which is huge for the developers.
&lt;li&gt;This is just a general guideline, and not ant specific, but you should always keep your build fast for development. That means it runs in seconds, not minutes. I've had ant builds that ran &lt;tt&gt;ejbc&lt;/tt&gt; for development (adding 2-3 minutes to the build), and productivity cut by a factor of 2 immediately.
&lt;/ol&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106553976922287509?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106553976922287509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106553976922287509'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_10_01_archive.html#106553976922287509' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106496326690476090</id><published>2003-09-30T16:07:00.000-07:00</published><updated>2003-10-01T11:35:00.893-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;HTTPUnit: Unit test your web apps!&lt;/h3&gt;
One thing I've always missed when developing web applications is unit testing. One can always unit test portions of the app, which usually amounts to testing the layers underneath the actual user interface code, but that's really not the place where the biggest disconnects happen.  The place where you have real problems is in the user interface talking to the model code via HTTP.
&lt;p&gt;
This is something the windows interface people have been dealing with for years, and they have a lot of decent solutions out there for automated UI testing, but most of them are fairly sensitive to things like widget placement, etc. There are also products like Silk that will both do functional and load testing of your app. But almost all of these are targeted at QA folks, which are far too late in the game to actually let you catch your errors. Usually by the time things get to QA as regressions, you have to go through a bug process, etc, and it's just a huge pain. There was an old Rational ad that I always think about when I'm unit testing: Is a mistake a mistake if nobody ever sees it?
&lt;p&gt;
Anyway, &lt;a href="http://www.httpunit.org"&gt;HTTPUnit&lt;/a&gt; seems to me to be the clostest thing to the missing link I've yet seen. It simulates the servlet container and the browser (including javascript, frames rendering, etc) and lets you unit test servlets, jsps, etc, along with write java code that actually walks click paths in the application, sets form values, does posts and verifies UI integrity. All for the developers. All without having to start Weblogic. I'm currently working on integrating it with my application platform to ensure that it serves our needs, but the promise so far is huge.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106496326690476090?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106496326690476090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106496326690476090'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106496326690476090' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106451301567244744</id><published>2003-09-29T16:53:00.000-07:00</published><updated>2003-09-29T16:53:23.270-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Hiring &amp; Women in Software&lt;/h3&gt;
I'm currently in the middle of trying to bring in an engineer to my current company to help with a product we have in the works. I've plowed through hundreds of resumes, we've done phone interviews, etc, culling out all but around 10-12 of these people. I've been through this process many,  many times, and the one thing that really jumps out at me is: When you get down to the short list, I'm starting to notice more and more women in tech that are really really qualified. My wife always says that to be a woman or a minority and to make it as a software engineer, you have to be twice as good as the average person to get noticed. 
&lt;p&gt;
What I find encouraging is that after the dotcom crash and the whatever the hell we're in now, it seems like the numbers for women showing up in the hiring pool that are actually really qualified and solid candidates are really looking up. It gives me some fairly large measure of hope for fixing the gender gap in software, I suppose.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106451301567244744?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106451301567244744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106451301567244744'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106451301567244744' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106487945072220016</id><published>2003-09-29T16:50:00.000-07:00</published><updated>2003-09-29T16:51:05.553-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;The Evils of Downcasting, or Why I Miss Smalltalk&lt;/h3&gt;
When I learned how to develop using OO, I learned that any downcasting was a "funny smell", and could always be eliminated. My experience of developing this way led me to develop code that was extremely tight and easy to maintain.  I had found my development nirvana. All I had to do was follow this pattern, and all was well. 
&lt;p&gt;
Then I started working in Java. Did I mention I learned how to properly do OO using Smalltalk? All of my Java code always seemed like a hack. There were static "helper" functions cropping up that constantly made me ill. And most importantly, I was writing code that did conditional downcasts that I couldn't work around.
&lt;p&gt;
Then it dawned on me: in Java, if I need it, I can't add a method to string to clean my code up. Swing is fixed. All my commericial libraries have fixed APIs. In Smalltalk, if you need to add a method to Boolean, you just go right ahead and do that. The libraries and your code merge into one sort of blob that are both honed to each other. This is a clean, elegant blob that works perfectly, but it also means that you incur the penalty of maintaining all that gargantuan amount of code you've just "tweaked" to make cleaner. 
&lt;p&gt;
I'm really not sure which is a better tradeoff, but the idea of tweaking the JDBC drivers and the appserver to really make my code smooth, and then incurring the weight of maintaining those 250-500kloc of code that I could previously write off as someone else's problem doesn't sound all that hot. Maybe I'll live with my Java hack code and simply remember OO nirvana like a sweet, pleasant memory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106487945072220016?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106487945072220016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106487945072220016'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106487945072220016' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106426574060723740</id><published>2003-09-22T14:22:00.000-07:00</published><updated>2003-09-22T14:26:48.756-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Bonkers: Mate for the Masses&lt;/h3&gt;
In the last few months, I've started drinking &lt;a href="http://www.yerbamate.com"&gt;Yerba Mate&lt;/a&gt; instead of coffee as my primary caffeine source. It's a much happier buzz, as it doesn't leave you feeling all shitty and jittery after 12 hours of slugging it down while coding. After having been off coffee for a while and then going back to it briefly, coffee to me feels like some sort of toxin I'm bringing into my body, while mate feels cleansing.
&lt;p&gt;
What I discovered today was &lt;a href="http://www.bonkersinternational.com"&gt;Bonkers&lt;/a&gt;, which is a non-loose Mate in tea bags. The genius thing there is they have &lt;i&gt;super caffeinated&lt;/i&gt; Mate, which is like making a good thing 10x better. It's called WIRED &amp; CRAZY MATE; I encourage you to go find some at your grocery store (I shop at the &lt;a href="http://www.oaklandchamber.com/html/2001_12_piedmont_grocery.html"&gt;Piedmont Grocery&lt;/a&gt;, which is Divine, and carries all the Bonkers you need).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106426574060723740?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106426574060723740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106426574060723740'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106426574060723740' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106425411408637167</id><published>2003-09-22T11:08:00.000-07:00</published><updated>2003-09-22T14:27:34.473-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;NTFS Maximum Path Name Length&lt;/h3&gt;
So a useful tidbit for windows users: NTFS,  at least on XP (and probably everywhere), has a maximum path name length. When I found this out, it really felt like being tossed back into UFS circa UNIX System 3. The maximum length of a path on Windows (at least from the command line) is 256 characters. 
&lt;p&gt;
What this means from a practical perspective is that if you have deep path structures in your webapp, and you have your appserver deeply structured (such as WebSphere), you'll run into stray messages like:&lt;br&gt;
&lt;tt&gt;(The system cannot find the path specified)&lt;/tt&gt;
&lt;p&gt;
The problem is, WebSphere puts the app (by default) at &lt;tt&gt;C:\Program Files\WebSphere\AppServer\installedApplications\&lt;i&gt;hostname&lt;/i&gt;&lt;/tt&gt;. When you tack this onto the deep, nice file structure you have in your app, suddenly you're looking at paths far in excess of 256 characters long. And the beauty of it is, WebSphere fails silently and tells you that it deployed correctly. You only see the above message when you try and copy the files manually into the deployment directory using something like &lt;tt&gt;ant&lt;/tt&gt;.
&lt;p&gt;
The solution is to tell the appserver to deploy the app (when you're pushing it in the deployment tool) into a shorter path, like &lt;tt&gt;C:\temp\ws&lt;/tt&gt;. This way, it will actually deploy correctly when it says it did.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106425411408637167?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106425411408637167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106425411408637167'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106425411408637167' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106424914963050405</id><published>2003-09-22T09:45:00.000-07:00</published><updated>2003-09-22T14:28:01.083-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Perl is the Yugo of Programming Languages&lt;/h3&gt;
I, like 99% of the rest of the world, saw &lt;a href="http://blogs.law.harvard.edu/philg/2003/09/20#a1762"&gt;this article&lt;/a&gt; on Java being the SUV of programming languages. I'll spare you the lawyer jokes (note the url).
&lt;p&gt;
The part that really blows me away is that people actually believe this sort of junk and then parrot it to the rest of the world. How is Java too powerful? It has OOP that works and wasn't tacked on as an afterthought? It helps you structure your code so you can actually not end up with a total mess at the end of things?
&lt;p&gt;
My only retort to this article is that scripting languages should be used like duct tape. They seal up big cracks in software systems so they work, but they're almost always a hack, and when you try not to make them a hack, it's a hell of a lot more work than it would have been to actually write it using a full featured language in the first place. 
&lt;p&gt;
I'm not here to argue about strong versus weak typing. I'm here to encourage people to actually &lt;i&gt;TRY&lt;/i&gt; the technology in the real world before they start becoming a pro or con evangelist. And, yes, before you ask: I've written more Perl for money than I care to recall. There's a reason why I use Java now, and it's not because it's fashionable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106424914963050405?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106424914963050405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106424914963050405'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106424914963050405' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106391050119333091</id><published>2003-09-18T11:41:00.000-07:00</published><updated>2003-09-22T14:28:26.176-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Ruby, C#, and Python: Whither the Software Wind Blows&lt;/h3&gt;
I've been looking for quite a while as to what is going to be the "next big thing" that is going to take off in the software world. At the rate that most of us were used to in 1999, the "hot new things" in Java and XML are starting to grow whiskers.  
&lt;p&gt;
Over the last 6 months, I've had the opportunity to put out ads and get resumes for various software positions in the bay area. 6 months ago, we would get 200 responses to a job posting in the first day, and about 500 in the course of a week. We put out an ad last week for a java/XML person, and got a grand total of 100 resumes in a week. I see this as a definite sign of real economic recovery. We also didn't get any resumes from the people that were applying for jobs &lt;i&gt;way&lt;/i&gt; below their skill sets, which I find relieving. At one point, we were hiring a junior engineer and got a resume from one of the original multics designers. That was a depressing day.
&lt;p&gt;
Anyway, long story short: it seems economic recovery is upon us, in some sense (cross our fingers). With this recovery, I'm seeing a lot more mention of alternate technologies and people pursuing real project development in things like Ruby and Python.  And, of course, C# is rapidly gaining momentum. There's a feeling of a breath of life and fresh air in the industry, like someone opened the attic and remembered that a long time ago we used to actually invent new things and not keep banging out junk using the same old tools, and maybe they should invest some time, money and effort in moving things forward.
&lt;p&gt;
Here's to the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106391050119333091?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106391050119333091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106391050119333091'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106391050119333091' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-1063909178822071</id><published>2003-09-18T11:19:00.000-07:00</published><updated>2003-09-18T11:19:38.673-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Patterns of Enterprise Application Architecture, or Working Around The RDBMS&lt;/h3&gt;
I've recently been readin Martin Fowler's latest book, &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321127420/qid=1063908883/sr=8-1/ref=sr_8_1/002-2739728-0952816?v=glance&amp;s=books&amp;n=507846"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;.  This, honestly, is the best patterns book I've read since the original GoF patterns book.  It had the same effect of both showing me names for things I already knew how to do, quantifying the tradeoffs of the various decisions and showing me new ways to do things that I hadn't thought of. I fully recommend everyone working on enterprise software (C# or Java, in particular) buys it and reads it cover to cover.
&lt;p&gt;
The thing that struck me most about the book is always the thing that struck me most about dealing with enterprise software in general: the RDBMS is like a giant boat anchor that's unfortunately necessary. It seems like a massive chunk of the book is dedicated to dealing with getting your clean object model into and out of the database while not sacraficing too much efficiency or cleanliness. To his credit, Mr. Fowler does a great treatment on the subject that's clear and easy to understand and implement. I thank my lucky stars that &lt;a href="http://www.hibernate.org"&gt;hibernate&lt;/a&gt; exists, and implements a &lt;i&gt;large&lt;/i&gt; number of the patterns in the book cleanly and efficiently so I don't have to.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-1063909178822071?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/1063909178822071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/1063909178822071'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#1063909178822071' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106338997640486828</id><published>2003-09-12T11:06:00.000-07:00</published><updated>2003-09-12T11:06:16.423-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Intellij "Aurora": Great new UI, and lots more great plugins&lt;/h3&gt;
If you're an intellij user, I encourage you to download the latest "Aurora" release from the &lt;a href="http://www.intellij.net/eap/"&gt;JetBrains EAP (Early Access Program)&lt;/a&gt;. It has a great new UI and a killer set of features that just made things that much better. In particular, the new JUnit runner is just too cool for school.

The thing that got me to download Aurora in the first place was the &lt;a href="http://www.intellij.org/twiki/bin/view/Main/AutoBoxingPlugin"&gt;Auto Boxing Plugin&lt;/a&gt;, which is a plugin that lets you do:
&lt;pre&gt;
Integer i = 12;
&lt;/pre&gt;
And will "auto suggest" that it be changed to:
&lt;pre&gt;
Integer i = new Integer(12);
&lt;/pre&gt;
Which conveniently solves a major language shortcoming with just an IDE hook. It does a LOT more than that though, working around a lot of other Java foibles cleanly and gracefully.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106338997640486828?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106338997640486828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106338997640486828'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106338997640486828' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106338683847358080</id><published>2003-09-12T10:13:00.000-07:00</published><updated>2003-09-12T10:14:24.540-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Test Driven Development with Databases&lt;/h3&gt;
I, like I suspect many people, have always had a problem with test driven development for enterprise systems. The unit tests that you read in the books all have no side effects. They check that the code runs, and if they fail, no big deal. However, the reality for enterprise systems is that tests have side effects: they mutate the data in the database. If they fail in ways you don't expect, they can horque the data that they are depending on to run, and the whole system breaks down. My experience is that in this situation, unit testing gets pretty quickly tossed out the door, because as soon as you end up having to diagnose the data to get your tests to run after they've clobbered it, it becomes very labor intensive and breaks your train of thought and productivity rapidly.

I had the opportunity to talk to someone that does a lot of test driven development against enterprise systems, and he offered me the nougat I was missing. Props to ThoughtWorks. The two necessary things are:
&lt;ul&gt;
&lt;li&gt;Data sets for the tests are as important as the test code, and are fixed. These are guarded with the same care that you guard the test code itself. This I had managed to figure out on my own.
&lt;li&gt;Test code, when it runs, has a harness around it that always, when the execution is complete, rolls the transaction back. This way, even if the test fails mysteriously, it won't clobber the underlying data that the tests depend on.
&lt;/ul&gt;

The only downside to this that I see is that tests have to have all their data that they need defined as DML that is loaded into the system using something like sqlplus before the tests can run, because by definition, the tests themselves cannot modify the database.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106338683847358080?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106338683847358080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106338683847358080'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106338683847358080' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106331031640312565</id><published>2003-09-11T12:58:00.000-07:00</published><updated>2003-09-11T13:01:36.836-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Anonymous no longer&lt;/h3&gt;
&lt;img src="http://www.further.com/kris/photos/aftermath-small.jpg" height="100" align="left"&gt;&lt;a href="http://www.freeroller.net/page/cpurdy"&gt;Cameron&lt;/a&gt; mentioned me in his /dev/null blog, and pointed out that I was ranting anonymously, which I found both suprising and pretty amusing.  I mean, someone is actually reading this.. that sets a much higher standard for me to live up to; delivering quality content. This is me on the left, and &lt;a href="http://www.further.com/kris/kris-gradstudent.jpg"&gt;this was me  while still in grad school&lt;/a&gt;.  My name is Kris, and I can be contacted at &lt;tt&gt;kris at further dot com&lt;/tt&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106331031640312565?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106331031640312565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106331031640312565'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_09_01_archive.html#106331031640312565' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-106073454153062306</id><published>2003-08-12T17:29:00.000-07:00</published><updated>2003-08-27T11:48:43.343-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;WebSphere v5: A case study in how to design the worst development platform ever&lt;/h3&gt;

I've had the opportunity to work with a large set of application servers and j2ee platforms,  including Resin, Tomcat, WebLogic and WebSphere. The open source (Tomcat, Resin) servers, have, in my experience, always been the best platforms to work with, hands down. Configuration is simple. Applications deploy and run with minimal trouble. Things are buggy, but software is always buggy. The cursing you do about the appserver is generally good natured, and you get along. If you really get stuck, you grab the sourcecode and debug the stupid thing, which almost universally works and isn't terrible to do because, well, it's an http protocol translator in a fancy box.. how complex could it be really?
&lt;p&gt;
Enter WebSphere.
&lt;p&gt;
Really, all I'm looking for in a development platform is:
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Stable&lt;/b&gt;: The platform has been used by a lot of people, and the job it is expected to do it does reliably. This means no crashing, even when i redeploy my application a zillion times.
&lt;li&gt;&lt;b&gt;Fast Development&lt;/b&gt;: You should be able to drop code into the appserver and see it run without reading the wall street journal between compiling and actually seeing the code run.
&lt;li&gt;&lt;b&gt;Non Developer Hostile Feature Set&lt;/b&gt;: In the interpretation of any standard, there are always things that are ambiguous, and can be interpreted in several ways. Often times one of these ways will allow developers some more latitude to do things that are not necessary or look slightly strange but really don't affect correctness, and the other way will do things extremely strict that will cause massive development problems because the person who wrote the tool is anal retentive.
&lt;li&gt;&lt;b&gt;Diagnosable&lt;/b&gt;: In the event that I do something wrong, or god forbid, the tool crashes, I should be able to figure out what the hell actually happened, and fast.
&lt;/ul&gt;
Websphere, amazingly, fails all 4 of these tests. 
&lt;ul&gt;
&lt;li&gt;It routinely crashes on all of my development hosts and platforms just deploying my code. The crashes are non repeatable, and often silent. They usually appear to be instability in the jvm, but I don't give a damn, really. The appserver should eat generic webapps for lunch.
&lt;li&gt;Deployment cycles are terrifyingly slow. The only way to deploy an application is a zipped war, and you have to use a webgui to update your application. This totally ruins any chance at keeping your train of thought. Updates of an application usually take 5 minutes from a code change to seeing it run, or more. I know there is a hot deploy mode, but it's hostile to use and has been severely unreliable.
&lt;li&gt;I have never taken a jsp that works on another appsever, dropped it on websphere and seen it work. Websphere wont read mac line endings in jsps, but when it crashes, it tells you that your jsp tags are not properly closed. Complete crap. It also has the strictest, most retarded interpretation of the j2ee spec i've ever seen. Resetting the content type of your jsp page twice or more works perfectly on every other appserver. I know that's not right. I don't care, as long as its always set to the same string.
&lt;li&gt;When it crashes due to bad file encodings, or simply using the console, it gives misleading error messagess or no error messages at all.
&lt;/ul&gt;
&lt;b&gt;For shame&lt;/b&gt;. I previously held IBM in very high regard with respect to the quality of their java tools. My experience with websphere has totally ruined the IBM java reputation for me. They need to get their heads out of the sand and realize that the people working in the trenches USE their tool, and make buying decisions based on how hard it is to use the tool. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-106073454153062306?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106073454153062306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/106073454153062306'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_08_01_archive.html#106073454153062306' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105868258374917907</id><published>2003-07-19T23:29:00.000-07:00</published><updated>2003-09-12T10:57:39.780-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;File encodings suck, or dealing with localizing a real world app&lt;/h3&gt;
If you're like me, you probably have to deal with bringing translated text (resource bundles) into your application.  This means, you send your english property files off to another company, and they send them back to you in french, russian, spanish, korean and a truckload of other languages. The problem is, the translated files arrive from the (terrible) translators in any random file encoding that the translator felt like using.
&lt;p&gt;
That is, you get the files in some weird Latin-3 encoding and you need it in UTF-8. Except you don't know that it's in Latin-3, it just looks like a bunch of garbage because you don't have fonts to render greek on your box.  What is one to do?
&lt;p&gt;
The two things you need, if you're dealing with java, are &lt;tt&gt;iconv&lt;/tt&gt; and &lt;tt&gt;native2ascii&lt;/tt&gt; .. &lt;tt&gt;native2ascii&lt;/tt&gt; is the tool that converts from the binary utf-8 encoding to an ascii encoding with escapes, so it looks like \uXXXX whenever there should be a non-ascii chacter.  &lt;tt&gt;native2ascii&lt;/tt&gt; comes with the jdk, so you've already got that. &lt;tt&gt;iconv&lt;/tt&gt; or &lt;tt&gt;piconv&lt;/tt&gt; are available under cygwin or any linux distro, and both work equally well. Remeber, in the end, you're going to end up running the file thru &lt;tt&gt;native2ascii&lt;/tt&gt; before you try it in the app, anyway, because that is the only format that java can read natively.
&lt;p&gt;
Remember, when you're working on a moden linux machine, vi is UTF-8 clean, and on windows, notepad is UTF-8 clean. So what you need to do is using iconv or piconv to convert the file from whatever encoding you guess it is to UTF-8, and then open it with vi or notepad. If it does not look corrupt, you're in business. At that point, run &lt;tt&gt;native2ascii -encoding &lt;your_encoding&gt; &amp;lt; file &amp;gt; file.java.ready&lt;/tt&gt;, where &lt;tt&gt;&lt;your_encoding&gt;&lt;/tt&gt; is the encoding you used with iconv to produce the file that looked ok in notepad or vi.
&lt;p&gt;
The homebrew heuristic to detect the corrupt files that were converted with the wrong -encoding switch with native2ascii, based only on experience,  is as follows: Pick a file that has a sequence like this &lt;tt&gt;[ascii character][non-ascii character][ascii character]&lt;/tt&gt;. Take the file and run it thru native2ascii, with the source set to a your encoding that you think is right.  If the output looks like &lt;tt&gt; [ascii character]\uXXXX[ascii character]&lt;/tt&gt; then you've found the encoding. However, if there are more than 1 &lt;tt&gt;\uXXXX&lt;/tt&gt; sequences between the ascii characters, your encoding is wrong and you need to try again. 
&lt;p&gt;
Of course, if you had a hex editor and a copy of the code pages on hand, you could determine this much less heuristically, but I can never find either of those when I need them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105868258374917907?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105868258374917907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105868258374917907'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_07_01_archive.html#105868258374917907' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105859301199363445</id><published>2003-07-18T22:36:00.000-07:00</published><updated>2003-07-18T22:36:51.930-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Relearn how to type, it's worth your effort; gesture keyboards rule&lt;/h3&gt;

I've recently switched to using a &lt;a href="http://www.fingerworks.com"&gt;Fingerworks&lt;/a&gt; gesture keyboard. It takes a lot of effort to re-learn how to type (how well can you type on a flat table?). Once you throw in the 3 weeks of retraining, however, the boost that the gestures support gives your development is amazing. Imagine making the "hang loose" sign with your left hand and your ide does autocompletion. Then you slide around your right hand, and without leaving the keyboard, you're jetting around using the mouse, arrow keys at lightning speed with your left hand, and simple gestures that trigger extemely complex application level macros.
&lt;p&gt;
The biggest challenge is not learning how to gesture or use your mouse, though, its learning how to type. I have yet to switch over to the fingerworks keyboard for my main device, just because my programming on it is like 1/3 speed of my normal development, which personally makes me want to throw the computer out the window. But I am getting faster, and I can see the day where my Kinesis will go up on ebay and I'll be that much faster and efficent when I work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105859301199363445?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105859301199363445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105859301199363445'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_07_01_archive.html#105859301199363445' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105859259258165443</id><published>2003-07-18T22:29:00.000-07:00</published><updated>2003-07-18T22:29:52.536-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;"COTS" Open Source: Practically Delivering on the COTS vision&lt;/h3&gt;

I've recently been putting in a lot of work building a custom web application framework for internal product work at my organization. Largely, this effort has focused on using off the shelf components, leveraging their strengths and implementing the custom framework as a layer of glue between those components to integrate them into a platform. Some would say "duh" and claim that is the whole point of using off the shelf software. And I do not entirely disagree. 
&lt;p&gt;
The exciting bit here is that this is actually real, and the integration can happen in such a fashion that things are actually nicely coherant and integrated as a tools platform without having to spend a fortune on customization of the invidual tools from vendors, and deal with the fact that tools don't meet your requirements exactly.  Instead, just having the ability to look inside the tools and work around issues, work around features that are getting in your way, you can very quickly assemble something that will rocket you ahead in your development effort.
&lt;p&gt;
The tools that I have glued together are jStateMachine (no longer publicly available), &lt;a href="http://hibernate.bluemars.net"&gt;Hibernate&lt;/a&gt; and a collection of open source libs (dom4j, etc), using &lt;a href="http://www.eclipseuml.com"&gt;Eclipse UML&lt;/a&gt; as a charting tool. This has given us a system that lets you draw uml statecharts that describe your app, run them immediately in the appserver and cleanly drop in dhtml renderers for your data that are decoupled from the backend logic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105859259258165443?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105859259258165443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105859259258165443'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_07_01_archive.html#105859259258165443' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105770449268784414</id><published>2003-07-08T15:48:00.000-07:00</published><updated>2003-07-08T15:48:12.700-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Scrollable Results &amp; Hibernate&lt;/h3&gt;
I was looking for a method to do nice, database indedendent paged results without sucking the whole result set out of the database. Just found out from crazy bob that &lt;a href="http://crazybob.org/roller/page/crazybob/20030305"&gt;scrollable result sets&lt;/a&gt; don't work the way they "should", mostly because the drivers suck. So much for that idea.
&lt;p&gt;
However, it turns out that &lt;a href="http://hibernate.bluemars.net"&gt;Hibernate&lt;/a&gt; (which I am looking to use) has an Oracle9 dialect that understands the pattern of using a nested select and the Oracle &lt;tt&gt;ROWNUM&lt;/tt&gt; pseudo-column. Here's to the Hibernate developers for a clean solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105770449268784414?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105770449268784414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105770449268784414'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_07_01_archive.html#105770449268784414' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105770400854976921</id><published>2003-07-08T15:40:00.000-07:00</published><updated>2003-07-08T15:40:36.866-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Plugging some amazing effort: &lt;a href="http://www.realityinteractive.com"&gt;Reality Interactive&lt;/a&gt;&lt;/h3&gt;
I'd like to take this opportunity to plug &lt;a href="http://www.realityinteractive.com"&gt;Reality Interactive&lt;/a&gt; and my buddy Rob. He's done some amazing things with the 1.4 JDK, and, despite the fact that it looks like he rewrote a game that's several years old, he's done something infinitely cooler.  The promise here (which he has shown proof that he can realize) is that simulations (i.e., games or things like flight simulators) can be written much faster, much more reliably in Java than they can in C++. Over and above the boost of using a better language that's more suited to the task, he's built a toolkit that brings a lot of the hard won experience of the enterprise java world to simulations. This lets people do things like focus on actually writing their physics engine rather than invent another architecture that will be discarded in 8 months.
&lt;p&gt;
3 cheers for some real innovation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105770400854976921?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105770400854976921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105770400854976921'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_07_01_archive.html#105770400854976921' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105770373000422652</id><published>2003-07-08T15:35:00.000-07:00</published><updated>2003-07-08T15:35:30.036-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Why did you make us wait for this?&lt;/h3&gt;
To echo the sentiment of a thundering crowd: Is &lt;a href="http://www.java.net/"&gt;this&lt;/a&gt; really what we were waiting for?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105770373000422652?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105770373000422652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105770373000422652'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_07_01_archive.html#105770373000422652' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105547447631540990</id><published>2003-06-12T20:21:00.000-07:00</published><updated>2003-06-13T00:18:57.056-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Weblogic, Container Managed Transactions, and Connection Pooling: Why you need the JTS driver&lt;/h3&gt;
&lt;b&gt;&lt;i&gt;Long winded intro&lt;/b&gt;&lt;/i&gt;&lt;br&gt;
So, to start this off: I've been working on a VERY large system for the last year or so that runs on BEA Weblogic. It uses EJBs in container managed transaction mode, because that's what "everyone" says to do.  There are, of course, benefits to having transactions and avoiding a commit on each single db operation, so great, I said, let's use them. Did I mention this was my first weblogic application? Did I mention it's almost a quarter million lines?
&lt;p&gt;
So we built the system, and the whole time we were building it, it was always slow.  Some of the lessons I learned about Oracle and database connections still leave my shaking my head. Anyway, we kept getting faster. And faster. But faster will still slow as dirt, quite honestly. I'd built a ton of apps that ran on other appservers, and they were always TONS faster than this. I was left  scratching my head until I wore a bald spot in my hair. I mean, I'd tuned the code, and tuned it and tuned it. I was having halucinations of JProbe UIs, and it would not speed up.
&lt;p&gt;
So I was getting into quite a tight spot, as the customer was not able to actually USE the app, it was so slow. As it was more and more important that I actually fix the problem, I sat down one afternoon and read the "Container Managed Transactions" section of the weblogic docs yet again. And I noticed a weird footnote, that said something to the effect of "A transaction should use a single JDBC connection, as any connection that is used by the transaction, even if closed, remains associated with the transaction until it commits." 
&lt;p&gt;
I sat straight up in my chair and grabbed the desk, as I thought I might faint.
&lt;p&gt;
&lt;b&gt;&lt;i&gt;The chase&lt;/b&gt;&lt;/i&gt;&lt;br&gt;
Long story short: I was following the same pattern I (and probably lots of others) had always used, which is: 
&lt;pre&gt;
try {
    connection = dataSource.getConnection();
    connection.executeXYZ();
} finally {
    connection.close();
}
&lt;/pre&gt;
This would happen for each db operation I needed to do in the transaction,  so what it turns out I was doing was using a HUGE swath of database connections (15-30 sometimes) for each  transaction. Then, when I committed the outer TX, the Weblogic transaction manager would have to run a commit on each individual connection that was attached to the transaction. Which makes it yet slower.  And the fact that those connections are unavailable to the server during the whole TX makes it yet slower still, as the connection pool was artificially exhausted by only a small number of users. The fix was to go from "connection per query" to "connection per transaction", which, if done the brute force way, is a massive code change (everywhere you currrently fetch a connection, you need to have it passed in). Turns out the fix was trivial if you do it using a vendor proprietary solution. In this case, proprietary saved my bacon.
&lt;p&gt;
The answer to my (and maybe your) ills is called the "Weblogic JTS Driver". You can read more about it &lt;a href="http://edocs.bea.com/wls/docs70/jdbc/rmidriver.html#1026194"&gt;here&lt;/a&gt;. What this does is change your API from using a DataSource to an old fashioned Driver, but it, under the hood, uses your connection pool and makes sure your single transaction always uses the same connection.  Suddenly, my application went from crashing with 8 users, to handling a solid pounding by 60. And it was miller time.

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105547447631540990?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105547447631540990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105547447631540990'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_06_01_archive.html#105547447631540990' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105537730394081681</id><published>2003-06-11T17:21:00.000-07:00</published><updated>2003-06-11T17:21:43.726-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Why do open source projects ignore me?&lt;/h3&gt;
So here's just a thought for a cloudy wednesday afternoon: I've written various chunks of code that I actually want to contribute back to open source projects over time, specifically to &lt;a href="http://www.apache.org/ant/"&gt;apache ant&lt;/a&gt;, and I've always gotten completely ignored.  Now, if I were a neophyte and writing and sending in stupid hello world code snippets, I would expect this. However, I'm a professional, contributing back code that I use every day in production that could be useful to other people.  And not even a "thanks but no thanks" email in response to my submission.
&lt;p&gt;
Normally,  I think most people would feel shunned and walk away rebuffed in some way because these other "super cool" programmers "won't email me back".  I, on the other hand, think that these projects are basically shooting themselves in the foot, because I (and I suspect, many other talented programmers) are getting ignored when they try and contribute, and so they just basically go "aw, fuck it anyway" and never bother again because the team is too lazy or buried in their own hubris to respond to code submissions.  I guess this is just a bit of a lament, and, if any open source project leaders are listening, a warning: ignore people who are trying to contribute at your own (and the rest of the industry's) peril. Open source lives and dies on the goodwill of the developers, and if you don't breed good will, you can't grow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105537730394081681?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105537730394081681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105537730394081681'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_06_01_archive.html#105537730394081681' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105333541258332611</id><published>2003-05-19T02:10:00.000-07:00</published><updated>2003-05-19T02:10:12.506-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Insomnia yeilds cool IntelliJ tricks&lt;/h3&gt;
First off, the &lt;a href="http://www.intellij.org/twiki/bin/view/Main/IntelliJPluginsHome"&gt;IntelliJ plugin registry&lt;/a&gt; contains tons and tons of plugins. I do have to say the presentation is poor, and its difficult to tell what is a "real" worth my time plugin and what is basically a toy. Which is what took me so long to find this stuff. So the revolutions are:
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.intellij.org/twiki/bin/view/Main/PerforceDirectPlugin"&gt;Perforce Direct Plugin&lt;/a&gt;: This is the single greatest perforce integration I've seen thus far, tho I am not up on where p4eclipse is these days. This is a must if you use perforce with IntelliJ, and the only p4 integration for it (besides the one it ships with) that works out of the box.
&lt;li&gt;&lt;a href="http://www.intellij.org/twiki/bin/view/Main/TabifierPlugin"&gt;Tabifier Plugin&lt;/a&gt;: It turns one someone else used to use emacs, and misses having their = signs lign up when they declare variables.
&lt;li&gt;&lt;a href="http://www.intellij.org/twiki/bin/view/Main/LogMonitorPlugin"&gt;Log4j Monitor&lt;/a&gt;: Jump a few hoops and you can see and navigate your log4j output ala the chainsaw tool inside intellij, with the bonus of being able to adjust logging levels at runtime.
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105333541258332611?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105333541258332611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105333541258332611'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_05_01_archive.html#105333541258332611' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105332240519665447</id><published>2003-05-18T22:33:00.000-07:00</published><updated>2003-05-19T02:11:11.200-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Two finds for a sunday&lt;/h3&gt;
The first thing is &lt;a href="http://m.bacarella.com/papers/secsoft/html/"&gt;The Peon's Guide To Secure System Development&lt;/a&gt;, which I just re-read while surfing my bookmarks. This wasn't anything I didn't already know, but I definitely can say that I really like the way the guy writes and the message he gets across. He and I are of a single mind.
&lt;p&gt;
The other thing is: &lt;b&gt;&lt;i&gt;Cygwin users, it's time to stop using that damn DOS box!&lt;/i&gt;&lt;/b&gt;&lt;br&gt;
The trick is:
&lt;ol&gt;
&lt;li&gt;Install/upgrade to the latest cygwin
&lt;li&gt;When doing the update, in the setup.exe, look under Shells and select "rxvt"
&lt;li&gt;After the app is installed, from a cygwin (or dos) shell, run 
&lt;tt&gt;C:\cygwin\bin\rxvt.exe -fn "Courier New-14" -fg grey85 -bg black -e (path to your shell) -l&lt;/tt&gt;
&lt;/ol&gt;
I have this setup as a shortcut to start my shell on my box, and it's heavenly. I finally have my xterm back!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105332240519665447?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105332240519665447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105332240519665447'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_05_01_archive.html#105332240519665447' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105314509699048677</id><published>2003-05-16T21:18:00.000-07:00</published><updated>2003-05-16T21:18:16.970-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Heuristic resource leak checkers&lt;/h3&gt;
&lt;a href="http://www.cs.uiuc.edu/people/faculty/sha.html"&gt;Lui Sha's Law&lt;/a&gt;:  Engineering is about solving the problem that can be solved.
&lt;p&gt;
The above is a rough paraphrase of something Lui, my advisor and mentor in grad school, used to say reguarly. Lui is a damn smart guy, and that has really stuck with me over the years. If you try and solve the general problem of finding things like JDBC leaks, EJB leaks or any other technically "intractable" problem, you're just gonna end up stuck in the weeds digging for years with no answer. I'm certainly not smart enough to solve the halting problem, and my guess is you're not either. 
&lt;p&gt;
What you can, instead, do is look for the pattern of how you fetch and release database connections in your system, using your frameworks and code standards. If something doesn't match the pattern, it's probably a leak, but if nothing else, it's definitely something odd that doesn't match the rest of the system and should be looked at.
&lt;p&gt;
I built an EJB leak checker for the system I'm currently building that scans for things that don't match how we fetch and release EJBs. Thus far, it's found something like 99.9% of all of our leaks, if not 100% (damn halting problem.. I can't tell!). Certainly the before and after of runninging it shows a much more reliable application afterwards under load. It works so well we integrated it into the build, and the build halts if there's a probable leak.  If you can do this for your system, I fully encourage it. It saves on JProbe licenses :-)
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105314509699048677?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105314509699048677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105314509699048677'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_05_01_archive.html#105314509699048677' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105314408804347254</id><published>2003-05-16T21:01:00.000-07:00</published><updated>2003-05-16T21:01:28.030-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;A moment to reflect on your ergonomics&lt;/h3&gt;
Kris's Law: When you're in pain because of working, you won't want to work. &lt;br&gt;
Kris's Law Corollary #1: If something is a hassle or complex to do, and you have to do it more than once, you won't do it, you'll do it wrong or very half-assed.
&lt;p&gt;
The general principal is pretty simple. I included the corollary just because I needed to write it down.  From an ergonomics perspective, causing yourself pain can happen a myriad of ways. The way I'm currently fighting this is how to deal with correct monitor position on multidisplay machines.  If you have it wrong, you cause yourself neck, shoulder and back pain as you twist your body in funny ways to look at things that are at some weird angle to your body and normal position. If this gets bad enough (and, yes, like everything else, I took this to a pretty distant extreme) you'll really fuck your body up. 
&lt;p&gt;
So: If you start to hurt, see a doctor. And start moving around your monitor, chair, etc, to fix it. Don't let it go on, or you'll regret it later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105314408804347254?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105314408804347254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105314408804347254'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_05_01_archive.html#105314408804347254' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105306831618157670</id><published>2003-05-15T23:58:00.000-07:00</published><updated>2003-05-15T23:59:25.893-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Weblogic and exploded ejb deployments&lt;/h3&gt;
Several things I discovered today:
&lt;ol&gt;
&lt;li&gt;If you deploy an exploded ear file, you must deploy all of the ejbs exploded or all of them jarred, otherwise the deployment will choke, as it is hard-coded to have all of them in the same packing format.
&lt;li&gt; If you have some ejb jars pre-compiled and some that have not been, this will generate random results, since the first jar that ejbc happens to hit that is precompiled, it will stop.  This can be worked around with an undocumented deployment order switch in the config.xml, but does not work reliably, and will typically have to fail once for you to generate the config.xml entries that you can then tweak so they work. The undocumented trick is to force the ejb jars that are not precompiled to be first in the deployment order, and the compiled ones all with the same priority and last.
&lt;li&gt;Ant does string replacement based on literals, it does not normalize / and : in path-like strings.  So if, for instance, you're using a &amp;lt pathconvert&amp;gt element that is trying to replace project paths with "" or other strings, you have to not use / or \ in project paths, but instead refer to ${file.separator} when building the output paths.
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105306831618157670?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105306831618157670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105306831618157670'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_05_01_archive.html#105306831618157670' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105258993463951792</id><published>2003-05-10T11:05:00.000-07:00</published><updated>2003-05-10T11:17:49.343-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Apache &lt;tt&gt;mod_proxy&lt;/tt&gt;, your appserver and slow clients&lt;/h3&gt;
Weblogic (and other java appservers) operate in a thread-per-client mode, which means that a single client that is getting a response from your appserver consumes a thread on the server side, and until the message is completely delivered, this thread cannot service any other clients.  Thread per client is both a design choice by the original J2EE designers, and a necessity due to the fact that Java before 1.4 had to have a thread for each client because the way the I/O model was structured.
&lt;p&gt;
Under lab conditions where you have fast clients and very low network latency, having each client consume a thread on the server is totally fine, because the time to send the response to the client is negligable. This allows threads to quickly recycle after they finish their work cycle.
&lt;p&gt;
The problem is, this is actually the best case scenario. Under real-world workloads, where clients are slow and packet loss is rampant, what ends up happening is your server bogs down trying to send data to slow clients. So if one client is on a 56K modem and everyone else is on a T1, that 56K modem will actually consume a thread and impact performance for all the rest of the users on the appserver. The thread that sends the slow client event static content will stay stuck and unable to do useful work until the download completes. This has a very real impact on the server as a whole, because the thread pool will quickly exhaust and people will queue and wait for threads that can service them.
&lt;p&gt;
Originally, before I figured out what was going on, I was boosting the thread pool size on the server to rediculous levels (well over 150) just based on trial and error results from remote load testing across the internet. I had discovered that the higher the thread pool numbers, the faster things seemed to be for people. However, huge thread counts start causing the operating system problems, primarily in scheduler overhead trying to properly do the run queue.
&lt;p&gt;
This is where &lt;tt&gt;mod_proxy&lt;/tt&gt; comes in. This apache module is written in C, has internal response buffers and is intended to deal with tons of slow clients without eating tons of critical OS resources, like threads (which, unfortunately, is not possible before JDK 1.4).  If you put it in front of your application, suddenly, when the threads complete their work cycles, they return the data to the proxy and immediately are ready for service again.  The throughput of your server suddenly skyrockets because the java side of things is actually spending time doing useful work, rather than buffering data to slow clients.
&lt;p&gt;
And, just for your boot notes, the Apache &lt;tt&gt;mod_weblogic&lt;/tt&gt; that comes with the appserver does not release the appserver-side resources until the actual client completes. This is just based on observation of server operation and not empirical testing, and should be further verified, but there is STRONG evidence that &lt;tt&gt;mod_proxy&lt;/tt&gt;  makes much more efficient use of your appserver resources.
&lt;p&gt;
From the Apache &lt;tt&gt;mod_proxy&lt;/tt&gt; documentation (thanks Igor):
&lt;tt&gt;
 When a response is received which fits entirely within the IO buffer size, the remote HTTP or FTP server socket will be closed before an attempt is made to write the response to the client. This ensures that the remote server does not remain connected unnecessarily while the response is delivered to a slow client. A high value for the IO buffer decreases the load on remote HTTP and FTP servers, at the expense of greater RAM footprint on the proxy
&lt;/tt&gt;
So long story short is: make your I/O buffers LARGE in your mod_proxy to take the heat off your appserver.  Reference for &lt;tt&gt;mod_proxy&lt;/tt&gt; &lt;a href="http://httpd.apache.org/docs/mod/mod_proxy.html#proxyiobuffersize"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105258993463951792?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105258993463951792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105258993463951792'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_05_01_archive.html#105258993463951792' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105218145543197262</id><published>2003-05-05T17:37:00.000-07:00</published><updated>2003-05-05T17:44:55.776-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Disable and enable GC mechanisms&lt;/h3&gt;
I just found out that when you enable a GC mechanism (for JDK 1.4) you have to explicitly disable the mechanism you were previously using. Thus, to actually have your app only use the ParallelGC mechanism, you must set TWO switches:&lt;br&gt;
&lt;tt&gt;-XX:+UseParallelGC -XX:-UseConcMarkSweepGC&lt;/tt&gt;&lt;br&gt;
to both turn ON the parallel GC, and turn off the Mark/Sweep algorithm. Also, you need to adjust: &lt;br&gt;
&lt;tt&gt;-XX:ParallelGCThreads=N&lt;/tt&gt;&lt;br&gt;
to match your system, where a "good" value of N is typically 8&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105218145543197262?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105218145543197262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105218145543197262'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_05_01_archive.html#105218145543197262' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105198750275804669</id><published>2003-05-03T11:45:00.000-07:00</published><updated>2003-05-03T11:45:02.670-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;XDoclet for rapid EJB changes&lt;/h3&gt;
If there's one thing I've learned in the past year, it's that any little barrier that you have between you and doing something makes it so it doesn't happen, especially in development when the timelines are short and the pressure is high. This includes having to call people that aren't in the office, and running static leak checkers on your code outside of the build. Or testing your code because it has to be inside the appserver to run.
&lt;p&gt;
Normally, to add or modify an EJB, you have to update 4 files: The &lt;tt&gt;Remote &lt;/tt&gt; interface, the &lt;tt&gt;Bean&lt;/tt&gt; implementation, and potentially the &lt;tt&gt;ejb-jar.xml&lt;/tt&gt; and &lt;tt&gt;weblogic-ejb-jar.xml&lt;/tt&gt; files. To create an EJB, you also have to make a &lt;tt&gt;Home&lt;/tt&gt; interface. All of this is really quite useless from a productivity point of view. I've been through several revisions of code generators  to try and solve this problem, and none of them really worked ALL that well. You may cut the 4 file edits down to 2, but 2 is still too many, and causes a huge pain when things get out of sync. This leads to your ejb code being a total mess. 
&lt;p&gt;
Enter &lt;a href="http://xdoclet.sourceforge.net/"&gt;XDoclet&lt;/a&gt;: The correct approach. This is a code generator that is driven not from an external document, but from actual annotations in the sources.  This lets you edit (or create) one file  for your ejbs, and the system handles the rest. Combine this with an IntelliJ macro, and suddenly the business of making EJBs changes dramatically.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105198750275804669?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105198750275804669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105198750275804669'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_05_01_archive.html#105198750275804669' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105175643072580211</id><published>2003-04-30T19:33:00.000-07:00</published><updated>2003-04-30T19:33:50.660-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Turn logging on and off at runtime&lt;/h3&gt;
If you're using log4j like the rest of the java world seems to be now, there's two really great tricks:
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;Turn logging on and off dynamically&lt;/b&gt;: If you call &lt;tt&gt;PropertyConfigurator.configureAndWatch("log4j.properties", 20 * 1000);&lt;/tt&gt; from a servlet that is set to load on bootstrap in the &lt;tt&gt;init&lt;/tt&gt; method, every 20 seconds it will reload the &lt;tt&gt;log4j.properties&lt;/tt&gt; properties file in the &lt;tt&gt;cwd&lt;/tt&gt; of your program (which, for weblogic is the &lt;tt&gt;wlserver6.1&lt;/tt&gt; or &lt;tt&gt;weblogic81&lt;/tt&gt; directory). This file doesn't have to exist at startup, and will be read if it is created. This lets you ship a canned log4j.properties with your app, then drop a new file in this directory that turns on &lt;tt&gt;DEBUG&lt;/tt&gt; for parts of your app that you need to diagnose at runtime. The only thing to note here is that you need to explicitly set things back to &lt;tt&gt;INFO&lt;/tt&gt; to shut off &lt;tt&gt;DEBUG&lt;/tt&gt; at runtime, simply removing the config line from the dyanamically loaded file will not reset anything.
&lt;li&gt;&lt;b&gt;Disable line numbers&lt;/b&gt;: This is a trick I found from someone else's blog, so I don't take credit for this one. The way log4j finds line numbers for log messages is by actually parsing a stacktrace from a &lt;tt&gt;Throwable&lt;/tt&gt;. So if you want a major boost with logging on, remove the line numbers from your output formatters and things will pick up dramatically.
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105175643072580211?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105175643072580211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105175643072580211'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_04_01_archive.html#105175643072580211' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105175579349385888</id><published>2003-04-30T19:23:00.000-07:00</published><updated>2003-05-10T09:53:54.756-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Send your appserver temp dirs to a second hard disk&lt;/h3&gt;
If you have a second disk in your machine, your appserver startup time can be dramatically reduced by sending the generated output to a second disk. There is a "bug" with weblogic where when you're running an exploded application that it copies all of the files out of the normal application directory into the &lt;tt&gt;.wlnotdelete&lt;/tt&gt; directory during startup.
&lt;p&gt;
To do this you need junction from &lt;a href="http://www.sysinternals.com"&gt;sysinternals&lt;/a&gt;, which lets you create directory hard links in NTFS filesystems. Create a directory on your second disk called &lt;tt&gt;wlnotdelete&lt;/tt&gt;, and then junction the directory &lt;tt&gt;config/&lt;i&gt;mydomain&lt;/i&gt;/applications/.wlnotdelete&lt;/tt&gt; to the &lt;tt&gt;wlnotdelete&lt;/tt&gt; on your second disk. I also did the &lt;tt&gt;config/&lt;i&gt;mydomain&lt;/i&gt;/.wlstaging&lt;/tt&gt;. This VASTLY reduced my startup time; when the appserver starts now, it just does a big cpu burst until it's started, instead of hanging doing tons of disk I/O for a long time. The same appears to be true for hot deploys. 
&lt;p&gt;
One thing that holds a lot of potential is sending your the generated files to a ramdisk. Unfortunately, my application is far too huge (300M in my .wlnotdelete) to make this feasible, but if your app is small enough, this is supposed to be a huge boost. You can get a ramdisk for XP for free &lt;a href="http://www.arsoft-online.de/products/product.php?id=1"&gt;here&lt;/a&gt;
&lt;p&gt;
&lt;i&gt;Post Script:&lt;/i&gt; A friend (hi GP) read this and suggested: "rather than doing it in the application, if you are running on solaris, you will make it go even faster if you  turn off the UFS write throttle (or set the watermarks to something freaking absurd)." .. I am quite interested in trying this, and seeing if the general concept ports to other platforms.
&lt;p&gt;
&lt;i&gt;Post Post Script:&lt;/i&gt;: The above trick, with basically altering the UFS write buffers to be HUGE, works great on Solaris, but there is no logical analog on Windows. One of the design constriants for NTFS is that there are operations that must be guaranteed to be persisted out to disk before the write() method returns to the caller, which is true for things that change filesystem metadata.  So there's no buffer size that I can find to alter that makes any difference for this case.
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105175579349385888?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105175579349385888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105175579349385888'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_04_01_archive.html#105175579349385888' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105172424307614754</id><published>2003-04-30T10:37:00.000-07:00</published><updated>2003-04-30T10:37:23.036-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Another approach to the application server db throughput problem&lt;/h3&gt;
Just was sent a link to &lt;a href="http://www.objectweb.org/c-jdbc/"&gt;c-jdbc&lt;/a&gt; by a coworker (thanks Igor, again), which is an open source jdbc solution to move an existing jdbc application to using a cluster of dbs. Right now, this is focused on open source solutions (JoNAS and PostgreSQL), where it makes an extreme amount of sense. This isn't as much of a great idea for Oracle, as the license fees for the extra dbs would kill you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105172424307614754?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105172424307614754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105172424307614754'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_04_01_archive.html#105172424307614754' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105168416339976277</id><published>2003-04-29T23:29:00.000-07:00</published><updated>2003-04-29T23:29:23.463-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;More on weblogic hotdeploy: now that it's reasonably fast, make it work most of the time&lt;/h3&gt;
So there's another hidden gotcha to weblogic hot deployment: it tends to crash the appserver. Great, huh? You dangle the carrot of not having to spend 5 minutes picking your nose every time you compile, then take it away. But don't give up hope, if you're running the right service pack, it is possible to patch your code (yes, your code must be patched in order to make their code work) so that hot deploy can actually work.
&lt;p&gt;
What I'm speaking to is mostly working around several bugs in weblogic 6.1. The issues are:
&lt;ul&gt;
&lt;li&gt;Weblogic 6.1 Service Packs &amp;lt 4 often just don't work. There are crash bugs in the hot deployment in, I beleive sp3, that just make it not an option. Upgrade to sp4 on your development boxes. Hopefully 7 and 8.1 fix this.
&lt;li&gt;There are various memory leaks in the hot deploy code. A way to work around this (or at least to delay it) is to set &lt;tt&gt;-XX:MaxPermSize=128m &lt;/tt&gt; in your &lt;tt&gt;JAVA_OPTIONS&lt;/tt&gt; in the &lt;tt&gt;startWebLogic.sh&lt;/tt&gt;
&lt;li&gt;Servlets don't un-deploy due to a crash in the Weblogic GenericServlet &lt;tt&gt;destroy&lt;/tt&gt; method. This is where you get to change your code to deal with their bug. You need to edit all your servlet subclasses and override &lt;tt&gt;destroy()&lt;/tt&gt; (if you are not already) and be sure that after whatever processing YOUR &lt;tt&gt;destroy&lt;/tt&gt; does, it does not ever call &lt;tt&gt;super.destroy()&lt;/tt&gt;. The easiest solution is just to implement it as an empty method.
&lt;/ul&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105168416339976277?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105168416339976277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105168416339976277'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_04_01_archive.html#105168416339976277' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105167587457849286</id><published>2003-04-29T21:11:00.000-07:00</published><updated>2003-04-30T10:38:48.846-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;JCache clustered caches: they're not really a database&lt;/h3&gt;
So something that's becoming hot, and is definitely coming as a mainstream j2ee development toolkit, is to use cluster-coherent caches in your j2ee apps. If not the oldest trick in the book, caching has to be the second oldest. The problem comes when your app is expected to run across a cluster of hosts. Caches that get out of sync and start returning inconsistent results are the things of my nightmares. This is where JCache comes in. You can read more about it in &lt;a href="http://www.jcp.org/en/jsr/detail?id=107"&gt;JSR 107&lt;/a&gt;, which is an attempt to make a vendor neutral JCache API. 
&lt;p&gt;
So I've been using the JCache product from my friends over at &lt;a href="http://www.tangosol.com"&gt;Tangosol&lt;/a&gt; (shouts out to Cameron, Alex, Rob and all the gang). All told, great product. It can do all sorts of neat things, like call notification methods when you put data in the cache, etc. Great. And it can either replicate data across a cluster, or distribute it and keep a sortof L1/L2 cache.
&lt;p&gt;
The thing I learned today: Attempting to keep things so they MUST be in cache, and having your application be &lt;b&gt;&lt;i&gt;wrong&lt;/i&gt;&lt;/b&gt; if things are not in cache (such as if you run out of memory) is a terrible idea. It leads to bugs like you'd never beleive, because bad things happen to good people, like running out of memory. It's far better to sometimes be forced to go to the data store (SQL) and incur the network round trip penalty than it is to try and be clobbered when something expires.
&lt;p&gt;
This is not to say that JCache (especially Tangosol) don't do a servicable job at doing most of the things a database does (including distributed queries and indexes). However, if you use them as more than a best effort medium, you really have to hone your development model to using them so you don't get bit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105167587457849286?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105167587457849286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105167587457849286'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_04_01_archive.html#105167587457849286' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105164898506397636</id><published>2003-04-29T13:43:00.000-07:00</published><updated>2003-04-29T21:12:41.073-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Weblogic Hot Deployment: How to waste less of your day waiting to test your code&lt;/h3&gt;

My biggest frustration, and that of many people (I suspect) is the terrible documentation that BEA put out with releases before 8.1 (and possibly even after, I haven't dug fully into those docs, tho they do look better), and actually understanding how the appserver worked enough to make it so that it didn't basically kill their development process. The problem I am referring to is hot deployment, and how the appserver, every time you change something, has to redeploy your code. There is infinite value in being able to immediately test the change you make.  When you work with Weblogic, though, you have to get your code inside the container before it will run.. accessing the ejbs, etc. This basically is death for development, as it makes unit testing things painful, etc. I'll go into how I've learned to live with this over time later.
&lt;p&gt;
The thing that I've been toiling with today is how to speed up the hot deployment process, which is basically how you can get your code into the appserver without actually restarting it. Restarting means restarting database pooling,  and 3,000 other things that means your code won't be able to be run for literally several minutes after the build completes. One of my coworkers said he reads a  Wall Street Journal article every time he compiles and needs to test something. Obviously, I don't like having to pay people to read the newspaper.  I should add up the amount of time we've wasted doing builds and back bill BEA for our wasted development time.
&lt;p&gt;
&lt;b&gt;ANYWAY&lt;/b&gt;: The point of this all is if you deploy as an exploded directory structure if you don't want things to just BITE. There's detail on this &lt;a href="http://edocs.bea.com/wls/docs81/deployment/overview.html#1036349"&gt;here&lt;/a&gt;, which basically tells you how to unpack things. 
&lt;p&gt;
There are two things about hot deployment:
&lt;ol&gt;
&lt;li&gt; Web Application Hot Deploys
&lt;li&gt; EJB Hot Deploys
&lt;/ol&gt;
The first will work basically out of the box if your app is exploded.  Change the JSP in the directory and hit f5 in IE and it's updated. Boom (thanks Igor!). Almost like you're working with &lt;a href="http://www.caucho.com"&gt;resin&lt;/a&gt;, except 10x as expensive. The second one requires actually telling the server to do a forcible deploy, which involves touching a file called REDEPLOY in the META-INF directory of your EAR, which, on my PC, takes about 30 seconds and redeploys the whole app.
&lt;p&gt;
The thing I spent the time with today is looking to see if it was possible to just redeploy the ejb-jar. The fast answer to that was: Weblogic (6.1 thru 8.1 it seems) can only redeploy the whole app. So if you deploy as an ear, you have to redeploy the whole thing. If you deploy as an individual ejb-jar and a war, you can redeploy them individually. My next task is to try moving to separate deployments and see if it speeds up the ejb reload process.
&lt;p&gt;
Also, you may find info online that says touching the &lt;tt&gt;ejb-jar.xml&lt;/tt&gt; file in the ejb &lt;tt&gt;META-INF&lt;/tt&gt; directory will cause the ejb-jar to redeploy, bu this is outdated. The only thing that will cause a redeploy is touching the &lt;tt&gt;META-INF/REDEPLOY&lt;/tt&gt; file.

&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105164898506397636?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105164898506397636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105164898506397636'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_04_01_archive.html#105164898506397636' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105159978958407539</id><published>2003-04-29T00:03:00.000-07:00</published><updated>2003-04-29T13:43:47.533-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Boost your interactive (and enterprise) java performance&lt;/h3&gt;
If you're a common user of interactive java applications, such as the &lt;a href="http://www.intellij.com/idea/"&gt;IntelliJ IDEA&lt;/a&gt; IDE, there are some great VM flags that you can use to boost your interactive application performance. The two, in particular that have helped me the most, are:&lt;br&gt;
&lt;ul&gt;
   &lt;li&gt;-XX:CompileThreshold=5 
   &lt;li&gt;-XX:+UseParallelGC
&lt;/ul&gt;
The -XX:CompileThreshold sets how many times the JIT has to run a method or block before it actually produces compiled code. By default this is a huge number (15,000). Cranking it down to something very small (ie, 5) forces most of the application to compile when the system starts up, which causes a boost of about 30-40% after an initial startup delay. The -XX:+UseParallelGC helps eliminate some of the GC hit (pauses) with JDK 1.4 by making it run concurrently. Both of these tips are actually really handy for enterprise applications as well, where runtime speed is important, but the startup cost can be easily paid ahead of time.
&lt;p&gt;
For IntelliJ, as well as any LaunchAnywhere system, you set these flags by editing a .lax file and changing the &lt;tt&gt;lax.nl.java.option.additional&lt;/tt&gt; line. The lax file for starting intellij is in the IntelliJ-IDEA-&lt;version&gt;/bin directory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105159978958407539?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105159978958407539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105159978958407539'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_04_01_archive.html#105159978958407539' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105157454126818474</id><published>2003-04-28T17:02:00.000-07:00</published><updated>2003-04-29T13:44:08.020-07:00</updated><title type='text'></title><content type='html'>&lt;h3&gt;Boycott netgear access points&lt;/h3&gt;

Never, ever buy one of these access points: 
&lt;a href="http://www.netgear.com/support/products/ME102.asp"&gt;netgear me 102. &lt;/a&gt; &lt;br&gt;
This thing has rarely worked, and now has maigcally changed its SSID to "DORA" and won't reset with the PC configuration utility.
&lt;P&gt;
I've been perfectly happy with my linksys befw11s4.
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105157454126818474?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105157454126818474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105157454126818474'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_04_01_archive.html#105157454126818474' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-5334737.post-105157388770386877</id><published>2003-04-28T16:51:00.000-07:00</published><updated>2003-04-28T16:51:27.850-07:00</updated><title type='text'></title><content type='html'>Ok. This is blogspot try #2. 

I mostly wanted to start this blog so I could bitch about software, and tell people what I've learned so they can avoid the pain I've had to go thru. Ironic that the blogspot software screwed up and failed to create my blog properly. If you're wondering (my first hint), if you have an account on blogspot, agree to be a beta tester.. the beta test software works (while the "production" code crashed for me). Sad that that is my first blog entry.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5334737-105157388770386877?l=burnthacker.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105157388770386877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5334737/posts/default/105157388770386877'/><link rel='alternate' type='text/html' href='http://burnthacker.blogspot.com/2003_04_01_archive.html#105157388770386877' title=''/><author><name>Kris Wehner</name><uri>http://www.blogger.com/profile/12381897412664836258</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry></feed>
