<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>sutrotech</title>
	<atom:link href="http://www.sutrotech.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sutrotech.com</link>
	<description>simple things simple, complex things possible...</description>
	<pubDate>Sat, 14 Feb 2009 19:42:58 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Slacker Elves in the Amazon Cloud</title>
		<link>http://www.sutrotech.com/2008/07/slacker-elves-in-the-amazon-cloud/</link>
		<comments>http://www.sutrotech.com/2008/07/slacker-elves-in-the-amazon-cloud/#comments</comments>
		<pubDate>Tue, 08 Jul 2008 23:43:03 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.sutrotech.com/?p=55</guid>
		<description><![CDATA[
One of my current projects has been building a framework for automatically
provisioning and deploying servers into the 
Amazon EC2 cloud.

So, I have scripts that ask Amazon to start an EC2 instance, wait for
Amazon to tell me that they are 'running', and then try to SSH into
the instances to do things to them.


One vexing issue I [...]]]></description>
			<content:encoded><![CDATA[<p>
One of my current projects has been building a framework for automatically
provisioning and deploying servers into the 
<a href='http://www.amazon.com/gp/browse.html?node=201590011'>Amazon EC2</a> cloud.

So, I have scripts that ask Amazon to start an EC2 instance, wait for
Amazon to tell me that they are 'running', and then try to SSH into
the instances to do things to them.
</p>
<p>
One vexing issue I ran into is that often the ssh connection would fail
while running the script, yet I would have no problem ssh'ing manually
afterwards.  I spent some time <a href='http://www.google.com/search?hl=en&client=firefox-a&rls=org.mozilla%3Aen-US%3Aofficial&hs=PPh&q=ssh+fails+new+ec2+instance&btnG=Search'>googling the problem</a>
and found some people having similar mysterious failures, but
no concrete solutions.
</p>
<p>
The failure mode for me during script execution looked exactly like what you
see when you've screwed up your keys somehow: running with -v, you can
see it tries public-key, has no luck, and moves on to ask for a password.
That definitely is not going to work because a) it's not interactive and
b) there is no root password on a fresh EC2 instance.
</p>
<p>
So, what is the problem?  Well, I have not really figured it out, but I
have come to realize that there is a period of time after the Amazon says
the instance is 'running' during which it will still reject all SSL connections.
The period of time seems to vary between 30 and 60 seconds, and seems to
increase during what I would assume are peak usage hours.  
</p>
<p>
I speculate that somewhere in the cloud is a little elf that runs
around distributing Amazon's half of the keypairs to all newly-started EC2 
instances.  The lag in SSL connectivity is due to the elf getting tired and/or busy,
and the monitoring machinery is not designed to wait for him to finish before
it declares that an instance is 'running'.
I've not been able to confirm that this is the case, but I'm sure
<a href='http://en.wikipedia.org/wiki/Occam%27s_razor'>Occam</a> would favor 
explanations involving lazy elves.
</p>
<p>
A crude way around the problem is to simply sleep for a minute or so
before trying to establish a connection.  A slightly less crude way
is to repeatedly attempt to SSH in after the instance starts.
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2008/07/slacker-elves-in-the-amazon-cloud/feed/</wfw:commentRss>
		</item>
		<item>
		<title>lodi 0.1.0 released</title>
		<link>http://www.sutrotech.com/2008/03/lodi-010-released/</link>
		<comments>http://www.sutrotech.com/2008/03/lodi-010-released/#comments</comments>
		<pubDate>Fri, 28 Mar 2008 18:51:24 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pcal.net/blog/?p=41</guid>
		<description><![CDATA[
Along with SQLsheet, I'm open sourcing another library that I've written: lodi (Local Dispatch).


A lot of my work lately has relied on generating XML using templates (I'm using Velocity).  The XML is mostly used to either drive an ETL process,
specify some XHTML to get rendered, or to configure some internal subsystem.


It gets complicated, though:


 [...]]]></description>
			<content:encoded><![CDATA[<p>
Along with SQLsheet, I'm open sourcing another library that I've written: lodi (<b>Lo</b>cal <b>Di</b>spatch).
</p>
<p>
A lot of my work lately has relied on generating XML using templates (I'm using <a href='http://velocity.apache.org/engine/devel/vtl-reference-guide.html'>Velocity</a>).  The XML is mostly used to either drive an ETL process,
specify some XHTML to get rendered, or to configure some internal subsystem.
</p>
<p>
It gets complicated, though:
</p>
<ul>
  <li>Sometimes that XML gets consumed outside the VM via HTTP, and sometimes it gets consumed inside the VM.
  <li>In either case, I need to be able to embed template parameters in a URL (i.e., query stirng).</li>
  <li>I want a uniform method for addressing the templates (inside or outside the VM)</li>
  <li>I want a uniform method for processing and organizing the templates in the webapp</li>
  <li>Some of the templates I want locked down from the outside - I don't want them served out over HTTP</li>
  <li>...except that sometimes I do.  For debugging, it turns out to be really handy to be able to peek at template instantiations in my browser.</li>
</ul>
</p>
<p>
My solution was to create a backdoor URL dispatcher for internal clients.  So, from outside I can access a template as
</p>
<p>
  <code>http://localhost/foo/bar/baz.vm?name=roger</code>
</p>
<p>
whereas from inside the VM (and only inside the VM) I can access it as
</p>
<p>
  <code>myapp:/foo/bar/baz.vm?name=roger</code>
</p>
<p>
  One nice thing about this is that the <code>myapp</code> URL will bypass the container security.  This means that I can be free of having to authenticate when calling internally without having to do unnatural things to my web.xml security configuration to lock it down from outside.
</p>
<p>
Another nice benefit is that the servlet request gets processed in the caller's thread.  This lets me propagate any Exceptions encountered while  directly back to the caller, which makes debugging and error handling a lot simpler when there are problems in a template.
</p>
<p>
<a href='http://www.pcal.net/blog/?page_id=39'>(more...)</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2008/03/lodi-010-released/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SqlSheet 0.1.0 released</title>
		<link>http://www.sutrotech.com/2008/03/sqlsheet-010-released/</link>
		<comments>http://www.sutrotech.com/2008/03/sqlsheet-010-released/#comments</comments>
		<pubDate>Thu, 27 Mar 2008 19:02:23 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pcal.net/blog/?p=35</guid>
		<description><![CDATA[
There are a number of  JDBC-Excel drivers out there, but most seem to be nearly abandoned.  Moreover, they all either use native pieces, are read-only, or do disconcerting things with in-memory databases, none of which work for me.


So, what is a self-respecting hacker to do besides write their own?  Here's the nutshell:


SQLSheet [...]]]></description>
			<content:encoded><![CDATA[<p>
There are a number of  JDBC-Excel drivers out there, but most seem to be nearly abandoned.  Moreover, they all either use native pieces, are read-only, or do disconcerting things with in-memory databases, none of which work for me.
</p>
<p>
So, what is a self-respecting hacker to do besides write their own?  Here's the nutshell:
</p>
<p>
<b>SQLSheet</b> is a JDBC driver which allows you to interact with Microsoft Excel
spreadsheets using SQL statements.
</p>
<p>Features:
<ul>
  <li>Pure Java (no native components)</li>
  <li>Fast (operates directly on the spreadsheet, does not rely on an in-memory database)</li>
  <li>Read and write operations</li>
  <li>PreparedStatement support</li>
</ul>
</p>
<p>
Now, if you just want to manipulate spreadsheets, just use <a href='http://poi.apache.org/'>Apache's POI</a> - it's great.  Why is SqlSheet useful, then? Mainly for manipulating spreadsheets inside other tools that are database-oriented.  You can just give them a <code>jdbc:xls</code> URL and start doing whatever you normally do.  In my case, I specifically wanted to be able to manipulate spreadsheets from inside the <a href='http://scriptella.javaforge.com/'>Scriptella ETL</a> framework.
</p>

<p>
<a href='http://www.pcal.net/blog/?page_id=40'> (more...)</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2008/03/sqlsheet-010-released/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Switched to Wordpress</title>
		<link>http://www.sutrotech.com/2008/03/switched-to-wordpress/</link>
		<comments>http://www.sutrotech.com/2008/03/switched-to-wordpress/#comments</comments>
		<pubDate>Thu, 27 Mar 2008 05:23:05 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pcal.net/consulting/?p=36</guid>
		<description><![CDATA[
While I can't think of anything much more boring than blogging about blogging, I will do it just briefly because here there might be a few useful bits of information here that are useful...


I just switched from MovableType 4 to WordPress and am overall very pleased.  It's faster, cleaner, simpler, and seems to have [...]]]></description>
			<content:encoded><![CDATA[<p>
While I can't think of anything much more boring than blogging about blogging, I will do it just briefly because here there might be a few useful bits of information here that are useful...
</p>
<p>
I just switched from MovableType 4 to WordPress and am overall very pleased.  It's faster, cleaner, simpler, and seems to have a stronger community.  It's PHP based, which I much prefer to MT's weird template tags.  A couple of pitfalls:
</p>
<p>
If you are like me and like to write your entries in raw HTML, there are a couple of things you need to do:
<ul>
  <li>Go to 'Users', click 'Edit' on your username, and uncheck 'Use the visual editor when writing'</li>
  <li>Download the <a href='http://wordpress.org/extend/plugins/raw-html/'>Raw HTML plugin.</a></li>
  <li>Or, better yet, use my <a href='/stuff/raw-html-hacked.zip'>hacked version</a> which is always on (i.e., doesn't require the magic 'raw' comment delimiters).</li>
</ul>
</p>
<p>
Also, don't mess around with symlinks or <code>.htaccess</code> - this seems to somehow cause problems with deleting comments and posts.  If you come from MT, it's tempting to do this because WordPress wants to live under your document root, whereas MT publishes static pages into a separate directory.  My advice is to just put WordPress in your <code>public_html</code> dir where it wants to be - it feels weird but it's ok.
</p>
<p>
Finally, I highly recommend downloading the <a href='http://www.siolon.com/2007/persistent-styles-plugin/'>Persistent Styles Plugin</a> so that you can non-destructively tweak wordpress templates.
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2008/03/switched-to-wordpress/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PropJoe</title>
		<link>http://www.sutrotech.com/2008/03/propjoe/</link>
		<comments>http://www.sutrotech.com/2008/03/propjoe/#comments</comments>
		<pubDate>Tue, 18 Mar 2008 06:40:49 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=29</guid>
		<description><![CDATA[
I have long had this irritating problem with .properties.  It goes something like this:



I like to use  .properties files for configuration unless there is a compelling reason to use something more complicated.
I'm pretty uptight about using constants in my code.  This includes using constants to refer to the names of properties in [...]]]></description>
			<content:encoded><![CDATA[<p>
I have long had this irritating problem with <code>.properties</code>.  It goes something like this:
</p>
<p>
<ul>
<li>I like to use  <code>.properties</code> files for configuration unless there is a compelling reason to use something more complicated.</li>
<li>I'm pretty uptight about using constants in my code.  This includes using constants to refer to the names of properties in a <code>.properties</code> file.
<li>Over time, the constants and the <code>.properties</code> file can drift apart - you have to keep them both in sync.</li>
<li>Similarly, properly documenting them both becomes a painful</li>
</ul>
</p>

<p>
So, I proceeded to finally do something about it.  I spent about 15 minutes writing the code and 45 minutes writing the documentation, go figure why.  Maybe it's because <i><a href='http://www.hbo.com/thewire/'>The Wire</a></i> is over and I think I just needed to do something to say goodbye.  At any rate, I have found it has made my life just a little bit easier.
</p>
<p>
With that, I give you, <a href='/downloads/propjoe/javadoc'>PropJoe</a>.
</p>
<p>
<a href='/downloads/propjoe/javadoc'>docs</a> | <a href='/downloads/propjoe'>download</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2008/03/propjoe/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Create a custom .EXE to launch Tomcat</title>
		<link>http://www.sutrotech.com/2008/01/create-a-custom-exe-to-launch-tomcat/</link>
		<comments>http://www.sutrotech.com/2008/01/create-a-custom-exe-to-launch-tomcat/#comments</comments>
		<pubDate>Wed, 09 Jan 2008 01:20:20 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=28</guid>
		<description><![CDATA[
In developing data integration applications for Windows users, it's really important to provide
them with the most
Windows-like experience as possible when it comes to installation, starting, and
stopping the server.  This has long been a painful topic
for Java developers.  (Don't even get me started about Java WebStart... :) )





My applications run inside Tomcat, and I [...]]]></description>
			<content:encoded><![CDATA[<p>
In developing data integration applications for Windows users, it's really important to provide
them with the most
Windows-like experience as possible when it comes to installation, starting, and
stopping the server.  This has long been a painful topic
for Java developers.  (Don't even get me started about Java WebStart... :) )
</p>


<span id="more-40"></span>
<p>
My applications run inside Tomcat, and I should note also that Tomcat does include
a native Windows launcher that may be sufficient for many purposes.
In my case, however, I don't want my users to know that they are running Tomcat.
I want to have complete control over the startup environment and the outward
appearance of the app.  I also don't want my users to have access to the
configuration options that
come with the Tomcat system tray icon.
</p>
<p>
Fortunately, there are some reasonable options out there, and the best I have
found is
<a href='http://launch4j.sourceforge.net/'>Launch4j</a>.
I'm going to describe the broad
strokes of how to create a Launch4j exe that starts up Tomcat for you.
Over all, I've been very pleased with the results, and would recommend this
to anyone who is deploying primarily to Windows users and wants to deploy
their app in a professional-feeling package.
</p>

<p>
I should also note that
<a href='http://www.javalobby.org/articles/tomcat2go'>this entry by Roshan Shrestha</a>
from several years back provided a very helpful starting point.
I've updated and simplified what he did there,
and I also opted to use Launch4j instead of JSmooth as it seems to be more
up to date.
</p>

<h3>Overview</h3>

<p>
In short, my requirements were:
</p>

<ul>
<li>Provide a native .EXE that launches Tomcat</li>
<li>Appear in the taskbar like a regular .EXE</li>
<li>Take the user to a download page if they don't have a JRE installed</li>
<li>Open the user's browser after the server is launched from the EXE</li>
<li>Allow me to provide a custom icon and splash screen</li>
<li>In general, just 'feel' as much like a native Windows app as possible</li>
</ul>

<p>
There are 5 basic steps you need to do to get this going:
<ol>
<li>Create a main class to start Tomcat</li>
<li>Ensure that the Catalina environment gets initialized</li>
<li>Create a Launch4j Configuration</li>
<li>Create an icon and a splash screen</li>
<li>Set up an Ant script to put it all together</li>
</ol>

<p>I describe these steps in more detail below.</p>

<h3>Create a main class to start Tomcat</h3>

<p>
At the end of the day, Launch4j just invokes a main method and then dies.
In our main method, we want to start Tomcat and then start the user's
browser pointed at the new Tomcat instance.
</p>
<p>
The listing of <b>TomcatLauncher.java</b> below shows what you need to do.  Note the two key dependencies:
on Tomcat's Bootstrap class for starting tomcat, and on ejalber's
very useful BrowserLauncher for starting the user's browser.  (You'll need
to download the BrowserLauncher source and integrate it into your build).
</p>



<h3>Ensure that the Catalina environment gets initialized</h3>

<p>
The default Tomcat startup scripts do some mucking around to set
various system properties when Tomcat is actually launched.  We need to
ensure that our launcher emulates this mucking around.
For the most part, the two main things you need to worry about
are setting catalina.home and logging system properties.
</p>
<p>
I've found the easiest and most flexible way to set the required properties is
to use Launch4j's ini file feature, which lets you specify arguments to
the launched JVM in an .ini file.    This file is read every time the launcher
is executed (NOT when it is built), so it also allows you to tweak VM settings
(such as heap size) in the wild.
The file has to be in the same directory
as the lancher .exe file and have the same name but with an extension of
.l4j.ini rather than .exe.
</p>
<p>
The .ini file can use a number of useful variables such
as EXEDIR that we can use to ensure that the right directories get found.
See the <b>mylauncher.l4j.ini</b> listing below for an example.
</p>



<h3>Create a Launch4j Configuration</h3>

<p>
Launch4j needs an XML file that describes how to create the launcher at
buildtime.  There isn't a whole lot to this - it basically tells it where
to find jars and icons and the name of the class to run.  Launch4j comes with a lot of
documentation and even a fancy GUI for setting this up, so I won't belabor this
part of it.  See the appended
<b>launcher.xml</b> for an example and a few notes on
potential gotchas.
</p>

<h3>Create an icon and a splash screen</h3>

<p>
The splash screen is completely native and for this reason (apparently),
it *has* to be a bloated .BMP.  The .BMP
</p>
<p>
The icon file has to be a Windows .ico file.  There are lots of ways to make
this.  On MacOS, I found a very handy one called
<a href='http://www7a.biglobe.ne.jp/~ogihara/software/index.html'>IcoMaker</a>.
</p>

<h3>Set up an Ant script to put it all together</h3>

<p>
Launch4j includes a nice ant task that lets you automate the building of
your .exe (even on MacOS!).  Again, I won't belabor the details here, but
you need to:

<ul>
<li>Compile your classes and jar them up.</li>
<li>Run the Launch4jTask, pointing it at the launch4j binaries, splash BMP, and ICO files</li>
<li>Copy your jar, the ini file, and whatever else into your deployment directory</li>
</ul>
</p>

<p>
That's pretty much all there is to it.  As I say, so far I have been
very pleased with they way this has worked.  Users don't even know they
are running a Java application, and I retain a lot of control over the
environment that they're running in.
</p>
<p>
Another thing that I've done that completes the illusion is to create a windows
tray icon using the  <b>com.jeans.trayicon</b> package -
I'll add an entry about this later.
</p>


<hr/>
<h3>Code Listings</h3>
<hr/>


<h4>launcher.xml</h4>

<pre>
&lt;launch4jConfig>

&lt;!-- Maybe just me, but I like keeping the jar outside -->
&lt;dontWrapJar>true&lt;/dontWrapJar>
&lt;headerType>gui&lt;/headerType>

&lt;outfile>mylauncher.exe&lt;/outfile>
&lt;errTitle>An error has occurred&lt;/errTitle>
&lt;chdir>.&lt;/chdir>
&lt;priority>normal&lt;/priority>
&lt;downloadUrl>http://java.com/download&lt;/downloadUrl>
&lt;supportUrl>http://www.mycompany.com/support&lt;/supportUrl>

&lt;!-- This is resolved at BUILDTIME -->

&lt;icon>images/desktop_icon.ico&lt;/icon>
&lt;classPath>
&lt;mainClass>com.mycompany.TomcatLauncher&lt;/mainClass>

&lt;!-- You need to use backslashes here -->
&lt;!-- These are resolved at RUNTIME -->

&lt;cp>%EXEDIR%\lib\mylauncher.jar&lt;/cp>
&lt;cp>%EXEDIR%\tomcat\bin\bootstrap.jar&lt;/cp>
&lt;/classPath>
&lt;jre>
&lt;path>jre&lt;/path>
&lt;minVersion>1.5.0&lt;/minVersion>
&lt;maxVersion>&lt;/maxVersion>
&lt;dontUsePrivateJres>true&lt;/dontUsePrivateJres>
&lt;/jre>
&lt;splash>
&lt;!-- This is resolved at BUILDTIME -->

&lt;file>images/splash.bmp&lt;/file>
&lt;waitForWindow>true&lt;/waitForWindow>
&lt;timeout>60&lt;/timeout>
&lt;timeoutErr>false&lt;/timeoutErr>
&lt;/splash>
&lt;/launch4jConfig>
</pre>

<hr/>

<h4>build.xml</h4>

<pre>
...
&lt;target name="exe">

&lt;taskdef name="launch4j"
classname="net.sf.launch4j.ant.Launch4jTask"
classpath="${launch4j.dir}/launch4j.jar:${launch4j.dir}/lib/xstream.jar" />

&lt;launch4j configFile="launcher.xml"
outfile='${build.dir}/mylauncher.exe'
bindir='${launch4j.dir}/bin'/>
&lt;/target>
</pre>

<hr/>

<h4>mylauncher.l4j.ini</h4>

<pre>
-Dcatalina.home="%EXEDIR%/tomcat"
-Djava.util.logging.config.file="%EXEDIR%/tomcat/conf/logging.properties"
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Xms512m
-Xmx512m
</pre>

<hr/>

<h4>TomcatLauncher.java</h4>

<pre>
package com.mycompany;

import org.apache.catalina.startup.Bootstrap;
import edu.stanford.ejalbert.BrowserLauncher;
import javax.swing.JOptionPane;

public class TomcatLauncher implements Runnable {


// =========================================================================
// Constants

// url that the launcher will open in a browser.  you might need to make
// this more flexible (e.g., passed in via args or configuration).
private static final String START_URL = "http://localhost:8080";

// =========================================================================
// main() - start Tomcat in a separate thread so launcher thread can die

public static void main(String[] args) {
TomcatLauncher tl = new TomcatLauncher();
Thread t = new Thread(tl);
t.start();
}


// =========================================================================
// Runnable imlementation - launch Tomcat


public void run() {
registerShutdownHook();
startTomcat();
showStartPage();
}

// =========================================================================
// Private methods that do the real work

/**
* In case Ctrl-C or other unexpected shutdown...
*/
private void registerShutdownHook() {
this.shutdownThread = new Thread("shutdownHook") {
public void run() {
if (readyToExit == false) {// abnormal exit
readyToExit = true;
try {
if (bootStrap != null) bootStrap.stop();
} catch (Exception e) {
e.printStackTrace();
}
// do any other cleanup work, e.g. closing log files
} catch (Exception e) {
e.printStackTrace();
}
}
Runtime.getRuntime().addShutdownHook(this.shutdownThread);
}

/**
* Start Tomcat
*/
private void startTomcat() {
try {
log("Starting Tomcat...");
bootStrap = new Bootstrap();
bootStrap.init();
bootStrap.start();
log("...Tomcat started.");
} catch (Throwable t) {
t.printStackTrace();
JOptionPane.showMessageDialog(this,
"Error starting Ledgerscape server.", title,
JOptionPane.ERROR_MESSAGE);
}
}

/**
* Open the browser
*/
private void showStartPage() throws Exception {
try {
BrowserLauncher.openURL(START_URL);
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this, "Error starting browser.", title,
JOptionPane.ERROR_MESSAGE);
}
}

private void log(String msg) {
// FIXME you will probably want to make this write to a file
System.out.println(msg);
}
}
</pre>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2008/01/create-a-custom-exe-to-launch-tomcat/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Scriptella 1.0 Beta Released</title>
		<link>http://www.sutrotech.com/2007/11/scriptella-10-beta-released/</link>
		<comments>http://www.sutrotech.com/2007/11/scriptella-10-beta-released/#comments</comments>
		<pubDate>Wed, 28 Nov 2007 17:19:29 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=27</guid>
		<description><![CDATA[
Fyodor Kupolov has released a 1.0 beta of his
Scriptella ETL framework.
I downloaded it and integrated it into my applications - so far so good.



I blogged about Scriptella a while ago.  It's a simple and elegant framework for declaratively manipulating result-set style data (typically but not necessarily from a database).  Fyodor also seems to [...]]]></description>
			<content:encoded><![CDATA[<p>
Fyodor Kupolov has released a 1.0 beta of his
<a href='http://scriptella.javaforge.com'>Scriptella ETL</a> framework.
I downloaded it and integrated it into my applications - so far so good.
</p>

<p>
I <a href='http://www.pcal.net/blog/?p=25'>blogged about Scriptella a while ago</a>.  It's a simple and elegant framework for declaratively manipulating result-set style data (typically but not necessarily from a database).  Fyodor also seems to have updated the
<a href='http://scriptella.javaforge.com/reference/index.html'>reference</a> section with some nice diagrams that explain the concepts very clearly.
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2007/11/scriptella-10-beta-released/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Painless Spell Checking in Ant</title>
		<link>http://www.sutrotech.com/2007/11/painless-spell-checking-in-ant/</link>
		<comments>http://www.sutrotech.com/2007/11/painless-spell-checking-in-ant/#comments</comments>
		<pubDate>Fri, 02 Nov 2007 21:54:17 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=26</guid>
		<description><![CDATA[I've been using ant as a scripting language for assembling and deploying the new

CFOsoft.com

website.  A few embarrassing typos later, I realized it would be nice to also be able to spellcheck it in the same process.





A quick google search turned up

Rob Mayhew's

AntSpell

task. It works as advertised, no muss no fuss.  10 minutes later, [...]]]></description>
			<content:encoded><![CDATA[I've been using ant as a scripting language for assembling and deploying the new
<a href='http://www.cfosoft.com'>
CFOsoft.com
</a>
website.  A few embarrassing typos later, I realized it would be nice to also be able to spellcheck it in the same process.
</p>


<span id="more-38"></span>
<p>
A quick google search turned up
<a href='http://robmayhew.com'>
Rob Mayhew</a>'s
<a href='http://robmayhew.com/antspell/antspelltask.html'>
AntSpell
</a>
task. It works as advertised, no muss no fuss.  10 minutes later, I had it integrated into my build with a custom dictionary.   Thanks Rob!
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2007/11/painless-spell-checking-in-ant/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Scriptella ETL</title>
		<link>http://www.sutrotech.com/2007/07/scriptella-etl/</link>
		<comments>http://www.sutrotech.com/2007/07/scriptella-etl/#comments</comments>
		<pubDate>Sat, 21 Jul 2007 18:49:36 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=25</guid>
		<description><![CDATA[
My current project involves a lot of transforming and migrating database data, so some kind of ETL framework is called for.  I spent some time researching the various Java ETL offerings and surprisingly found there is not a whole lot out there.


Fortunately, I did find one which is meeting my needs
in a very elegant [...]]]></description>
			<content:encoded><![CDATA[<p>
My current project involves a lot of transforming and migrating database data, so some kind of ETL framework is called for.  I spent some time researching the various Java ETL offerings and surprisingly found there is not a whole lot out there.
</p>
<p>
Fortunately, I did find one which is meeting my needs
in a very elegant way:
<a href='http://scriptella.javaforge.com/'>Scriptella</a>
</p>


<span id="more-37"></span>
<p>
Their website says
</p>
<p><i>
"Our primary focus is simplicity. You don't have to
study yet another complex XML-based language"
</i></p>
<p>
I second that emotion; the last thing I need
to do is deal with another misguided attempt to stuff
procedural logic into XML.
</p>
<p>
At first glance, though, Scriptella looks like nothing if not
"yet another complex XML-based language:"
</p>
<p>
<pre>
&lt;etl>
&lt;connection driver="$driver" url="$url" user="$user"
password="$password"/>
&lt;script>
&lt;include href="PATH_TO_YOUR_SCRIPT.sql"/>
-- And/or directly insert SQL statements here
&lt;/script>
&lt;/etl>
</pre>
</p>
<p>
Do not be fooled.  That is just a shell, and it's about all of
the XML you will have to write.
</p>
<h2>The Rules</h2>
<p>For the impatient, here is a sketch of a spec for how you write a Scriptella script:</p>
<ul>
<li>You use XML to build a simple skeleton for nesting chunks of declarative languages (typically SQL but not always)</li>
<li>Outer chunks are responsible for generating a result set - (a list of hashmaps, essentially)</li>
<li>Inner chunks are processed iteratively for each row in the result set generated by its enclosing chunk</li>
<li>Inner chunks do something useful with each row (such as perform an INSERT).  They can refer to members of the current result set row by name.</li>
<li>Chunks can be nested to any depth (i.e., inner chunks can also be outer chunks)</li>
</ul>
<h2>A Simple Example</h2>
<p>
That may sound a little confusing, but it's actually quite
elegant and powerful.  A simple example goes a long way.
</p>
<p>
Say you have an Employee table in Database A that you want to copy
into Database B, row by row.  In scriptella, it would look
something like this:
</p>
<pre>
...
<b>&lt;query connection-id='DatabaseA'></b>
SELECT ID, FIRST, LAST FROM EMP
<b>  &lt;script connection-id='DatabaseB'></b>
INSERT INTO EMPCOPY VALUES (?ID, ?FIRST, ?LAST)
<b> &lt;/script></b>
<b>&lt;/query></b>
</pre>

<p>
When processed, this Scriptella script would select each row out
of EMP in Database A and insert them into EMPCOPY in Database B.
The nested 'script' element gets processed once for each row, and
the '?' parameters get filled in with values from each row.
</p>
<p>
It's as if you wrote Java code that opened two JDBC connections,
executed a query on one, iterated through the result set, and
dumped each row into a prepared INSERT statement opened on the other
connection.
</p>
<p>
At this point, you can knock yourself out - create
tables from scratch, write arbitrarily complex SELECT statements,
create and drop tables as needed, whatever.  You can
also use this as a way to write queries that generate
queries - a more dialect-neutral alternative to
the various flavors of dynamic SQL (i.e., queries that generate queries).
You have the full power of SQL at your disposal and Scriptella won't get in the way unless you ask it to.
</p>

<p>
<h2>Beyond SQL</h2>
<p>
Things start to get really interesting when you consider that
Scriptella is designed to accommodate any language, not just
SQL.  For example, something like this can be used to dump
data from a table to System.out:
</p>

<p>
<pre>
...
<b>&lt;query connection-id='DatabaseA'></b>
SELECT ID, FIRST, LAST FROM EMP
<b>   &lt;script connection-id='janino-java-connection'></b>
String employee = get("FIRST");
System.out.print("Found an employee named "+employee);
<b>    &lt;/script></b>
<b>&lt;/query></b>
</pre>
</p>

<p>
Any language that you have a JSR-223 driver for can be used.
You can have scripts that generate data for processing by
enclosed XML chunks as well as processing data from enclosing chunks
</p>
<p>
<h2>Wrapping Up</h2>
<p>
There are a lot more (and better) examples on the
<a href='http://scriptella.javaforge.com/'>Scriptella website</a>.  The short of it, though is that Scriptella gives you
a simple, elegant, declarative mechanism for:

<ul>
<li>Moving data between databases</li>
<li>Writing dynamic queries</li>
<li>Sprinkling in procedural logic when you need it</li>
</ul>
</p>
<p>
Most importantly, it does all of this with as little intrusion
as possible.  Most of the time, I  want to do the heavy
lifting with SQL, and Scriptella doesn't get in the way of
that.  But when I need to add some procedural logic or do something
trickier, Scriptella is there.
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2007/07/scriptella-etl/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Dynamic Persistence Units in EJB3</title>
		<link>http://www.sutrotech.com/2007/04/dynamic-persistence-units-in-ejb3/</link>
		<comments>http://www.sutrotech.com/2007/04/dynamic-persistence-units-in-ejb3/#comments</comments>
		<pubDate>Thu, 19 Apr 2007 17:12:05 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=24</guid>
		<description><![CDATA[
UPDATE 10/27/08:

JPA FAIL! So, Mr. Patrick Linskey, who knows something about such things, points out that the standard actually does provide a framework for dynamic PUs: javax.persistence.Persistence.createEntityManagerFactory.  You still have to plug in vendor-specific properties, but this is a much better way to go.  I'm not actually sure how I could have been led so [...]]]></description>
			<content:encoded><![CDATA[<i>
UPDATE 10/27/08:
<p>
JPA FAIL! So, Mr. Patrick Linskey, who knows something about such things, points out that the standard actually does provide a framework for dynamic PUs: javax.persistence.Persistence.createEntityManagerFactory.  You still have to plug in vendor-specific properties, but this is a much better way to go.  I'm not actually sure how I could have been led so far astray - what I knew at the time I knew from perusing the hibernate forums...
</p>
</i>
<p>
I gotta say, again, that I really think JPA is great.  It took almost a decade, but Sun got pretty much everything right.  I love just putting annotations everywhere, and anyone who thinks that is a bad idea is a dodo-head.  Die XML, die!
</p>
<span id="more-36"></span>

<span style="text-decoration: line-through;">Unfortunately, the legacy of deployment descriptors still lives on in the dusty corners of the
EJB3 spec.  One thing that you still can't do without a deployment
descriptor is define a new Persistence Unit. </span>

<span style="text-decoration: line-through;"> That's a fairly big omission.  In the case of the app I am writing, a big
part of what I need to do is allow the user to configure new databases and
connect to them.  I don't know what those databases are until runtime, and
if I happen to want to talk to those databases via JPA, I'm pretty much out
of luck - at least as far as the spec is concerned. </span>

<span style="text-decoration: line-through;"> Here is a vendor specific-solution for Hibernate.  It actually took a while
for me to google this together, so maybe this will save someone some time.
Maybe my googling skillz are not as mad as they used to be.  Anyway. </span>
<pre><span style="text-decoration: line-through;">
import org.hibernate.ejb.Ejb3Configuration;
import java.sql.DataSource;
import java.util.Properties;

// ...

@SuppressWarnings("deprecation")
public static EntityManagerFactory
createEMF(DataSource ds,
Class[] entityClasses,
Properties props)
{
Ejb3Configuration ejb3conf =
new Ejb3Configuration();
ejb3conf.setDataSource(ds);
//
// set any fixed properties you want
ejb3conf.setProperty("hibernate.dialect",
org.hibernate.dialect.HSQLDialect);
ejb3conf.setProperty("hibernate.show_sql",
"false");
ejb3conf.setProperty("hibernate.hbm2ddl.auto",
"update");

if (props != null) {
Set&lt;Entry&lt;Object, Object&gt;&gt; entries = props.entrySet();
for (Entry e : entries) {
ejb3conf.setProperty(
e.getKey().toString(),
e.getValue().toString());
}
}
for (int i = 0; i &lt; entityClasses.length; i++) {
assert entityClasses[i] != null;
ejb3conf.addAnnotatedClass(entityClasses[i]);
}
return ejb3conf.createEntityManagerFactory();
}</span></pre>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2007/04/dynamic-persistence-units-in-ejb3/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Time to dust off the ol&#8217; VT100</title>
		<link>http://www.sutrotech.com/2006/12/time-to-dust-off-the-ol-vt100/</link>
		<comments>http://www.sutrotech.com/2006/12/time-to-dust-off-the-ol-vt100/#comments</comments>
		<pubDate>Wed, 13 Dec 2006 08:14:58 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=23</guid>
		<description><![CDATA[
Just stumbled across Charva.  I love it.  I just wish I could think of a reason to use it.






]]></description>
			<content:encoded><![CDATA[<p>
Just stumbled across <a href='http://www.pitman.co.za/projects/charva/Screenshots.html'>Charva.</a>  I love it.  I just wish I could think of a reason to use it.
</p>

<center>
<a href='http://www.pitman.co.za/projects/charva/Screenshots.html'>
<img src='http://www.pitman.co.za/projects/charva/images/charva1.png' />
</a>
</center>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/12/time-to-dust-off-the-ol-vt100/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Smile MacBook Users, You&#8217;re on Camera!</title>
		<link>http://www.sutrotech.com/2006/12/smile-macbook-users-youre-on-camera/</link>
		<comments>http://www.sutrotech.com/2006/12/smile-macbook-users-youre-on-camera/#comments</comments>
		<pubDate>Mon, 11 Dec 2006 18:11:32 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=21</guid>
		<description><![CDATA[









BROADCASTING LIVE!


Scary, huh?  It's you on the internet!  Well, not really - its just looping back locally.   But still.  I  blatantly stole this cool trick from this guy.


(For those not on an iSight equipped Mac: the above box shows the video feed from the Mac's built-in webcam).


But seriously, I [...]]]></description>
			<content:encoded><![CDATA[<p>
</p>
<center>
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" height="256" width="320">
<param name="src" value="http://www.yourdomain/your.mov">
<param name="autoplay" value="true">
<param name="type" value="video/quicktime" height="256" width="320"><embed src="http://www.pcal.net/stuff/isight.mov" autoplay="true" type="video/quicktime" pluginspage="http://www.apple.com/quicktime/download/">
</object>

<br/>
<font color='red'><blink>BROADCASTING LIVE!</blink></font>
</center>

<p>Scary, huh?  It's you on the internet!  Well, not really - its just looping back locally.   But still.  I  blatantly stole this cool trick from <a href='http://www.josephcrawford.com/2006/11/11/scary-isight-trick/'>this guy</a>.
</p>
<p>
(For those not on an iSight equipped Mac: the above box shows the video feed from the Mac's built-in webcam).
</p>
<p>
But seriously, I am a little concerned about the iSight.  It's fun and has the geek factor and everything, but there also are security and privacy issues that I think Apple seems to have pretty much ignored.
</p>

<p>
This morning, I was on a WebEx.  The WebEx software and the iSight both decided that video of me should be transmitted.  The WebEx software provides no way to disable this.  Apple provides no way to disable the camera.  A control panel?  A shutter?  Better yet, a removable camera?  A BTO option to skip it entirely?  Something?  Please?
</p>

<p>
And yes, I do know I could fix this with a 1 sq cm of electrical tape.  But then how am I going to get that consulting gig at NORAD if they won't let me through the 20-foot-thick door with my machine?
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/12/smile-macbook-users-youre-on-camera/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Java Web Frameworks: the Good, the Bad, and the Ugly</title>
		<link>http://www.sutrotech.com/2006/12/java-web-frameworks-the-good-the-bad-and-the-ugly/</link>
		<comments>http://www.sutrotech.com/2006/12/java-web-frameworks-the-good-the-bad-and-the-ugly/#comments</comments>
		<pubDate>Sun, 03 Dec 2006 22:44:03 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=22</guid>
		<description><![CDATA[
There have been a million blog postings this year weighing the pros and
cons of the various web frameworks now available.  It's a bit overwhelming
to wade through it all, so I'm going to try to provide a nutshell
summary of my take on the three that I've evaluated recently: Seam, GWT, and Echo.


I chose these because [...]]]></description>
			<content:encoded><![CDATA[<p>
There have been a million blog postings this year weighing the pros and
cons of the various web frameworks now available.  It's a bit overwhelming
to wade through it all, so I'm going to try to provide a nutshell
summary of my take on the three that I've evaluated recently: Seam, GWT, and Echo.
</p>
<p>
I chose these because they seem to be the projects which have the most
momentum.  (I'm not proud - it pays to follow the herd in this kind of thing).
I can't claim to have written 'real' applications with any of these yet, but
in each case I at least got so far as prototype that presents master-detail
views that update a database.
</p>
<p>
A quick note about me: I've been a longtime skeptic of the whole Ajax thing.
My experience writing the early console for WebLogic server left me
traumatized by javascript.  The latest generation of tools may be changing
my mind.
<p>
So, without further adieu, the nutshells:
</p>


<table cellpadding='8' border='1'>
<tr>
<td colspan='2'>
<h2><a href='http://www.jboss.com/products/seam'>JBoss Seam</a></h2>
</td>
</tr>
<tr>
<td><b>What It Is</b></td>
<td>
A few annotations, a library of JSP tags, and some interceptor/injection runtime
magic that provide an unobtrusive glue layer between EJB 3.0 and JSF.
</td>
</tr>
<tr>
<td nowrap valign='top'><b>The Good</b></td>
<td>
Seam feels very clean and well-designed.  You don't actually use that
much Seam stuff in withing a Seam app, which is always a good sign. Seam
seems to be informed by an underlying pragmatism about what most real
world apps are like and how they are developed.  It's not quite JSF
on Rails but it's in the ballpark.
</td>
</tr>
<tr>
<td nowrap valign='top'><b>The Bad</b></td>
<td>The docs are a bit haphazard and the tutorials are schizophrenic.</td>
</tr>
<tr>
<td nowrap valign='top'><b>The Ugly</b></td>
<td>I would have killed for a framework like this six or seven years ago.  Unfortunately,
it does seem like much of the world is moving in a different direction now.
If Ajax figures prominently in your future, you might do well to look elsewhere.
There are some scattered efforts to Ajax-ify Seam but nothing I've
read about them seems very compelling.
</td>
</tr>
<tr>
<td nowrap valign='top'><b>The Bottom line</b></td>
<td>If you are committed to a traditional page-centric application
with JSF, Seam will make your life a lot easier.  But nowadays you
probably need to carefully consider the depth of that commitment.
</td>
</tr>
</table>
<br/><br/>
<table cellpadding='8' border='1'>

<tr><td colspan='2'>
<b><h2><a href='http://code.google.com/webtoolkit'>Google Web Toolkit</a></h2>
</td></tr>

<tr>
<td nowrap valign='top'><b>What it Is</b></td>
<td>A compiler that translates java source code directly into javascript,
a library of AWT-like widgets, and a 'hosted mode' container for simplifying
the edit-compile-deploy-debug cycle.</td>
</tr>

<tr>
<td nowrap valign='top'><b>The Good</b></td>
<td>
The sheer audacity of GWT's much-hyped approach really is astounding.  Actually,
I'm not sure that part is good.  The good part is that it really does
seem to work; I didn't encounter any cross-browser issues.  You write java code and you get Ajax magic without having to
touch the hated javascript.  The approach allows you to maximize the
amount of application processing that is offloaded to the browser, which
in theory could help you scale an application more easily.
<br/><br/>
Much has been made about potential security holes with putting logic
in javascript in the browser, but this strikes me as a red herring.  I fail
to see how it's any different from shipping an applet jar out to the
browser.  Moreover, GWT all but forces you to keep your business logic
on the serverside (more on this in The Ugly).
</td>
</tr>

<tr>
<td nowrap valign='top'><b>The Bad</b></td>
<td>I ran into some possible performance concerns
even on relatively simple pages (on the order of a dozens of listeners and
fields, things became very slow).  The license is worrisome: it paints
itself as open source, but they keep the compiler proprietary binary
(and the compiler is where all the value is).  <br /><br />
The documentation is excellent in some respects but poor to non-existent
in others, especially WRT project structure.  In particular,
GWT modules have a specific structure that is not documented anywhere.
Naming your subpackages 'public' and 'client' and 'server' is not a
matter of convention - they have meanings to the compiler but this
is not described anywhere AFAICT.  They seem to expect you to run
their little bootstrap tool to set everything up for you and not
ask questions - that approach always drives me absolutely nuts.
English is my friend.<br/><br/>
Also, I hope you love CSS as much as I hate it because you will be using
it a lot.  You pretty much have to define a style for every little widget
you use.  The constant context switching between Java and CSS quickly
becomes a pain when all you want to do is <code>myButton.setWidth(100)</code>.
</td>
</tr>

<tr>
<td><b>The Ugly</b></td>
<td>
In some ways, GWT presents a worst-of-both-worlds scenario in terms of how
it abstracts away the client/server divide.  You still have to define remote interfaces, and
using them is awkward because of the inherent limitations of the
java->javascript translation.  It basically forces you to build a stripped
down DAO layer for the javascript to talk to via XML, and for me that
quickly became extremely tedious.
</td>
<tr>
<td nowrap valign='top'><b>The Bottom Line</b></td>
<td>
If you are writing a quote-unquote Web 2.0 type app that has to scale
for millions
of users, GWT could be the way to go.  It does a great job of keeping
javascript out of your hair, but prepare for busywork if you need to talk to
an EJB.
</td>
</tr>
</table>
<br/><br/>
<table cellpadding='8' border='1'>

<tr><td colspan='2'><h2><a href='http://www.nextapp.com/platform/echo2/echo/'>Echo2</a></h2></td></tr>

<tr>
<td nowrap valign='top'><b>What It Is</b></td>
<td>Take Swing.  Rewrite the peer layer so that instead of talking
to native GUI widgets on the local machine, it talks to a javascript
agent in a remote browser that renders DHTML widgets.  That's Echo2.</td>
</tr>

<tr>
<td nowrap valign='top'><b>The Good</b></td>
<td>It's just like writing a swing app.  The API is almost identical.
It completely abstracts away the remoteness of the client - you can have
an ActionListener that invokes a session bean directly if that's what you
want to do.  There are no restrictions on what you can do because all
of the action is on the server - the javascript simply provides a reflection
of what the server tells it is happening.  It has a
<a href='http://demo.nextapp.com/Demo/app'>truly amazing demo app</a>.
</td>
</tr>


<tr>
<td nowrap valign='top'><b>The Bad</b></td>
<td>It's just like writing a swing app.  The API is almost identical.
Doing relatively simple things often requires more code than it should.
You will suffer greatly if you are allergic to anonymous inner classes
(I'm not, some are).</td>
</tr>

<tr>
<td nowrap valign='top'><b>The Ugly</b></td>
<td>It's just like writing a swing app, except it isn't.  The peers
are all on the other side of possibly high-latency link, but the API makes it
easy for you to forget this.  The runtime tries to do some smart things
with batching up client/server comunication, but it's not always clear
what the rules are.  If your UI has to respond to lots of fine-grained
events (e.g., keystrokes in a textfield), you might have trouble.  If
your UI needs to support hundreds or thousands of concurrent users,
you might be in trouble.  (I don't have hard data on that, only the intuition
that Echo's approach is inherently more chatty and therefore less scalable
for some kinds of apps).
</td>
</tr>

<tr>
<td nowrap valign='top'><b>The Bottom Line</b></td>
<td>If you're writing a traditional J(2)EE app with forms and tables
that talk to a database and it doesn't have to scale to thousands of
users, Echo seems like the way to go.  The beauty of it really isn't
even so much about Ajax.  Rather, it's
about a client/server programming model that feels like a fat
client model 98% of the time.  You do have to be a little careful not
to let things become overly chatty, but for many kinds of apps that
isn't likely to be a problem.
</td>
</tr>

</table>
</p>

<p>
At the end of the day, the answer is the same as it almost always is:
it depends on the app.  Seam if you have to do traditional pages,
GWT if you're building GoogleMaps, and Echo if you're doing mid-size/J2EE
apps.
</p>
<p>
At the moment, I'm mostly in the last category, so my choice is clear:
Echo all the way
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/12/java-web-frameworks-the-good-the-bad-and-the-ugly/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Introducing iQuip 1.0</title>
		<link>http://www.sutrotech.com/2006/10/introducing-iquip-10/</link>
		<comments>http://www.sutrotech.com/2006/10/introducing-iquip-10/#comments</comments>
		<pubDate>Tue, 31 Oct 2006 01:35:27 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=19</guid>
		<description><![CDATA[
I hate Objective C but I can't stay away.  I put together a little Preference Pane for the Mac that puts a random quote in your login window.  It's basically a pretty wrapper around the old fortune program.


You can get it here.  Lemme know if it works for you.



Props to thenopp and [...]]]></description>
			<content:encoded><![CDATA[<p>
I hate Objective C but I can't stay away.  I put together a little Preference Pane for the Mac that puts a random quote in your login window.  It's basically a pretty wrapper around the old <code>fortune</code> program.
</p>
<p>
You can <a href='http://www.pcal.net/iquip'>get it here</a>.  Lemme know if it works for you.
</p>

<p>
Props to thenopp and especially Ralf for helping me track down some bugs.
</p>

<center>
<a href='http://www.pcal.net/iquip'>
<img border='1' src='http://www.pcal.net/iquip/images/loginwindow.png'  width='300' />
</a>
</center>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/10/introducing-iquip-10/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Return of the Disappearing RAM Slot</title>
		<link>http://www.sutrotech.com/2006/10/return-of-the-disappearing-ram-slot/</link>
		<comments>http://www.sutrotech.com/2006/10/return-of-the-disappearing-ram-slot/#comments</comments>
		<pubDate>Fri, 13 Oct 2006 19:45:58 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=20</guid>
		<description><![CDATA[

Back in January, I experienced the dreaded
Deaded Lower Ram Slot Problem
on my 1.5ghz PowerBook.


Well, it seems to have happened again.  Not sure exactly when it happened, but it may well have been right around the time I upgraded to 1.4.8.  But it also has been running hot for long stretches of a time, [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href='http://pcal.net/blog/archives/2006/01/the_invisible_r.html'>
Back in January</a>, I experienced the dreaded
<a href='http://lowermemoryslot.editkid.com/'>Deaded Lower Ram Slot Problem</a>
on my 1.5ghz PowerBook.
</p>
<p>
Well, it seems to have happened again.  Not sure exactly when it happened, but it may well have been right around the time I upgraded to 1.4.8.  But it also has been running hot for long stretches of a time, lately - maybe that's the cause.  Ugh, who knows?.  Back you go to Apple for a new logic board, little PowerBook.
</p>
<p>
This all got me wondering how I could make my machine make an assertion at startup about how much memory it has.  That in turn got me googling, which in short order produced a
<a href='http://www.bigbucketblog.com/2006/04/19/mac-os-x-and-the-missing-power-on-self-test/'>handy answer</a> courtesy of one Matt Comi.  Thanks, Matt.</p>
<center><img width='300' src='/stuff/images/power_burn.jpg'/></center>
<p>
<i>
And yes, I do need to get a new machine.  I have needed one for months, but just can't bring myself to do it knowing that the Core2 Duos are just around the corner.  Any day now, right?
</i>
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/10/return-of-the-disappearing-ram-slot/feed/</wfw:commentRss>
		</item>
		<item>
		<title>JavaOne: Josh Bloch is my Hero</title>
		<link>http://www.sutrotech.com/2006/05/javaone-josh-bloch-is-my-hero/</link>
		<comments>http://www.sutrotech.com/2006/05/javaone-josh-bloch-is-my-hero/#comments</comments>
		<pubDate>Wed, 24 May 2006 05:10:13 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=17</guid>
		<description><![CDATA[
Josh Bloch has always been my favorite deity in the Java pantheon.
He's never said or written anything that I didn't find shockingly reasonable.
He's one of the few folks willing to get up and talk in pragmatic terms
about the importance of good API design.  He believes the compiler is his
friend.  He wants to help [...]]]></description>
			<content:encoded><![CDATA[<p>
Josh Bloch has always been my favorite deity in the Java pantheon.
He's never said or written anything that I didn't find shockingly reasonable.
He's one of the few folks willing to get up and talk in pragmatic terms
about the importance of good API design.  He believes the compiler is his
friend.  He wants to help the compiler be your friend as well.
</p>
<p>
And to top it all off, he admits mistakes.  At this year's 'puzzlers' quiz
at JavaOne last week, he paused to offer everyone a big <i>mea culpa</i>
for a design decision he made which later turned out to be wrong.*
</p>
<p>
How often do you see a <b>THOUGHT LEADER</b> do that?  And in front of
thousands of people, no less?  I'm a fan for life.
</p>
<br />
<p>
<i>
* The mistake was that java.util.Arrays.asList() was updated to take varargs.  This means it's now ok to pass an array of primitives to asList, but you will get a (perhaps) astonishing result: a List containing a single entry (your array of primitives).
</p>
<p>
Personally, I was always a bit dubious about the inclusion of varargs in Java, anyway...
</p>
</i>

</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/05/javaone-josh-bloch-is-my-hero/feed/</wfw:commentRss>
		</item>
		<item>
		<title>JavaOne: It&#8217;s Done</title>
		<link>http://www.sutrotech.com/2006/05/javaone-its-done/</link>
		<comments>http://www.sutrotech.com/2006/05/javaone-its-done/#comments</comments>
		<pubDate>Tue, 23 May 2006 05:20:46 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=18</guid>
		<description><![CDATA[
Spent last week at JavaOne, spending some time now to blog a couple quick thoughts
about it.



Overall, and as reported elsewhere, the energy level was quite a bit higher
than in recent years.  Attendance was quite good.



I saw an inordinate number of 'Java couples' strolling about with matching orange
backpacks.  About 30 by my count.  [...]]]></description>
			<content:encoded><![CDATA[<p>
Spent last week at JavaOne, spending some time now to blog a couple quick thoughts
about it.
</p>
<ul>
<li>
Overall, and as reported elsewhere, the energy level was quite a bit higher
than in recent years.  Attendance was quite good.
</li>

<li>
I saw an inordinate number of 'Java couples' strolling about with matching orange
backpacks.  About 30 by my count.  Was this just me?  Male & female checking out
the latest on NetBeans and Ajax hand-in-hand or in an otherwise not very
we're-just-co-workers kind of way.
</li>

<li>
Crowd control for the sessions sucked even worse than usual.
</li>

<li>
I guess scripting language support is the next big thing.  Seems useful,
but only to a point.  The only use case I buy is to make it easier to provide
applications with end-user scriptability.  But now they're talking about VB.
They're talking about inline XML.  I am a little afraid.
</li>

<li>
Ajax was all the rage.  This still just gets a big WTF from me.
</li>

</ul>

<p>
If I were to hazard a guess as to W exactly that last F is, I would say this: Java
is done.  I don't mean that in a bad way.  I mean that in the sense of
all the big mountains having been climbed in J(2?)[S|E]E
</p>
<p>
They've finally cleaned up most all of the crap out of the language.  They've
cleaned the crap out of the persistence APIs.  Actually, most all of the
EE frameworks seem to be in pretty good shape now.  We're finally starting to
get mature development tools.  Even Swing is becoming a viable way to write
desktop applications.
</p>
<p>
The fact that a crock of hype like Ajax can be the hot thing at JavaOne speaks
volumes to how far Java has come.  The sense I get is that there just isn't that
much to do to the Java platform.  Maybe we don't need the JCP anymore, not
because it's too slow, but because it's going to run out of useful work to do?
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/05/javaone-its-done/feed/</wfw:commentRss>
		</item>
		<item>
		<title>NOT_TRUE_OR_FALSE</title>
		<link>http://www.sutrotech.com/2006/02/not_true_or_false/</link>
		<comments>http://www.sutrotech.com/2006/02/not_true_or_false/#comments</comments>
		<pubDate>Wed, 22 Feb 2006 18:04:15 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=13</guid>
		<description><![CDATA[
A
big thread on The Daily WTF
has opened up on the topic of tri-state booleans.  A majority of folks seem to be rushing to the defense of today's offender, who has introduced a constant named NOT_TRUE_OR_FALSE into his code.  This kind of abuse is very common and has always driven me nuts.


There is one [...]]]></description>
			<content:encoded><![CDATA[<p>
A
<a href='http://www.thedailywtf.com/forums/61210/ShowPost.aspx'>big thread on The Daily WTF</a>
has opened up on the topic of tri-state booleans.  A majority of folks seem to be rushing to the defense of today's offender, who has introduced a constant named NOT_TRUE_OR_FALSE into his code.  This kind of abuse is very common and has always driven me nuts.
</p>
<p>
There is one voice of reason (with a lame handle, "Dude Guy") amidst the madness, though:
</p>

<p>
<i>
This is just [the] good old problem of representing unknown information on a database, on which many people have written a fair amount, of which many, many more have read nothing. One classic problem: there is a difference between using a third value to represent "the real-world entity represented by this record has a value for this, but it is unknown," "the entity represented could have a value for this in the real world, but it actually happens not to have one," and "the real world is such that the entity described can't have a value for this." In short, people tend to systematically confuse data that represents facts about the real-world entities [with] questions and metadata about the completeness of the representation.
</i>
</p>
<p>
Thank you, Dude Guy, whoever you are.
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/02/not_true_or_false/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The Short Tail</title>
		<link>http://www.sutrotech.com/2006/01/the-short-tail/</link>
		<comments>http://www.sutrotech.com/2006/01/the-short-tail/#comments</comments>
		<pubDate>Sun, 22 Jan 2006 20:28:53 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=16</guid>
		<description><![CDATA[

According to IMDB, these are the "10 Best Pictures" and "10 Best Popcorn Movies" of 2005.  I'll bet you can't guess which list is which in 10 seconds or fewer.


For an added challenge, three movies in each list have been whited-out.  Give up?  Click-drag your mouse over the lists to reveal the [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href='http://www.imdb.com/features/rto/2006/poll/bestresults'>
According to IMDB</a>, these are the "10 Best Pictures" and "10 Best Popcorn Movies" of 2005.  I'll bet you can't guess which list is which in 10 seconds or fewer.
</p>
<p>
For an added challenge, three movies in each list have been whited-out.  Give up?  Click-drag your mouse over the lists to reveal the hidden answers!
</p>
<p>
<table border='1' cellpadding='4'>
<tr><td>&nbsp;</td><td><b>10 Best <font color='white'>Popcorn Movies</font></b></td><td><b>10 Best <font color='white'>Pictures</font></b></td></tr>
<tr><td>1</td>
<td>Harry Potter and the Goblet of Fire</td>
<td>Harry Potter and the Goblet of Fire</td>
</tr>

<tr><td>2</td>
<td>King Kong</td>
<td><font color='white'>Brokeback Mountain</font></td>
</tr>

<tr><td>3</td>
<td>Star Wars: Episode III</td>
<td>King Kong</td>
</tr>

<tr><td>4</td>
<td>Batman Begins</td>
<td>Sin City </td>
</tr>

<tr><td>5</td>
<td>Serenity</td>
<td>Star Wars: Episode III</td>
</tr>

<tr><td>6</td>
<td>Sin City</td>
<td>Serenity</td>
</tr>

<tr><td>7</td>
<td><font color='white'>Mr. & Mrs. Smith</color></td>
<td>Batman Begins</td>
</tr>

<tr><td>8</td>
<td><font color='white'>Wedding Crashers</font></td>
<td><font color='white'>Crash</font></td>
</tr>

<tr><td>9</td>
<td><font color='white'>War of the Worlds</font></td>
<td><font color='white'>Walk the Line</font></td>
</tr>

<tr><td>10</td>
<td>The Chronicles of Narnia</td>
<td>The Chronicles of Narnia</td>
</tr>

</table>
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/01/the-short-tail/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CoolPad Cool</title>
		<link>http://www.sutrotech.com/2006/01/coolpad-cool/</link>
		<comments>http://www.sutrotech.com/2006/01/coolpad-cool/#comments</comments>
		<pubDate>Tue, 10 Jan 2006 00:06:43 +0000</pubDate>
		<dc:creator>pcal</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pcal.net/consulting/?p=15</guid>
		<description><![CDATA[Who carees about the new MacBooks? Check this puppy out:









Yeah, that's what I'm talkin' about!  The

best thirteen bucks I've spent in a while - a portable laptop pad that

helps keeps a powerbook cool
protects surface of the table and the PB's underside
provides a handy swivel motion
produces a slight  tilt that i think is actually [...]]]></description>
			<content:encoded><![CDATA[<p>Who carees about the new MacBooks? Check this puppy out:<p>

<p>
<center>
<a href='http://www.amazon.com/gp/product/B00006HYPV/qid=1136760050/sr=8-1/ref=pd_bbs_1/002-2609137-5235235?n=507846&s=pc&v=glance'>
<img src='http://g-images.amazon.com/images/G/01/ciu/99/72/f4dab340dca07244c4d58010.L.jpg'/>
</a>
</center>
</p>

<p>Yeah, that's what I'm talkin' about!  The
<a href='http://www.amazon.com/gp/product/B00006HYPV/qid=1136760050/sr=8-1/ref=pd_bbs_1/002-2609137-5235235?n=507846&s=pc&v=glance'>
best thirteen bucks</a> I've spent in a while - a portable laptop pad that
<ul>
<li>helps keeps a powerbook cool</li>
<li>protects surface of the table and the PB's underside</li>
<li>provides a handy swivel motion</li>
<li>produces a slight  tilt that i think is actually more comfortable for typing</li>
</ul>
</p>]]></content:encoded>
			<wfw:commentRss>http://www.sutrotech.com/2006/01/coolpad-cool/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
