Tuesday, April 24, 2007

My list of stuff to learn

Frequently I find that there are dozens of technologies I want to learn, but really just don't have the time. As a list to myself (and anybody else who might care) of the stuff that I want to learn, but just haven't had the time, here's a short enumerated list:
  • FreeMarker
  • Scheme
  • Groovy
  • Grails
  • Ruby
  • Rails
  • Python
  • JPA (Java Persistence API)
  • EJB Annotations (primarily for Hibernate)
  • XSLT
And that's just the stuff I can remember off the top of my head as I write this. I'm sure that I'll add more later.

Monday, April 23, 2007

Reading blogs pays off

I've recently been trying to read more and more developer blogs in the hopes of improving myself as a developer. One of the blogs I came across is Brian Burridge's, and he recently had a good post about a little utility called Denim. It's a storyboarding/diagramming tool that was originally meant for web developers to quickly model their sites, but I see no reason why it can't be used for user interfaces in general. The program's made in Java so not unexpectedly) its Swing UI is ugly as shit, but it's so functional it's insane. This is how I'd make an interface (though I'd try to pretty mine up), but they got the basics right: functionality before beauty. If you're a serious developer, I think you should at least give it a shot and play around with it. It's free, open-source, and made at an academic institution. BTW, I jacked the latter link right from his page to save anybody reading this some time, not to take away from his blog, which I think you should check out.

Monday, April 16, 2007

The difference between links and forms ... at least for Spring

This post is really just a mental note to myself: the difference between links and forms is that links do not submit form variables. (Duh!) Therefore, you can't bind varibles in forms to Form Backing Objects in spring if you're going to use a link to do the transition rather than a form button.

Friday, April 13, 2007

(Web)Harvesting the web

I was recently assigned a task whereby I had to obtain data from the website of one of our commercial services, but the website is completely Web 1.0 and has no APIs of any kind that
we could hook into. To give you a bit of context, the site performs transactions on our behalf and we need information about those transactions. As my boss saw it, there were only two solutions really available :
1) Have somebody sit at a computer and download the transactions every 15 minutes
2) Have a computer set up to run a screen macro to log in and download the transactions file every 15 minutes (better, but still no where near ideal)

I think without even realizing it, my boss gave me the idea for option three. He continually mentioned the idea of screen-scraping the page to retrieve the information. Traditionally this means taking a visual representation of something and extracting information from what's essentially a picture. After doing some reading, I interpreted his suggestions to mean that I should find a way to do a web-scrape on the page (subtle difference). After doing some research, I found the perfect library for doing it in Java.

It's a project called WebHarvest, and it's fairly simple yet really powerful. You start off by writing a Scraper configuration in XML, load it in code, run the scraper, and it will store your data for you in the Scraper to retrieve when need it. The library itself works by doing either POSTs or GETs to a page, taking the response data, (almost certainly) doing a transform to convert the HTML to well-formed XHTML, and then running XPath queries and regular expressions on the result to get the data you need (ie rows of a table). It's incredibly powerful and if you need a solution where you want to automate logging into a website and retrieving data, then this is a great way to do it.

Monday, March 26, 2007

UTF-8 ... and why you should use it, part 2

I've sadly discovered that my previous post was lacking some bits of information. For starters,
when using tomcat, you should place this directive ( URIEncoding="UTF-8" ) in your connector definition. Then, you should use this attribute ( accept-charset="utf-8" ) with all your forms; this isn't really necessary, just good for practice. Then, you should ensure that you have a filter defined within your web.xml document to coerce incoming requests into UTF-8 format. The easy way of doing this if you're using Spring is to place the following definitions into your web.xml document :


<filter>
<filter-name>charsetFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>charsetFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

This will filter all your incoming requests for you. *Edit* : As one additional side note, if you're moving an existing database to UTF-8 (which is fairly likely since new production databases aren't started that often), then you'll also need to run an ALTER DATABASE statement on the database in MySQL to set its default character set to UTF-8.

Friday, March 16, 2007

Lousy documentation at its finest

This post's going to have to be short because I desperately want to get out of work to go play poker. The short version: I just spent the last three hours in a rage at MySQL because, for a new person following the documentation on their site, it's hard to realize that despite example after example of calling a stored *FUNCTION* with CALL [function name](); syntax, said syntax applies only to stored *PROCEDURES* and you should call a stored function like so : SELECT [function name]();

