<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>blog (personal)</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/" />
    <link rel="self" type="application/atom+xml" href="http://www.pcal.net/blog/atom.xml" />
    <id>tag:www.pcal.net,2007-11-20:/blog/6</id>
    <updated>2008-03-18T08:40:16Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Publishing Platform 4.01</generator>

<entry>
    <title>PropJoe</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2008/03/propjoe.html" />
    <id>tag:www.pcal.net,2008:/blog//6.412</id>

    <published>2008-03-18T07:40:49Z</published>
    <updated>2008-03-18T08:40:16Z</updated>

    <summary> 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&apos;m pretty uptight about using constants...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="java" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![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>
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, PropJoe.
</p> 
<p>
<a href='http://www.pcal.net/stuff/propjoe-0.1.0.zip'>Download propjoe-0.1.0.zip</a>
</p>


<br/>
<h3>Package Description for PropJoe:</h3>
<p>
Provides a javadoc doclet for generating a <code>.properties</code> file
from annotated Java constants.  This simplifies the task of maintaining
consistency and documentation between the <code>.properties</code> file
and Java code which references values in it.
</p>

<h2>Motivation</h2>

<p>
Properties files are ubiquitous.  They're easy to use and everyone understands
them.  They are the way to go for relatively simple application configuration
or to externalize program constants that might occassionally have to be
changed in the field.
</p>
<p>
If your app has a <code>.properties</code> file with more than a couple of propertie in
it, you hopefully you are using constants in your code to refer to the names
of the properties.  So, for example, you end up with a class that
holds a bunch of constants that you pass to <code>getProperty()</code>
when you need to get a property.  Something like this:
</p>
<p>

<pre>
public interface PropertyNames {

  public String LISTEN_PORT = "listen.port";

  public String BIND_ADDRESS = "bind.address";

  public String FACTORY_CLASS = "factory.class";

  //...
}
</pre>
</p>
<p>
And then of course you end up with a <code>.properties</code> file like this that
you need to ship with your product.
</p>
<p>
<pre>

#
# acme product.properties
#
listen.port  = 7001
bind.address = 127.0.0.1
factory.class = com.acme.AcmeFactoryImpl 

</pre>
</p>

<p>
This is all well and good and hopefully we can just assume that all of this
accepted good practice.  However, there are a few problems here:
</p>
<p>
Keeping the interface and the <code>.properties</code> file in sync
as the number of properties grows is problematic.
</p>
<p>
Also, documentation is similarly problematic.  We can document the Java interface, which
our developers will like.  We can document the properties file, which our
users will like.  Or we can try to document them both and slowly go insane
as the number of properties increases.
</p>

<img align='right' src='http://www.pcal.net/images/propjoe.jpg' width='200'/>

<h2>PropJoe</h2>


<p>
This is a basic single-sourcing problem, and it is this problem that PropJoe
solves in two easy steps:
</p>
<ul>
  <li>Apply PropJoe's <code>&#064;Property</code> annotations to the constants on the Java interface</li>
  <li>Run PropJoe javadoc doclet to generate a .properties files</li>
</ul>
</p>

<p>
To modify our example above, we'd have something like this on the Java
side:
</p>

<p>
<pre>
<p>
public interface PropertyNames {

  /**
   * The port that the server will listen on
   */
  &#064;Divider("Acme Product Properties")
  &#064;Property("7001")
  public String LISTEN_PORT = "listen.port";

  /**
   * The address the server server will bind to
   */
  &#064;Property("127.0.0.1")
  public String BIND_ADDRESS = "bind.address";

  /**
   * Fully-qualified class name of the special acme factory to instantiate.
   */
  &#064;Property("com.acme.AcmeFactoryImpl")
  public String FACTORY_CLASS = "factory.class";

  //...
}
</p>
</pre>
</p>

<p>
Which we could run through the PropJoeDoclet to get an output <code>.properties</code>
file like this:
</p>

<p>
<pre>
##############################################################
# Acme Product Properties

# The port that the server will listen on
listen.port  = 7001

# The address the server server will bind to
bind.address = 127.0.0.1

# Fully-qualified class name of the special acme factory to instantiate
factory.class = com.acme.AcmeFactoryImpl 
</pre>
</p>

<p>
Now, there is no more synchronization problem between the two files, and
the .properties file is nicely documented to boot.  All we have to do is 
worry about a single Java file.
</p>

<h2>Running the Doclet</h2>

<p>
Run PropJoe like you would any other doclet.  The only thing special about
it is that it requires one doclet parameter, </code>-f</code>, to specify
the path of the output properties file.  Note that if the file
already exists, the output will be appended to the file.
</p>

<p>
Also note that you can scan as may input Java files as desired for 
Property annotations - if you have those constants sprinkled all over
your codebase, that's fine - just feed all of the source to javadoc
and PropJoe will find them.
</p>
<p>
For example, from the command line you would simply
</p>
<p>

<pre>
  javadoc -doclet net.pcal.propjoe.PropJoeDoclet ... -f my/output/dir/product.properties
</pre>
</p>
<p>
or in Ant using the javadoc ant task:
</p>
<p>
<pre>
    &lt;javadoc packagenames='com.acme.product.*'  
             docletpathref='path.to.propjoe.jar'
                         failonerror='true'>
      &lt;fileset dir='bootstrap/src'>
        &lt;include name='**/PropertyNames.java'/>
      &lt;/fileset>
      &lt;doclet name='net.pcal.propjoe.PropJoeDoclet'>
                 &lt;param name='-f' value='my/output/dir/product.properties'/>
      &lt;/doclet>
    &lt;/javadoc>

</pre>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Create a custom .EXE to launch Tomcat</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2008/01/create-a-custom-exe-to-launch.html" />
    <id>tag:www.pcal.net,2008:/blog//6.411</id>

    <published>2008-01-09T03:20:20Z</published>
    <updated>2008-01-09T03:20:43Z</updated>

    <summary> In developing Ledgerscape, one thing that has become really important is to provide end users 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...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![CDATA[<p>
In developing <a href='http://cfosoft.com/ledgerscape_overview.php'>Ledgerscape</a>, one 
thing that has become really important is to provide end users 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>
<p>
Ledgerscape runs 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>
</entry>

<entry>
    <title>Scriptella 1.0 Beta Released</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2007/11/scriptella-10-beta-released.html" />
    <id>tag:www.pcal.net,2007:/blog//6.410</id>

    <published>2007-11-28T19:19:29Z</published>
    <updated>2007-11-28T19:31:16Z</updated>

    <summary> Fyodor Kupolov has released a 1.0 beta of his Scriptella ETL framework. I downloaded it and integrated it into Ledgerscape, so far so good. I blogged about Scriptella a while ago. It&apos;s a simple and elegant framework for declaratively...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![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
<a href='http://cfosoft.com/ledgerscape_overview.php'>Ledgerscape</a>, so far so good.
</p>

<p>
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 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>
</entry>

<entry>
    <title>Painless Spell Checking in Ant</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2007/11/painless-spell.html" />
    <id>tag:pcal.net,2007:/bleh//6.409</id>

    <published>2007-11-02T22:54:17Z</published>
    <updated>2007-11-20T15:59:17Z</updated>

    <summary>I&apos;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...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="java" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![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>
<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>
</entry>

<entry>
    <title>Scriptella ETL</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2007/07/scriptella-etl.html" />
    <id>tag:pcal.net,2007:/bleh//6.408</id>

    <published>2007-07-21T19:49:36Z</published>
    <updated>2007-11-28T19:18:43Z</updated>

    <summary> 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...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="java" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![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>
<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>
</entry>

<entry>
    <title>Guitar Zero</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2007/06/guitar-zero.html" />
    <id>tag:pcal.net,2007:/bleh//6.407</id>

    <published>2007-06-25T05:29:33Z</published>
    <updated>2007-11-20T15:59:17Z</updated>

    <summary> I thought Guitar Hero was the lamest thing ever - until I actually played it the other day. I loved Parappa the Rappa and GH is just another take on that idea. Then I discovered Frets on Fire: open...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="geekery" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![CDATA[<p>
I thought <a href='http://www.guitarherogame.com'>Guitar Hero</a> was the lamest thing ever - until I actually played it the other day.  I loved 
<a href='http://en.wikipedia.org/wiki/PaRappa_the_Rapper'>Parappa the Rappa</a> and GH is just another take on that idea.
</p>
<p>
Then I discovered <a href='http://fretsonfire.sourceforge.net/'>Frets on Fire</a>: open source community, people contribute hundereds of songs.  So I did one of my own - I attempted to transcribe a short song by one of my old bands.  It was not easy onaccounta the tools are not very good.  (Apologies for the solo in the middle Ralfie - I just couldn't figure it out).
</p>
<p>
Anyway, here it is:  <a href='/stuff/ninepin.zip'>ninepin.zip</a>
</p>
<p>
<center>
<a href='/images/ninepin1.png'>
<img src='/images/ninepin1.png' width='250'/>
</a>
&nbsp;
<a href='/images/ninepin2.png'>
<img src='/images/ninepin2.png' width='250'/>
</a>
</center>
</p>

<p>
<i>
I'm not truly lame until I buy the <a href='/images/ninepin3.jpg'>guitar controller thingie</a> and hook it up to my MacBook.  Which is possible with a PSX/USB adapter.  Not that I am going to get one.
<i>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>No, Let&apos;s Play Global Thermonuclear War</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2007/04/no-lets-play-global.html" />
    <id>tag:pcal.net,2007:/bleh//6.406</id>

    <published>2007-04-20T23:23:29Z</published>
    <updated>2007-11-20T15:59:17Z</updated>

    <summary> The mac port of DEFCON is finally out. It basically takes the last scene from WarGames and makes a real-time strategy game out of it. I&apos;m still figuring out how the game part of it works (I played the...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="geekery" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![CDATA[<p>
The mac port of 
<a href='http://www.ambrosiasw.com/games/defcon'>DEFCON</a>
is finally out. 

<p>
It basically takes the last scene from 
<a href='http://www.imdb.com/title/tt0086567/'>
WarGames</a> 
and makes a real-time strategy game out of it.  I'm still figuring out how the game part of it works (I played the Windows version a while ago), but the unique mood and aesthetics alone justify the purchase - it simply looks and feels like nothing you've ever played before.
</p>

<p>
<center>
<a href='/images/defcon.jpg'><img src='/images/defcon.jpg' /> </a>
</center>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Dynamic Persistence Units in EJB3</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2007/04/dynamic-persist.html" />
    <id>tag:pcal.net,2007:/bleh//6.405</id>

    <published>2007-04-19T18:12:05Z</published>
    <updated>2008-03-18T20:15:19Z</updated>

    <summary> 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...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="java" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![CDATA[<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>
<p>
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. 
</p>
<p>
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.
</p>
<p>
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.
</p>

<p>
<pre>

  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>> 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();
  }
</pre>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Pitchwire is Live</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2007/04/pitchwire-is-li-1.html" />
    <id>tag:pcal.net,2007:/bleh//6.404</id>

    <published>2007-04-07T03:27:48Z</published>
    <updated>2007-11-20T15:59:17Z</updated>

    <summary> My friend Michael&apos;s startup launched this week: http://www.pitchwire.com It&apos;s half a PR service for publicists and half spam control on steroids for journalists. I&apos;m not either one but I think it&apos;s a really great idea. Anything that gives people...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="i heart the interweb" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![CDATA[<p>
My friend Michael's startup launched this week:
</p>

<p>
  <a href='http://www.pitchwire.com'>http://www.pitchwire.com</a>
</p>
<p>It's half a PR service for publicists and half spam control on steroids for journalists.  I'm not either one but I think it's a really great idea.  Anything that gives people more control over what information gets thrown at them gets a thumbs up from me.
</p>
<p>
Michael did a great job on the app.  It's all in Ruby.  Even if you're not journalist, go bang on it and give him some feedback - he'd love to hear from you.
</p>

<center>
<a href='http://www.pitchwire.com'>
<img src='http://www.pitchwire.com/images/small_logo.gif'/>
</a>
</center>]]>
        
    </content>
</entry>

<entry>
    <title>How to Make a Movie in 10 Easy Steps</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2007/03/how-to-make-a-m.html" />
    <id>tag:pcal.net,2007:/bleh//6.403</id>

    <published>2007-03-17T08:52:33Z</published>
    <updated>2007-11-20T15:59:17Z</updated>

    <summary> by Lou Ye Find an attractive female lead who is willing to take her clothes off. A lot. Also, make sure she knows how to French inhale. Shoot various cast members having sex. Shoot various cast members brooding. Shoot...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="film" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![CDATA[<p>
 by Lou Ye 
</p>
<p>
<ol>
  <li>Find an attractive female lead who is willing to take her clothes off. 
      A lot.  Also, make sure she knows how to French inhale.</li>
  <li>Shoot various cast members having sex.</li>
  <li>Shoot various cast members brooding.</li>
  <li>Shoot various cast members smoking.</li>
  <li>Repeat steps 2-4 until you have no more film.</li>
  <li>Edit the footage into the following sequence: brooding, smoking, brooding, brooding, sex, brooding, smoking, sex, brooding, sex, sex, smoking, sex, sex, sex, brooding, brooding, smoking, brooding, sex, brooding, sex, sex, sex, sex, sex, sex, sex, smoking, sex, brooding.</li>
  <li>Add voiceover to the brooding and smoking so that the audience understands
     that the sex is just an expression of how deep and pained the characters are.</li>   
  <li>Watch test print of movie.  Realize just what a 
  <a href='http://www.imdb.com/title/tt0794374/'>
  steaming pile of panda shit</a> you have made.  Panic briefly.</li> 
  <li>Go back and splice in random news clips about Tiananmen Square in 1989.  Do not be surprised when you and your film are banned from China by the Communist Party.</li>
  <li>Watch as resulting controversy carries your film to acclaim at Cannes and 
      other festivals.  Try to contain laughter as festival promoters declare 
      your work a <a href='http://www.asianamericanfilmfestival.org/2007/films-events/film-detail/?i=107'>masterpiece</a>.</li>
</ol>
</p>
<p>
<i>No, I really don't hate everything.  I actually liked his two previous movies.</i>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Private, Pegged Parallels</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2006/12/private-pegged.html" />
    <id>tag:pcal.net,2006:/bleh//6.402</id>

    <published>2006-12-30T23:55:58Z</published>
    <updated>2007-11-20T15:59:17Z</updated>

    <summary> I continue to be extremely impressed with the Parallels VM. However, I just spent an undue amount of time wrestling with Window&apos;s and Parallel&apos;s network configurations in order to achieve a relatively simple result. In the hope of sparing...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="i love apple" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![CDATA[<p> 
I continue to be extremely impressed with the <a href='http://www.parallels.com/en/products/workstation/mac/'>Parallels VM</a>.  However, I just
spent an undue amount of time wrestling with Window's and Parallel's network
configurations in order to achieve a relatively simple result.  In the hope
of sparing someone else out there some wrestling, here's the scoop:
</p>
<p><b>Goal</b></p>
<p>Set up a Parallels VM with Windows XP so that it is isolated from 
the outside world but network addressable from my mac via a fixed address 
(192.168.2.100) and the name 'parallels.'
</p>
<b>
Solution
</b>
<ol>
<li>Set up your parallels VM</li>
<li>In your VM's Network Adapter configuration, choose 'Host-only Networking' for the emulation mode</li>
<li>Go to the DHCP tab of the Parallels application preferences.  Set the DHCP scope to include the desired address.  (I chose start of 192.168.2.1, end 192.168.2.254, subnet mask 255.255.255.0).
<li>Start the VM</li>
<li>In Windows, turn off the firewall.  (Control Panel | Windows Firewall)</li>
<li>In Windows, set the local connection to use a static IP.  (Control Panel | Network Connections | Local Area Connection | Properties... | Internet Protocol | Properties... | Use the following IP Address: 192.168.2.100)</li>
<li>In OS X, open a Terminal.  Type 'ping 192.168.2.100' and make sure you're getting a response.</li>
<li>In OS X, etc/hosts isn't recognized.  In order to put a name on that IP, you have to...
<li>Open Applications/Utilities/NetInfo Manager.  Go to 'machines.'  Create a duplicate of 'localhost'.  Rename it to 'parallels'.  Set 'ip_address' to 192.168.2.100.  Save and quit NetInfo Manager.</li>
<li>Back in Terminal, make sure you can 'ping parallels'.</li>
<li>Fin!</li>
</ol>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Time to dust off the ol&apos; VT100</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2006/12/time-to-dust-of.html" />
    <id>tag:pcal.net,2006:/bleh//6.401</id>

    <published>2006-12-13T10:14:58Z</published>
    <updated>2007-11-20T15:59:17Z</updated>

    <summary> Just stumbled across Charva. I love it. I just wish I could think of a reason to use it....</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="java" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![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>
</entry>

<entry>
    <title>Smile MacBook Users, You&apos;re on Camera!</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2006/12/smile-macbook-u.html" />
    <id>tag:www.pcal.net,2006:/blog//6.400</id>

    <published>2006-12-11T20:11:32Z</published>
    <updated>2007-11-30T23:41:19Z</updated>

    <summary> BROADCASTING LIVE! Scary, huh? It&apos;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...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="i hate apple" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![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>
</entry>

<entry>
    <title>Java Web Frameworks: the Good, the Bad, and the Ugly</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2006/12/java-web-framew.html" />
    <id>tag:pcal.net,2006:/bleh//6.399</id>

    <published>2006-12-04T00:44:03Z</published>
    <updated>2007-11-20T15:59:17Z</updated>

    <summary> There have been a million blog postings this year weighing the pros and cons of the various web frameworks now available. It&apos;s a bit overwhelming to wade through it all, so I&apos;m going to try to provide a nutshell...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="java" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![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>
</entry>

<entry>
    <title>Jumped the Battlestar?</title>
    <link rel="alternate" type="text/html" href="http://www.pcal.net/blog/2006/11/jumped-the-batt-1.html" />
    <id>tag:pcal.net,2006:/bleh//6.398</id>

    <published>2006-11-29T17:09:27Z</published>
    <updated>2007-11-20T15:59:17Z</updated>

    <summary>&quot;So, um, there are these robots that come and destroy almost all of the humans on the other side of the galaxy. But a few humans get away on a big spaceship and the show is basically about them running...</summary>
    <author>
        <name></name>
        <uri>http://www.pcal.net</uri>
    </author>
    
        <category term="geekery" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.pcal.net/blog/">
        <![CDATA[<p><i>"So, um, there are these robots that come and destroy almost all of the humans on the other side of the galaxy.  But a few humans get away on a big spaceship and the show is basically about them running away from the robots and...but yeah, no - it's really really good.  No, it's really nothing like Star Trek.  Um, yeah, really, you should check it out.  I even have the DVDs"</i></p>

<p>That's pretty much how a fan of <a href='http://www.battlestargalactica.com/'>Battlestar Galactica</a> sounds when trying to convince a friend to watch it.  After giving the clumsy spiel myself for a while, I've lately had the pleasure of hearing other people stumble through it.</p>

<p>But BSG really is hands down the best TV sci-fi ever, and I'd be willing to make the case that it's some of the best dramatic  writing on TV in any genre.  It isn't about spaceships and robots; it's about 9/11, Iraq and Guantanamo Bay.  Really.  I'm often amazed that the show doesn't make headlines for the boldness of the subject matter.</p>

<p>But while it's bold, it's also subtle. There is no preaching.  There is no editorializing.  The writers simply say "here is the world, it's very complex, you figure out what to think about it."  It's so refreshing - that mode is almost completely absent from political and cultural discourse in 21st century America.   Maybe it's no surprise that you have to go to outer space to find it.</p>

<p>...</p>

<p>Unfortunately, as I write this, I am also wondering if the show has jumped the shark.  I recently caught up on a episode 7 of the current season, and it was just plain bad.  Laden with possibilities, it landed with a thud.  It's the first time I've felt like the writers have lost sight of where  they are going.  Here's hoping it's a blip and not a trend.</p>

<p>If you haven't watched, it might be time to start now before things start going downhill.  (And you do have to watch it from the beginning or you will be very lost).</p>]]>
        
    </content>
</entry>

</feed>