Fuck, sometimes I hate my job as a developer and I wish I could just go work at a bar, like certain friends. And it's been one of those days.

Tuesday, March 13, 2007

Intricacies of Hibernate

If you're a serious developer / software engineer, then you know how important it is to keep a system you're building as modular as possible for all the standard reasons: separation of concerns, testing, etc . To this end, I've been developing my systems at work to use Data Access Object interfaces, rather than giving them direct exposure to hibernate. One of the benefits of this is that it abstracts my business and presentation layers from my persistence layer. One of the detractors is that it makes it harder to do certain other things:
  1. Maintain efficiency when performing database operations
  2. Use Hibernate effectively when loading / storing objects.
Case in point: for the last two days I've been trying to figure out why my detached objects keep having exceptions thrown regarding dirty collection references when I try to update them. As it turns out, the Session.update() function is really best used within the context of a transaction, where you modify your business objects within the transaction, so the persistent objects never become detached (this last portion is a lot more meaningful if you're familiar with Hibernate parlance) However, in a well modularized Web application, your business, presentation and persistence layers are detached so one never knows that your business objects are being persisted with Hibernate, and as such you must 'detach' your business objects from their sessions. Updating them in a new session won't work if you want to use Session.update. Instead, you need to use Session.merge . The subtle difference between these two is that .update checks things like dirty member collections and caching, whereas .merge verbatim overwrites the existing state of your business objects' members in the database. It took me two days to realize this and I'm very pissed off. I really wish it had been mentioned in the Hibernate documentation.

Friday, March 09, 2007

I still don't know enough, but I know something

For quite a while I've wanted an easier way of using Jasper Reports in my web applications. My first go around with Jasper Reports involved implementing custom servlets for Jasper reports and using (what I now realize is) a giant kludge to add to and maintain those reports and compile and run them on the fly. I've clearly learned a lot since that first try. My second go around with Jasper Reports involved precompiling them with an Ant task and using report views in Spring after I moved to the Spring framework. This was a lot better than what I had been doing, but I still made mistakes when I didn't quite know the best way to get parameters into my report.

Now I'm about to start with round three. This round started with an epiphane the other day: why not use a tag library to insert a Jasper Report into a page rather than dealing with entire views ? This would surely be far more compact and would even look far better. After googling for several hours and finding nothing even close to satisfactory in this regard, I decided to make my own tag library. I whipped up the tag library tutorial on Sun's website, and within a couple of hours, I had the very beginnings of a rudimentary tag library going, and I had successfully embedded a Jasper report within a page of one of my web apps. (It was a piece of shit test report embedded within a div, but it was more than enough for proof-of-concept).

This short snippet:
<div style="overflow: auto;">
<jr:report printerName="${printerName}" reportName="test" reportParameters="${sessionScope.mymap}"/>
</div>

Showed just how powerful and useful tag libraries can be. Combining this with Spring's dependency injection made things a lot easier too. I thought to myself: this could be really useful. And I was really surprised that nobody else had done this already. In light of my epiphane, I think I'm going to start up a source forge project for this, probably call it JasperTags. Who knows, it might even be useful. But there's a bunch of other stuff I need to learn first, like Maven 2, JIRA, and numerous other little useful developer tools so I can at least put on the facade of being a competent open source developer.

Monday, March 05, 2007

RAD, Spring, and thoomp!

Ok, so only the first two of the title trio have anything to do with each other. The latter's just the sound an air cannon makes and I thought it went well here. Moving on:


One of the best things about the Spring Framework for Java is that thanks to the fact that it's an Inversion of Control (IoC) container, you can very easily add to projects and update them with new code. The latest thing I did with one of my Spring-based projects was to add notifiers when certain batches are uploaded to the system. The first notifier I did was an email notifier, so nothing special. But immediately after I finished implementing it, my "Wouldn't it be cool if ..." sense kicked in and I considered implementing a notifier for MSN Messenger so that certain people in our organization could receive instant notification for batch uploads. After two minutes of google searching, I came upon the JML (Java MSN Messenger Library) posted on SourceForge.net . After a few minutes of looking at the example code posted with the project (still fairly sparse), I came up with the following to inject an ApplicationListener into my Spring context:

<bean id="msnMessenger" class="net.sf.jml.impl.MsnMessengerFactory" factory-method="createMsnMessenger" init-method="login" destroy-method="logout">
<constructor-arg value="my-email@hotmail.com"/>
<constructor-arg value="mypass"/>

<property name="logIncoming" value="true"/>
<property name="logOutgoing" value="true"/>
</bean>

<bean id="msnMessengerNotifier" class="my.package.ApplicationListenerImpl">
<constructor-arg ref="msnMessenger"/>

<property name="recipients">
<map>
<entry key="email_of_our_batch_processing_guy@ourcompany.com" value="His Name"/>
</map>
</property>
</bean>

...and the relevant implementation code :

this.msnMessenger.sendText(Email.parseStr(emailAddress), messageString);

...and in under 20 minutes I had an instant messaging notifier implemented thanks to the ease of Spring and the JML library. Please go see that site if you need instant messaging in Java with MSN Messenger, it's actually a great little project and they deserve to be supported. It seems however, that the one little caveat of this (and it's not even JML's fault) is that the notifier and the person receiving the notification must have each other on their contact lists.

Sunday, February 25, 2007

I've lost all meaning for the term "day off"

I have. Really. I'm sitting around researching screen scrapers (because it'll be horribly useful for work, sadly) and while Googling and reading blogs, I've come across a very useful looking tool called Firebug (http://getfirebug.com/) that lets you inspect and modify a page's DOM in real time. The original thread that prompted this was of course searching for existing methods of web scraping. I found a pretty good looking thread on this guy's blog which I can't wait to try out at work on certain pages that I probably can't mention in a personal blog. Suffice it to say that the content of that blog entry has me convinced, now more than ever, that Firefox is hands down the best browser ever.

<edit> This page is super useful for learning screen scraping with Ruby </edit>

Staying on the ball

If you know me, then you've seen my analogy with two fists to staying on the ball. If not, just know that it's a great analogy. The real topic of this post is that as a software developer, during the course of your education (if you have one beyond high school) you can't help but have this one idea beaten into you: you have to stay current with trends in software development and you have to be on the ball with learning new tools to get the job done quicker, otherwise you will find yourself out of a job.

As I read through blogs, articles, newsfeeds, etc, I'm learning more and more how behind the times I really am. I think part of that is due to my education, ironically enough: there's enough out there that you need to know to be truly effective in the workplace that they can't possibly keep up in universities and colleges, which makes it all that much harder to get a really good job that's going to pay you a lot of money. As a result, you have to find a way to keep up and stay current on your own or risk being left behind in a heap of a job with shit for pay. I don't want to do the latter. It's with that in mind that I realize there are some buzzwords / buzztechnologies that I should at least be familiar with if not know intimately and use on a day-to-day basis:

1. .NET / C# / ASP.NET : There's an assload of jobs out there that use this rather than Java or any of the popular open-source technologies. And unless you go a technical institute, they don't teach you this; it's something you have to learn on your own. The need to learn .NET and other Microsoft technologies has recently been burnt into my own mind after I went for a job interview and they went with somebody else, not because I didn't know .NET (but could learn it very rapidly given my existing experience) but because they could get a technical institute (*cough* NAIT *cough*) grad with maybe a tenth the software development experience far cheaper than a university-educated developer.

<interlude>
My experience is mainly with free and open source (FOSS) technologies like Java, Spring, Hibernate, Javascript, XML, HTML etc with a fair bit of Ruby and some Perl / Python / BASH scripting thrown in. While certainly very interesting and academically stimulating areas of software development, they unfortunately don't look nearly as good on a resume as does Microsoft technologies, which a majority of companies are very much locked into.
</interlude>

2. XQuery, XML databases, XSLT, Atom/APP, XForms, AJAX: All XML related technologies, their goal is to make web development easier and make web-based applications more robust and usable. I think it's important I at least get familiar with these technologies, if not use them on a day-to-day basis for my projects at work.

<interlude2>
As somebody who's graduated from a Canadian university with a degree in Engineering, I have the chance (and desire) to get my PEng designation. However, due to certain restrictions of my local engineering association, I have to meet certain strict requirements with regard to the work that I do. Some of those restrictions include having to work on engineering-related software (ie essentially engineering software for other engineers and engineering projects).
</interlude2>

3. Embedded devices / Device drivers / System-level development: this is something that has long garnered my interest, but that I've never had the time to devote to learning. I'll especially need it if I'm to accomplish certain career objectives as mentioned above.

There's a number of other technologies / etc, whatever that I can go on about that I need to learn, but it's really too numerous to mention in a single blog post. I've enumerated three balls that I want to be on, and to accomplish that, I'm going to have to jump from ball to ball on a constant basis and hope I don't fall flat on my ass.

Friday, February 23, 2007

Internet Explorer quirks

What I'm about to say is neither a new thought nor a new sentiment in the least: Internet Explorer sucks.

I don't just say that because I'm a huge fan of many other browsers, but because as somebody who develops applications that have to be completely browser-agnostic, dealing with Internet Explorer is a fucking pain. The quirk that's got me today is this: Internet Explorer doesn't properly handle XHTML. The consequence of this is that it doesn't recognize self-closed script tags as valid (ie <script src="blah.js" type="text/javascript"> ) and as a result will biff if you try to use them. Firefox, Opera and SeaMonkey all have no problem with it. Unfortunately I don't have a Mac with which to try out Safari and Camino, but the point is that using the above code snippet will cause Internet Explorer to NOT EVEN RENDER THE PAGE. It strikes me that this is a horrible bug, especially for a large corporation like Microsoft. It's this kind of BS that drives people to better solutions. I feel bad for the people who haven't realized there's better shit out there than IE. Sorry for the harsh language, but yes, I'm bitter.

Thursday, February 22, 2007

The things every user should know about Linux / Unix

There's a ton of things every user should know about Linux / Unix, and I'll be the first to admit that I don't know nearly as much as I should. Here's some basic stuff though (I'll enumerate it as much to remind myself as to inform others) :
user[add|mod|del] - Administrate users. As with anything else, read the man pages and learn the arguments they take inside and out.
group[add|mod|del] - ...same thing, just for groups.
chsh - Change your shell
echo $0 - Get the name of the shell you're currently running
whoami - Lets you know what user you're running under
users - Lists all the users currently logged into the system.
echo "stuff" /dev/pts/[some integer here] - Echoes text to the running pts, good for command line communication with other users.

Some important locations:
/etc/groups - Stores all of the system's user groups
/etc/passwd - Stores all of the system's user information

There's a ton more that should go in here, but I need to finish this post and start a new one. So yeah ... done.

Sunday, February 11, 2007

Fucking quirks

In an attempt to make one of my web applications more user friendly and bulletproof it against silly people at the same time, I've been adding Javascript to a lot of the pages. The basic functionality and validation is already there, but I've decided to use Javascript to help make a lot of the repetitive tasks go quicker and generally make the app easier to use:

This means automatically selecting certain options when other options are selected, putting in "Select All" and "Select None" buttons for large lists of items, etc. It's during these times that I've come across (1) one of Javascript's (in particular) little quirks, and additionally (2) a larger issue which affects all scripting languages.

1. In Javascript, when you want to select all the checkboxes (or radio buttons) in a form (or even a particular set), Javascript becomes quite inconsistent: if there's only one element in the group, it returns the element itself, rather than an array. I'll let you mull that over for a couple seconds, then keep reading.


Done ?

Ok. Speaking to any developers out there (or anybody else who's written code) who may be reading this, is that not the most retarded idea ever ? Seriously. That's just asking for trouble and wasting large amounts of time unnecessarily on debugging, especially for somebody unfamiliar with (and trying to learn) the language. Not to mention the fact that it leads to further code cruft due to (in my mind) unnecessary case checking that could be eliminated if something like form.checkboxes or form.radios returned a collection in any case, regardless of how many elements would be in the set. I mean, come on! Admittedly, I've had far less experience than the people who designed and implemented the Javascript language, but I think that kind of design decision is retarded on any level. I'm sorry guys, but it is.

2. While trying to debug the above mess, I came across the larger issue that always affects scripting languages: the lack of strongly-typed objects. By this very nature of scripting languages, this makes debugging harder than any given strongly-typed language, and it sucks. I suppose though, in all fairness to the Javascript language, it's the implementors that are responsible for providing help with debugging. On that note, Microsoft (and Internet Explorer X.X) are horrible for that sort of thing, displaying only "[object]" when trying to put an object to a string. Firefox is a bit better, in fact, it was Firefox that got me through my little ordeal above when I was expecting to see something like "[array]" and it gave me "[object HTMLInputObject]". Thank you Firefox and the developers working on the Mozilla project, it seems like you actually know something and understand what programmers have to go through when debugging things. To the people at Microsoft, how have you not thought of shit like this ? You suck.

Monday, February 05, 2007

Google and Firefox are officially fucking scary

To give you a little bit of background, I recently upgraded to Firefox 2.0 and I frequently use the hotkeys and search bar. A lot. More than you'll ever know. The Firefox search bar has had the ability to bring up entries that you've searched for in the past for quite a while, so I didn't notice this little trick until just recently :
When you have Google selected as your current search engine (I frequently use others as well, such as Wiki), it will automatically search for possible matches for what you're typing in and suggest them to even if you've never searched for it before. That in itself is a neat little trick, but the relevance of the results today astonished me when I wanted to search for the lyrics to "I believe in a thing called love" by The Darkness. I started by typing "the darkn" and right then and there "the darkness lyrics" was the third entry in the suggestion list. When I got to "the darkness i ", "the darkness i believe in a thing called love lyrics" was the first entry in the list. Is it just me, or has Google's seeming omnipotence combined with its usefulness and relevance gotten downright fucking disturbing ? I'm going to revel in this realization the rest of the day.

Friday, February 02, 2007

UTF-8 ... and why you should use it.

I've recently discovered that for the sake of compatibility with various languages and internationalization, that UTF-8 should be used for everything. That might sound like
a very vanilla statement with nothing to back it up, but I really don't have time to go into
the reasons I've discovered for using UTF-8. Also, suffice it to say that it has now been
forced on me as a requirement, one which I don't mind adhering to, but it takes some
effort to convert. Case in point is using Hibernate as your persistence framework. If you're
using XDoclet2 to generate all your mapping files from annotations, the conversion is very simple. In your component definitions in your ant task, make the the following changes:
<component classname="org.xdoclet.plugin.hibernate.HibernateMappingPlugin" destdir="${basedir}/src" version="3.0">

and :
<component destdir="${src.dir}" classname="org.xdoclet.plugin.hibernate.HibernateConfigPlugin" jdbcdriver="${jdbc.driver}" jdbcpassword="${jdbc.password}" jdbcurl="${jdbc.url}" jdbcusername="${jdbc.username}" dialect="${hibernate.dialect}" cacheprovider="${hibernate.cache.provider_class}" cacheusequerycache="${hibernate.cache.use_query_cache}" jdbcpool="" jdbcisolation="${hibernate.connection.isolation}" showsql="${hibernate.show_sql}" version="${hibernate.version}" style=""/>

... and that's all there is to updating Hibernate to generate your files with UTF-8 encoding. However, if you're making a web app, that's not the only thing that you're going to have to change. All your JSP(X) files should start with the following :

<jsp:root jsp="http://java.sun.com/JSP/Page" version="2.0" c="http://java.sun.com/jsp/jstl/core" fmt="http://java.sun.com/jsp/jstl/fmt" spring="http://www.springframework.org/tags" display="urn:jsptld:http://displaytag.sf.net" authz="http://acegisecurity.org/authz">

<jsp:directive.page language="java" contenttype="text/html; charset=UTF-8" pageencoding="UTF-8">

<jsp:output declaration="false" element="html" public="-//W3C//DTD XHTML 1.0 Transitional//EN" system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

... or something very similar, the key point being that the encoding(s) specified are in UTF-8.
Also, since you're most likely using a database if you're using a web application, you'll need to update your database settings. One of the most common databases out there (and the one that I use) is MySQL. To permanently change the settings of MySQL to use the UTF-8 collation, you'll have to find your appropriate 'my.cnf' file and put this line:
default-character-set=utf8

...under the [client] and [mysqld] headings.

Thursday, January 11, 2007

The business doesn't go away ...

Holy crap, things are just getting more and more busy here at work, but I just had to take a break to blog this so I don't forget about it in the future. I've been trying to install SSL for Tomcat 5.5 on a Windows 2000 Server setup, and I've been having so luck getting it to work. I've followed the instructions to a T, and yet still nothing would work. I googled for hours on end trying to find out what was going on, but for no luck. This was yesterday. Being as obsessive as I am about software, I couldn't just let it drop when I left, and I kept thinking things over. I thought it might be an issue with the name of the keystore in Windows (.keystore), but that wasn't it. Then I found a very interesting forum post:

> From: Jim Reynolds [mailto:jim.jreynold@(protected)]
> Subject: SSL Setup From Site
>
> 4) restarted tomcat, but I do not get ssl?

If you used the .exe download for Tomcat, you may have APR installed.
Its SSL configuration is rather different than that for Tomcat's pure
Java connector. The doc for APR is here:
http://tomcat.apache.org/tomcat-5 (See http://cat-5.ora-code.com).5-doc/apr.html

Alternatively, disable APR by deleting or renaming bin\tcnative-1 (See http://ive-1.ora-code.com).dll,
and then the standard SSL handling (which appears to be what you
configured) will be in effect.

- Chuck

As it turned out, I did use the installer to do the install on the Win2k Server setup, whereas I didn't before. So I went and found $CATALINA_HOME/bin/tcnative-1.dll was indeed there, moved it out to another folder (since you should never delete thing like that in case they're not the problem), restarted Tomcat, and lo and behold, it worked. The amount of relief that got off my chest was huge. The config file I used for the install used this SSL connector in the $CATALINA_HOME/conf/server.xml file :

port="8443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="C:\path\to\my\.keystore"
keystorePass="mychangedpass"
keystoreType="JKS"
debug="9"
/>


So if you're having these problems in a Windows install of Tomcat and you're reading this, I hope this helps.

Thursday, December 14, 2006

Still wicked busy...

I've been putting off posting to this blog longer and longer, and I really dislike doing that. The subject of today's post is more a rant than anything else. I've had to switch off dealing with projects that use Spring WebFlow for the moment and switch back to reporting, which means that I've had to deal with JasperReports and iReport again. This time it means looking into the Charting capabilities of iReport, and from what I'm seeing, they're so piss-poorly documented by everyone (including the people who make it) as to be a pointless and useless feature. I'd kill for a good tutorial on it right now, but the fact remains that there's nothing useful out there. At best there's a couple tutorials that scratch the surface, and don't lend themselves to any practical implementation. Ok, bitching done. I'll start coming out with much more useful posts in future, most notably with code and examples to hopefully fill the gap that is a lot of the internet as far as I see it when it comes to development.

Monday, December 04, 2006

Go with the flow

I've recently discovered the joy that is Spring WebFlow. For those not in the know, it's a Java web component specifically meant for the C in MVC (Model-View-Controller architecture). It allows you to declaratively define logical flows of information within an XML file, define a few Java beans to fit into the flow, and combine them all together to get your work done in a very short amount of time. Does my description sound kind of high level, abstract, vague, airy-fairy ? Well, then that description goes pretty well with Spring WebFlow (SWF) because SWF abstracts a LOT of gory details. I'll go into detail on it in a later post, I just thought that I'd bring it up now because I'm super busy at the moment, haven't posted anything in a while, and thought that I should.

Monday, November 06, 2006

You can alias beans !

That sounds like a a crazy statement to any normal person not familiar with Java, or at least to my coworkers, as normal as they are. I discovered several days ago that you can assign aliases to beans in the Spring framework for J2EE, and at the time I wondered why you'd ever want to do that. I now realize why: say you have a datasource that you share among numerous aspects of your system: transactions, reports, other stuff (but most importantly the first two.) Now say that your database is growing along with your customer base and it's getting way too (computationally) expensive to run reports on your production database. Just point your report bean aliases to a new data source bean after setting up a DB replication of your main database that gets updated every night, or every few hours. Then you've effectively switched your system over to a load balanced method without changing any of your production code. Genius!